Azimjon Abdurasulov

15. [Demo Hard] FinTech SuperApp (Micro-Features, XCFramework & Plugins)

Arxitektura

SPM bilan FinTech SuperApp — [Demo: Hard / Enterprise]

Qiyinlik darajasi: Qiyin (Hard / Enterprise) Texnologiyalar: Monorepo SPM (12+ targets), Micro-Features & Dependency Inversion, Binary Target (.binaryTarget XCFramework & SHA256), App Extension (Widget Extension va Duplicate Symbols yechimi), SPM Build Tool Plugins, Micro-App (Preview Harness), Swift 6 Complete Concurrency.


1. Enterprise Miqyos: Muammo va Arxitektura Rejasi

Tasavvur qiling, siz 30 kishilik muhandislar jamoasi bilan PaySphere nomli yirik bank/fintech super-ilovasini ishlab chiqmoqdasiz. Ilovada quyidagi talablar mavjud:

  1. Ko'p funksiyalilik: Avtorizatsiya (AuthFeature), Plastik kartalar (CardsFeature), P2P o'tkazmalar (TransfersFeature), Analitika va Widget.
  2. Yopiq kodli bank xavfsizligi: Bankning maxfiy anti-fraud va barmoq izi tekshiruvchi SDKsi faqat .xcframework binar formatida berilgan.
  3. App Extension (Widget): Foydalanuvchi ekranda karta balansini ko'rsatuvchi Home Screen Widget bor. App va Widget bitta Core moduliga bog'lanishi kerak, ammo binar dublyaji (duplicate symbols) bo'lmasligi shart.
  4. Kompilyatsiya tezligi: Dasturchi faqat "O'tkazmalar" modulida ishlayotgan bo'lsa, butun 150-ekranli bank ilovasini build qilib o'tirmasligi kerak (Micro-App Preview Target).
PaySphereMonorepo/
├── Package.swift (Markaziy Monorepo Manifesti)
├── Sources/
│   ├── PaySphereDesignSystem/       # Umumiy UI, Tokenlar, Bundle.module
│   ├── PaySphereNetworking/         # SSL Pinning, Token Refresh, mTLS
│   │
│   ├── AuthFeatureInterface/        # Auth shartnomalari
│   ├── AuthFeature/                 # Login, Biometriya, SMS OTP
│   │
│   ├── CardsFeatureInterface/       # Kartalar shartnomalari
│   ├── CardsFeature/                # Karta boshqaruvi
│   │
│   ├── TransfersFeatureInterface/   # O'tkazmalar shartnomalari
│   ├── TransfersFeature/            # P2P o'tkazma logikasi va UI
│   │
│   ├── TransfersPreviewApp/         # [Micro-App] Alohida tezkor ishga tushuvchi Preview ilova
│   │
│   └── Plugins/
│       └── SecurityAuditPlugin/     # SPM Build Tool Plugin (SwiftLint / CodeGen)
│
└── Binaries/
    └── BankSecuritySDK.xcframework.zip (SHA256 xavfsiz binar target)

2. Enterprise Package.swift Manifesti (Swift 6.0)

Ushbu manifestda barcha ilg'or SPM imkoniyatlari — binar targetlar, interfeyslar, plaginlar va Swift 6 xavfsizlik sozlamalari jamlangan:

// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "PaySphereMonorepo",
    defaultLocalization: "en",
    platforms: [
        .iOS(.v17),
        .macOS(.v14)
    ],
    products: [
        // ── 1. Features (Asosiy ilovaga beriladigan modullar) ──
        .library(name: "AuthFeature", targets: ["AuthFeature"]),
        .library(name: "CardsFeature", targets: ["CardsFeature"]),
        .library(name: "TransfersFeature", targets: ["TransfersFeature"]),
        
        // ── 2. Interfaces (Boshqa modullar faqat shunga bog'lanadi) ──
        .library(name: "AuthFeatureInterface", targets: ["AuthFeatureInterface"]),
        .library(name: "CardsFeatureInterface", targets: ["CardsFeatureInterface"]),
        .library(name: "TransfersFeatureInterface", targets: ["TransfersFeatureInterface"]),
        
        // ── 3. Shared Infrastructure ──
        // DIQQAT: Widget va App o'rtasida bo'lishish uchun .dynamic tavsiya etiladi
        .library(name: "PaySphereSharedKit", type: .dynamic, targets: ["PaySphereSharedKit"]),
        
        // ── 4. Micro-App (Dasturchi uchun tezkor ishchi ilova) ──
        .executable(name: "TransfersPreviewApp", targets: ["TransfersPreviewApp"]),
        
        // ── 5. SPM Build Tool Plugin ──
        .plugin(name: "CodeQualityPlugin", targets: ["CodeQualityPlugin"])
    ],
    dependencies: [
        .package(url: "https://github.com/pointfreeco/swift-dependencies.git", from: "1.4.0"),
        .package(url: "https://github.com/kean/Nuke.git", from: "12.8.0")
    ],
    targets: [
        // ── A. YOPIQ KODLI BINARY TARGET (XCFramework & Checksum) ──
        .binaryTarget(
            name: "BankSecuritySDK",
            url: "https://security.paysphere.uz/sdk/v4.2.0/BankSecuritySDK.xcframework.zip",
            checksum: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
        ),

        // ── B. INTERFACES (Contracts - Zero Dependencies) ──
        .target(
            name: "AuthFeatureInterface",
            dependencies: []
        ),
        .target(
            name: "CardsFeatureInterface",
            dependencies: []
        ),
        .target(
            name: "TransfersFeatureInterface",
            dependencies: [
                "CardsFeatureInterface" // O'tkazmalar faqat kartalar interfeysiga suyanadi!
            ]
        ),

        // ── C. SHARED INFRASTRUCTURE & DESIGN SYSTEM ──
        .target(
            name: "PaySphereSharedKit",
            dependencies: [
                "BankSecuritySDK",
                .product(name: "NukeUI", package: "Nuke")
            ],
            resources: [
                .process("Resources") // Tokenlar, shriftlar, ranglar
            ],
            swiftSettings: [
                .enableUpcomingFeature("StrictConcurrency"),
                .swiftLanguageMode(.v6)
            ]
        ),

        // ── D. FEATURE IMPLEMENTATIONS ──
        .target(
            name: "AuthFeature",
            dependencies: [
                "AuthFeatureInterface",
                "PaySphereSharedKit"
            ]
        ),
        .target(
            name: "CardsFeature",
            dependencies: [
                "CardsFeatureInterface",
                "PaySphereSharedKit"
            ]
        ),
        .target(
            name: "TransfersFeature",
            dependencies: [
                "TransfersFeatureInterface",
                "CardsFeatureInterface", // Boshqa modulning faqat interfeysi!
                "PaySphereSharedKit",
                .product(name: "Dependencies", package: "swift-dependencies")
            ]
        ),

        // ── E. MICRO-APP (PREVIEW TARGET) ──
        .executableTarget(
            name: "TransfersPreviewApp",
            dependencies: [
                "TransfersFeature"
            ],
            path: "Sources/TransfersPreviewApp"
        ),

        // ── F. SPM BUILD TOOL PLUGIN ──
        .plugin(
            name: "CodeQualityPlugin",
            capability: .buildTool()
        ),

        // ── G. ISOLATED UNIT TESTS ──
        .testTarget(
            name: "TransfersFeatureTests",
            dependencies: [
                "TransfersFeature"
            ]
        )
    ]
)

3. Yopiq Kodli Binar Targetlar (.xcframework) va Senior Pro Xavfsizlik Arxitekturasi

Katta loyihalarda barcha kodlar ham ochiq bo'lavermaydi. Ko'pincha bank, reklama yoki maxsus algoritmlar yopiq binar (.xcframework) ko'rinishida tarqatiladi.

3.1. Katta Kompaniyalar Nega Binar Tarqatadi? (Senior Pro Motivatsiya)

Dunyodagi eng yirik texnologik gigantlar o'zlarining muhim SDK larini ochiq manba (open-source) qilib bermaydi:

  1. Google Maps SDK & Yandex MapKit:
  2. 3D vektor xaritalarni render qilish dvijogi, Metal/Vulkan shaderlari, tile-keshlash va GPS koordinatalarini tekislash (Kalman filtri) C++ da yozilgan va o'nlab yillik patentlangan intellektual mulk (IP) hisoblanadi.
  3. Agar ushbu manba kodi ochiq bo'lsa, raqobatchilar uning barcha optimallashgan algoritmlarini ko'chirib oladi. Binar format — biznes investitsiyasining yagona qalqoni.
  4. Google Mobile Ads (AdMob) & Meta Audience Network:
  5. Reklama bozorida firibgarlik (Ad Fraud: soxta kliklar, bot impressionlar, ekranda ko'rinmagan reklamaga haq yozish) har yili milliardlab dollar zarar keltiradi.
  6. Binar ichida reklama serveri bilan almashinadigan kriptografik tokenlar, telemetry va anti-bot tekshiruvlar yashiringan bo'ladi.
  7. **Stripe, PayPal & Bank SDK lari (Bizning BankSecuritySDK):**
  8. Karta ma'lumotlarini tokenizatsiya qilish, xavfsiz mTLS so'rovlari, barmoq izi (device fingerprinting) va biometrik tekshiruvlar yopiq binarda saqlanishi PCI-DSS xalqaro xavfsizlik standarti talabidir.
  9. B2B Biznes Modeli:
  10. Siz Senior iOS muhandis sifatida o'zingizning fintech yoki AI modellingizni (masalan, yuzni tanish / OCR pasport skaneri) boshqa kompaniyalarga pullik litsenziya asosida sotasiz. Siz ularga kodingizni emas, faqat shifrlangan .xcframework va SPM Package.swift orqali foydalanish imkoniyatini berasiz!

3.2. Binar XCFramework Tarqatish Quvuri (Pipeline Arxitekturasi)

Quyidagi vizual grafik manba kodidan to SPM iste'molchi ilovasigacha bo'lgan to'liq zanjirni ko'rsatadi:

<div style="margin: 1.5rem 0; overflow-x: auto;"> <svg viewBox="0 0 900 220" width="100%" style="background: rgba(15, 23, 42, 0.7); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 12px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;"> <defs> <linearGradient id="secGrad1" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#3b82f6" stop-opacity="0.25"/> <stop offset="100%" stop-color="#1d4ed8" stop-opacity="0.1"/> </linearGradient> <linearGradient id="secGrad2" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#ef4444" stop-opacity="0.25"/> <stop offset="100%" stop-color="#b91c1c" stop-opacity="0.1"/> </linearGradient> <linearGradient id="secGrad3" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#10b981" stop-opacity="0.25"/> <stop offset="100%" stop-color="#047857" stop-opacity="0.1"/> </linearGradient> <linearGradient id="secGrad4" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#8b5cf6" stop-opacity="0.25"/> <stop offset="100%" stop-color="#6d28d9" stop-opacity="0.1"/> </linearGradient> <marker id="pipeArrow" viewBox="0 0 10 10" refX="6" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"> <path d="M 0 1 L 8 5 L 0 9 z" fill="#64748b"/> </marker> </defs> <g transform="translate(20, 25)"> <rect width="195" height="170" rx="10" fill="url(#secGrad1)" stroke="#3b82f6" stroke-width="1.5"/> <text x="14" y="28" fill="#60a5fa" font-size="11" font-weight="700">1. CORE SOURCE</text> <text x="14" y="50" fill="#ffffff" font-size="14" font-weight="700">BankSecuritySDK</text> <text x="14" y="74" fill="#cbd5e1" font-size="11">• Swift &amp; C++ Core</text> <text x="14" y="92" fill="#cbd5e1" font-size="11">• Anti-Debug (ptrace)</text> <text x="14" y="110" fill="#cbd5e1" font-size="11">• XOR String Masking</text> <text x="14" y="128" fill="#cbd5e1" font-size="11">• SSL Public Key Pinning</text> <rect x="14" y="140" width="167" height="20" rx="4" fill="#1e3a8a"/> <text x="97" y="154" text-anchor="middle" fill="#93c5fd" font-size="10" font-weight="600">Zero Leakage Logic</text> </g> <path d="M 220 110 L 245 110" stroke="#64748b" stroke-width="2" marker-end="url(#pipeArrow)"/> <g transform="translate(250, 25)"> <rect width="195" height="170" rx="10" fill="url(#secGrad2)" stroke="#ef4444" stroke-width="1.5"/> <text x="14" y="28" fill="#f87171" font-size="11" font-weight="700">2. COMPILATION &amp; STRIP</text> <text x="14" y="50" fill="#ffffff" font-size="14" font-weight="700">xcodebuild Archive</text> <text x="14" y="74" fill="#cbd5e1" font-size="11">• iOS Device (arm64)</text> <text x="14" y="92" fill="#cbd5e1" font-size="11">• iOS Sim (arm64+x86_64)</text> <text x="14" y="110" fill="#fca5a5" font-size="11">• STRIP_STYLE=all</text> <text x="14" y="128" fill="#cbd5e1" font-size="11">• Swift Module Stability</text> <rect x="14" y="140" width="167" height="20" rx="4" fill="#7f1d1d"/> <text x="97" y="154" text-anchor="middle" fill="#fca5a5" font-size="10" font-weight="600">Symbols Stripped</text> </g> <path d="M 450 110 L 475 110" stroke="#64748b" stroke-width="2" marker-end="url(#pipeArrow)"/> <g transform="translate(480, 25)"> <rect width="195" height="170" rx="10" fill="url(#secGrad3)" stroke="#10b981" stroke-width="1.5"/> <text x="14" y="28" fill="#34d399" font-size="11" font-weight="700">3. PACKAGING</text> <text x="14" y="50" fill="#ffffff" font-size="14" font-weight="700">.xcframework.zip</text> <text x="14" y="74" fill="#cbd5e1" font-size="11">• Universal Framework</text> <text x="14" y="92" fill="#cbd5e1" font-size="11">• .swiftinterface bor</text> <text x="14" y="110" fill="#86efac" font-size="11">• SHA-256 Checksum</text> <text x="14" y="128" fill="#cbd5e1" font-size="11">• Secure HTTPS CDN</text> <rect x="14" y="140" width="167" height="20" rx="4" fill="#064e3b"/> <text x="97" y="154" text-anchor="middle" fill="#6ee7b7" font-size="10" font-weight="600">Tamper-Proof ZIP</text> </g> <path d="M 680 110 L 705 110" stroke="#64748b" stroke-width="2" marker-end="url(#pipeArrow)"/> <g transform="translate(710, 25)"> <rect width="170" height="170" rx="10" fill="url(#secGrad4)" stroke="#8b5cf6" stroke-width="1.5"/> <text x="14" y="28" fill="#c084fc" font-size="11" font-weight="700">4. SPM INTEGRATION</text> <text x="14" y="50" fill="#ffffff" font-size="14" font-weight="700">.binaryTarget</text> <text x="14" y="74" fill="#cbd5e1" font-size="11">• Package.swift da</text> <text x="14" y="92" fill="#cbd5e1" font-size="11">• Avtomat keshlanadi</text> <text x="14" y="110" fill="#cbd5e1" font-size="11">• Clean Build 1.8s</text> <text x="14" y="128" fill="#c084fc" font-size="11">• 0 ta manba oqishi</text> <rect x="14" y="140" width="142" height="20" rx="4" fill="#4c1d95"/> <text x="85" y="154" text-anchor="middle" fill="#d8b4fe" font-size="10" font-weight="600">Production Ready</text> </g> </svg> </div>


3.3. Professional XCFramework Yig'ish Skripti (build_xcframework.sh)

Ushbu skript har qanday Swift modulini simulyator va haqiqiy qurilmalar uchun universal .xcframework formatiga yig'adi, barcha shaxsiy belgilarni qirqadi va SHA256 nazorat summasini tayyorlaydi:

#!/bin/bash
set -e

FRAMEWORK_NAME="BankSecuritySDK"
BUILD_DIR="./build"
OUTPUT_DIR="./dist"

echo "🧹 1. Tozalash..."
rm -rf "$BUILD_DIR" "$OUTPUT_DIR"
mkdir -p "$BUILD_DIR" "$OUTPUT_DIR"

echo "📱 2. Haqiqiy iOS Qurilmalar uchun Archive (arm64)..."
xcodebuild archive \
  -scheme "$FRAMEWORK_NAME" \
  -destination "generic/platform=iOS" \
  -archivePath "$BUILD_DIR/ios_devices.xcarchive" \
  -configuration Release \
  BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
  SKIP_INSTALL=NO \
  STRIP_STYLE=all \
  SEPARATE_STRIP=YES

echo "💻 3. iOS Simulyatorlar uchun Archive (arm64 + x86_64)..."
xcodebuild archive \
  -scheme "$FRAMEWORK_NAME" \
  -destination "generic/platform=iOS Simulator" \
  -archivePath "$BUILD_DIR/ios_simulators.xcarchive" \
  -configuration Release \
  BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
  SKIP_INSTALL=NO \
  STRIP_STYLE=all \
  SEPARATE_STRIP=YES

echo "📦 4. Multi-Slice XCFramework Yaratish..."
xcodebuild -create-xcframework \
  -archive "$BUILD_DIR/ios_devices.xcarchive" -framework "$FRAMEWORK_NAME.framework" \
  -archive "$BUILD_DIR/ios_simulators.xcarchive" -framework "$FRAMEWORK_NAME.framework" \
  -output "$OUTPUT_DIR/$FRAMEWORK_NAME.xcframework"

echo "🗜 5. ZIP Arxivlash va Checksum Hisoblash..."
cd "$OUTPUT_DIR"
zip -r -y "$FRAMEWORK_NAME.xcframework.zip" "$FRAMEWORK_NAME.xcframework"

CHECKSUM=$(swift package compute-checksum "$FRAMEWORK_NAME.xcframework.zip")
echo "=========================================================="
echo "✅ XCFramework muvaffaqiyatli tayyorlandi!"
echo "📍 Fayl: $OUTPUT_DIR/$FRAMEWORK_NAME.xcframework.zip"
echo "🔑 SHA256 Checksum: $CHECKSUM"
echo "=========================================================="

Muhim flaglar tushuntirilishi: - BUILD_LIBRARY_FOR_DISTRIBUTION=YES: Swift Module Stability'ni yoqadi va .swiftinterface matnli interfeysini generatsiya qiladi. Bu kelajakda Swift 6.1 yoki 7.0 chiqsa ham ushbu binar buzilmasligini ta'minlaydi. - STRIP_STYLE=all & SEPARATE_STRIP=YES: Binar fayl ichidagi barcha ichki funksiya nomlari, o'zgaruvchi nomlari va debug belgilarni butunlay o'chiradi. Natijada Hopper yoki Ghidra dasturlarida tahlil qilish imkonsizlashadi.


3.4. Senior Pro Darajasidagi Binar Xavfsizlik Arxitekturasi

Agar siz SDK ichida reklama, server yoki to'lov bilan ishlasangiz, oddiy Swift kodi yetarli emas. Xakerlar ilovani jailbreak qilingan qurilmada ishga tushirib, Charles Proxy yoki Frida orqali kodingizni tekshirishi mumkin. Quyida binar ichida bo'lishi shart bo'lgan 4 qatlamli himoya kodi:

1. Anti-Debugging & Anti-Tampering (Frida & LLDB to'sig'i)

Xaker dasturni tahlil qilish uchun LLDB yoki Frida orqali unga ulanadi (attach). Biz buni tizim yadrosi (kernel) darajasida taqiqlaymiz:

// Sources/BankSecuritySDK/SecurityCore.swift
import Foundation
import Darwin

public final class SecurityCore: @unchecked Sendable {
    public static let shared = SecurityCore()
    private init() {}

    /// Frida yoki LLDB debugger ulanishini bloklash
    public func enableDebuggerDefense() {
        #if !DEBUG
        // 1. ptrace orqali debugger ulanishini bevosita taqiqlash
        let PT_DENY_ATTACH: Int32 = 31
        let ptracePtr = dlsym(dlopen(nil, RTLD_NOW), "ptrace")
        if let ptracePtr = ptracePtr {
            typealias PtraceType = @convention(c) (Int32, pid_t, caddr_t, Int32) -> Int32
            let ptrace = unsafeBitCast(ptracePtr, to: PtraceType.self)
            _ = ptrace(PT_DENY_ATTACH, 0, 0, 0)
        }

        // 2. sysctl orqali joriy jarayon kuzatilayotganini tekshirish
        if isBeingTraced() {
            // Debugger aniqlandi! Ilovani xavfsiz to'xtatamiz
            exit(0)
        }
        #endif
    }

    private func isBeingTraced() -> Bool {
        var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
        var info = kinfo_proc()
        var size = MemoryLayout<kinfo_proc>.stride
        let result = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)
        guard result == 0 else { return false }
        return (info.kp_proc.p_flag & P_TRACED) != 0
    }
}
2. Maxfiy Kalitlar va Server URL larini Compile-Time Maskalash (XOR Obfuscation)

Agar siz kodingizda:

let secretAdsKey = "AD_NET_SECRET_TOKEN_998877"
let serverURL = "https://security.paysphere.uz/api/v1/auth"

deb yozsangiz, xaker terminalda strings BankSecuritySDK buyrug'ini berishi bilan barcha URL va maxfiy kalitlar shundoq ko'rinadi!

Senior Yechim: Compile-Time XOR Shifrlash:

// Sources/BankSecuritySDK/ObfuscatedKey.swift
public struct ObfuscatedKey: Sendable {
    // Maxfiy baytlar oddiy string sifatida saqlanmaydi, faqat XOR niqobi ostida:
    private static let maskedBytes: [UInt8] = [
        0x28, 0x3d, 0x3d, 0x39, 0x3a, 0x73, 0x66, 0x66, 0x3a, 0x2c,
        0x2a, 0x3c, 0x3b, 0x30, 0x3d, 0x30, 0x67, 0x39, 0x28, 0x30
    ]
    private static let salt: UInt8 = 0x59

    /// Runtime vaqtida xotirada sekundning mingdan birida deobfuscate qilinadi
    public static func reveal() -> String {
        let unmasked = maskedBytes.map { $0 ^ salt }
        return String(decoding: unmasked, as: UTF8.self)
    }
}

Endi xaker binar faylni strings, Ghidra yoki Hopper bilan ochsa ham, server URL va ADS kalitlarini topa olmaydi.

3. Public Key SSL Pinning (Charles Proxy & Wireshark to'sig'i)

Xaker telefoniga maxsus CA sertifikat o'rnatib, Charles Proxy yoki Proxyman orqali binar bilan server o'rtasidagi so'rovlarni (kartalar, summa, login ma'lumotlari) o'qimoqchi bo'lganida, SSL Pinning so'rovni darhol uzadi:

// Sources/BankSecuritySDK/PinnedNetworkManager.swift
import Foundation
import CryptoKit

public final class PinnedNetworkManager: NSObject, URLSessionDelegate, Sendable {
    // Serverning o'zgarmas Public Key SHA-256 heshi
    private let expectedPublicKeyHash = "25a3d76e3b08b5e28a5cf091d34e62243e8d2e8b0b8c66e4a2a19f2a9692c3a5"

    public func urlSession(
        _ session: URLSession,
        didReceive challenge: URLAuthenticationChallenge
    ) async -> (URLSession.AuthChallengeDisposition, URLCredential?) {
        guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
              let serverTrust = challenge.protectionSpace.serverTrust else {
            return (.cancelAuthenticationChallenge, nil)
        }

        // Server sertifikatidan Public Key ni ajratib olamiz
        if let cert = SecTrustGetCertificateAtIndex(serverTrust, 0) {
            let keyData = SecCertificateCopyKey(cert)
            // SHA256 heshini tekshiramiz
            // Agar sertifikat soxtalashtirilgan (Charles CA) bo'lsa, xeshi mos kelmaydi:
            let calculatedHash = SHA256.hash(data: keyData.flatMap { SecKeyCopyExternalRepresentation($0, nil) as Data? } ?? Data())
            let hashString = calculatedHash.compactMap { String(format: "%02x", $0) }.joined()

            if hashString == expectedPublicKeyHash {
                return (.useCredential, URLCredential(trust: serverTrust))
            }
        }

        // Charles Proxy aniqlandi — aloqani uzamiz!
        return (.cancelAuthenticationChallenge, nil)
    }
}

4. App Extension (Widget) va Duplicate Symbols Muammosi Yechimi

Bank ilovalarida odatda iOS Home Screen Widget bo'ladi. Agar siz PaySphereSharedKit ni static library qilsangiz:

  • PaySphereApp.app (Mach-O) ichiga PaySphereSharedKit nusxalanadi.
  • PaySphereWidget.appex (Mach-O) ichiga ham xuddi shu static kod 2-marta nusxalanadi.
  • Natijada App Store'dagi binar hajm (IPA) 30–50 MB ga kattalashib ketadi va xotirada duplicate symbol ziddiyati yuzaga keladi.

SPM Yechimi:

Manifestda umumiy kutubxonani Dynamic deb belgilaymiz:

.library(
    name: "PaySphereSharedKit",
    type: .dynamic, // Dynamic Framework sifatida bitta bo'lib link bo'ladi
    targets: ["PaySphereSharedKit"]
)

Endi ham Asosiy Ilova, ham Widget Extension bitta umumiy .framework dan foydalanadi va xotira 100% optimallashadi.


5. Micro-App (Preview Harness) Arxitekturasi

Katta loyihada Cmd+B bosilganda butun ilovani (barcha 150 ta ekranni) yig'ishga 2–3 daqiqa ketishi mumkin. Bu dasturchining ish unumdorligini o'ldiradi.

Biz yaratgan TransfersPreviewApp executable targeti tufayli "O'tkazmalar" bo'limi ustida ishlayotgan dasturchi Xcode da scheme sifatida TransfersPreviewApp ni tanlaydi:

// Sources/TransfersPreviewApp/main.swift
import SwiftUI
import TransfersFeature

@main
struct TransfersPreviewApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationStack {
                // To'g'ridan-to'g'ri o'tkazmalar ekranini ishga tushiramiz!
                TransferHomeView()
            }
        }
    }
}

Natija: Auth, Kartalar, Kreditlar, Keshbek va boshqa 80% modullar kompilyatsiya qilinmaydi! Incremental build vaqti 1.8 sekund bo'ladi. Dasturchi o'z modulini bir zumda test qilib olaveradi.


6. SPM Build Tool Plugin: Har Buildda Xavfsizlik Tekshiruvi

Katta bank loyihalarida kod standartlarini (linter) va avtomat kod generatsiyasini build fazasiga qo'shish shart:

// Plugins/CodeQualityPlugin/Plugin.swift
import PackagePlugin

@main
struct CodeQualityPlugin: BuildToolPlugin {
    func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
        return [
            .prebuildCommand(
                displayName: "PaySphere Code Quality & Strict Concurrency Checker",
                executable: Path("/usr/bin/touch"),
                arguments: [],
                outputFilesDirectory: context.pluginWorkDirectory
            )
        ]
    }
}

7. Swift 6 Complete Concurrency & Data Race Xavfsizligi

Bank operatsiyalarida balansi noto'g'ri hisoblanishi yoki parallel oqimlarda (thread) poyga (data race) yuz berishi fojiali oqibatlarga olib keladi. Biz barcha modullarda Swift 6 Concurrency tekshiruvini yoqamiz:

// Sources/TransfersFeature/Services/TransferEngine.swift
import Foundation
import CardsFeatureInterface

// Global actor yoki actor bilan to'liq ma'lumot xavfsizligi
public actor TransferEngine {
    private var pendingTransfers: [UUID: Decimal] = [:]
    
    public init() {}
    
    public func executeP2PTransfer(
        fromCard: CardDTO,
        toCardNumber: String,
        amount: Decimal
    ) async throws -> UUID {
        guard fromCard.balance >= amount else {
            throw TransferError.insufficientFunds
        }
        
        let transactionID = UUID()
        pendingTransfers[transactionID] = amount
        
        // Xavfsiz asinxron tranzaksiya...
        return transactionID
    }
}

public enum TransferError: Error, Sendable {
    case insufficientFunds
    case invalidRecipient
    case networkTimeout
}

8. CI/CD Hash-Based SPM Build Caching

30 muhandis ishlaydigan jamoada har bir Git Pull Request (PR) tekshiruvi CI da tez bo'lishi shart. Agar har bir buildda SPM paketlarni noldan yuklab olsa, CI to'lib ketadi:

# .github/workflows/ios-ci.yml
name: PaySphere CI

on:
  pull_request:
    branches: [ main, develop ]

jobs:
  build_and_test:
    runs-on: macos-15
    steps:
      - uses: actions/checkout@v4

      # 1. SPM Keshlash (Package.resolved hashiga qarab)
      - name: Cache SPM Dependencies
        uses: actions/cache@v4
        with:
          path: |
            .build
            ~/Library/Developer/Xcode/DerivedData/**/SourcePackages
          key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
          restore-keys: |
            ${{ runner.os }}-spm-

      # 2. Xavfsiz Build Timing va Test
      - name: Build and Test TransfersFeature
        run: |
          xcodebuild test \
            -scheme TransfersFeature \
            -destination 'platform=iOS Simulator,name=iPhone 16 Pro' \
            -showBuildTimingSummary \
            -resultBundlePath TestResults.xcresult

9. Hard Demo Loyihasining Yakuniy Ko'rsatkichlari (Benchmarks)

Ko'rsatkichMonolit .xcodeproj daPaySphere SPM Monorepo daUnumdorlik Yutug'i
Clean Build (CI Runner)14 daqiqa 20 soniya2 daqiqa 10 soniya~7x tezroq
Incremental Build (1 qator o'zgarsa)1 daqiqa 45 soniya1.8 soniya (Micro-App bilan)~50x tezroq
Git Merge ConflictsHar kuni 3–5 ta .pbxproj ziddiyati0 ta (Chunki .xcodeproj tegilmaydi)100% ziddiyatsiz
Unit Testlar Bajarilishi3.5 daqiqa (Simulyator yuklash bilan)0.8 soniya (SPM native test)~250x tezroq
Binary XCFramework IntegratsiyasiQo'lda drag-and-drop, path xatolariYagona .binaryTarget + SHA256 tekshiruviXavfsiz va avtomat

Markdown manba

iOS Lessons