A franchise applicant in Thar or a physician in Houston experiences a single process. The backend orchestrates Musharakah pool formation, Shariah compliance, bank provisioning, APPNA diaspora investment, ZTBL credit, pension fund participation, and franchise deployment through unified API gateways.
Farmer, shopkeeper, women's group → CNIC registration → Pool with neighbors → JazzCash/Easypaisa contribution → Musharakah pool → Franchise funded → Monthly profit via mobile money
Pakistani physician in US → APPNA portal → Select hometown Musharakah pool → Stripe/ACH $500+ → Co-invest with local community → Quarterly returns + social impact report
IsDB, Gulf SWF, pension fund → Due diligence package → Shariah board review → Large-scale Musharakah ($100K-$50M) → Fund 100-10,000 franchise units → Diminishing Musharakah exit
Every user type enters the same funnel. The orchestration engine detects their profile and routes them through the correct backend processes — banking, compliance, pooling, deployment.
User registers via web/mobile/Postal Code Center. Selects: Community Investor Operator APPNA Diaspora Institutional. System captures CNIC (local) or Passport+SSN (diaspora).
Local: CNIC → NADRA e-Sahulat API → Document AI scan → SBP AML check
APPNA: US Passport + SSN → Stripe Identity → OFAC screening → FinCEN compliance
Gulf: Emirates ID → GCC KYC → UAE Central Bank clearance
Institutional: Company registration → LEI verification → Enhanced due diligence
System auto-provisions or links appropriate bank account:
• Islamic bank account (Meezan/BankIslami) for Musharakah pooling
• JazzCash/Easypaisa wallet for micro-investors (PKR 10K-50K)
• Stripe Connect account for APPNA/international
• ZTBL account link for agricultural franchise operators
Investors: Vertex AI matches to pools based on location, risk profile, investment size, preferred sector (cooking, solar, AI kiosk)
Operators: Skills + location + capital → Top 3 franchise type recommendations
APPNA: Hometown zip code → Active pools in home village/city → Social impact score
User selects Musharakah pool. Reviews: target capital, current fill %, profit ratio, franchise type, Shariah certificate, operator profile. Commits capital amount. System validates against pool rules (min/max, geographic restrictions).
Auto-generates trilingual contract (EN/UR/AR) from template. Includes: profit ratios, loss rules, diminishing schedule, Halal clause, dispute resolution. Submitted to Shariah Advisory Board queue. AI pre-screens for compliance (Gemini-powered).
Capital contribution routed through appropriate gateway:
• JazzCash/Easypaisa: USSD or app → PKR 10K-500K → Instant
• Islamic Bank Transfer: IBFT/RTGS → PKR 50K-50M → Same day
• Stripe (APPNA): Card/ACH → $500-$500K → FX conversion at market rate
• Wire (Institutional): SWIFT → $100K-$50M → T+1 settlement
All parties sign digitally. CNIC-verified digital signature for locals. DocuSign/Stripe-verified for international. Shariah advisor counter-signs. Executed contract stored in Cloud Storage. All parties receive PDF copy via SMS/email/WhatsApp.
Pool capital released → Equipment procurement from approved vendors → Operator completes training modules (4-6 weeks) → Equipment installation → Quality inspection → Launch. All tracked in real-time dashboard.
Operator submits monthly report: revenue, expenses, units sold. System auto-calculates net profit. Dashboard shows all investors real-time performance. AI flags anomalies. ZTBL-linked units also report agricultural output.
Quarterly: System calculates distributable profit → Allocates per Musharakah ratio → Deducts Zakat if elected → Routes payment to each partner (JazzCash/bank/Stripe). Diminishing Musharakah: operator's equity unit purchase processed, ownership % updated.
After 3-5 years, operator has purchased all equity units. System: marks pool as COMPLETED, transfers franchise registration to operator, generates ownership certificate (trilingual), notifies all partners of successful exit with final ROI summary.
Every Pakistani bank is a potential Musharakah channel. Islamic banks are primary (Shariah-native), government banks provide infrastructure reach, private banks offer scale, and microfinance enables the lowest income tiers.
| Bank | Branches | Assets 2024 (PKR B) | Islamic Window | API Integration | Musharakah Role |
|---|---|---|---|---|---|
| Meezan Bank 🥇 | 1,000+ | 2,800+ | Full Islamic | ✅ REST API | Primary pool custodian, Musharakah accounts |
| BankIslami | 380+ | 650+ | Full Islamic | ✅ REST API | Rural franchise accounts, micro-Musharakah |
| Dubai Islamic Bank | 250+ | 580+ | Full Islamic | ⚙️ In progress | Gulf investor bridge, AED/PKR settlement |
| Al-Baraka Bank | 200+ | 420+ | Full Islamic | ⚙️ In progress | Bahrain/ME investor gateway |
| MCB Islamic / Faysal | 850+ | 1,200+ | Islamic Division | 🔜 Planned | Mass-market Islamic window Musharakah |
| Bank | Branches | Assets 2015→2024 | Growth | Musharakah Role |
|---|---|---|---|---|
| National Bank (NBP) | 2,150 | 4,800→16,500 B | +123% | Govt scheme disbursement, rural reach |
| Bank of Punjab | 850 | 1,850→8,200 B | +118% | Punjab franchise deployment channel |
| Sindh Bank | 320 | 680→4,100 B | +113% | Sindh/Thar franchise operations |
| Bank of Khyber | 180 | 420→2,800 B | +133% | KPK/tribal areas deployment |
| ZTBL (Zarai Taraqiati) | 500+ | 195B annual | 890K farmers | Agricultural franchise bridge |
HBL (PKR 5.2T) • UBL (3.2T) • MCB (2.8T) • Allied (2.2T) • Bank Alfalah (1.85T) • Standard Chartered • Habib Metro • JS Bank • Askari • Soneri • Summit • Silk • Bank Al-Habib • Samba • KASB
Integration: Open Banking API (SBP RAAST) for IBFT transfers. Private banks serve as secondary investment channels — their Islamic windows route to Musharakah accounts at partner Islamic banks. HBL/UBL provide remittance corridors for APPNA members.
Khushhali Bank • JazzCash (50M users) • Telenor/Easypaisa (40M) • FINCA • U Microfinance • NRSP MFB • Apna • Advans • SadaPay • NayaPay
Integration: JazzCash/Easypaisa APIs for instant investment (PKR 10K min). USSD channel for non-smartphone users. Microfinance banks provide Tier 1-3 household credit bridge — operator can start franchise while Musharakah pool forms.
# ═══════════════════════════════════════════════════════
# BANK GATEWAY ROUTER — Routes to appropriate bank API
# ═══════════════════════════════════════════════════════
from fastapi import APIRouter, Depends
from enum import Enum
class BankChannel(str, Enum):
ISLAMIC = "islamic" # Meezan, BankIslami, Dubai Islamic
GOVERNMENT = "government" # NBP, BoP, Sindh, BoK
ZTBL = "ztbl" # Agricultural loans
PRIVATE = "private" # HBL, UBL, MCB via RAAST
MOBILE = "mobile_money" # JazzCash, Easypaisa
STRIPE = "stripe" # International (APPNA, Gulf)
WIRE = "wire" # Institutional SWIFT
router = APIRouter(prefix="/api/v1/banking", tags=["Banking"])
@router.post("/provision")
async def provision_bank_account(user_id: str, user_type: str, location: dict):
"""Auto-provision appropriate bank channel based on user profile."""
if user_type == "community_investor":
if location["province"] in ["Punjab", "Sindh", "KPK", "Balochistan"]:
# Check if user has Islamic bank account
existing = await check_existing_accounts(user_id)
if not existing:
# Create Meezan Musharakah Pool Account
return await islamic_bank_api.create_musharakah_account(
bank="meezan", user_cnic=user_id, account_type="musharakah_pool"
)
return existing
# Fallback: mobile money for unbanked
return await mobile_money_api.create_wallet(user_id, provider="jazzcash")
elif user_type == "franchise_operator":
# Operators need both: Islamic account + ZTBL link (if agricultural)
islamic = await islamic_bank_api.create_musharakah_account(
bank="bankislami", user_cnic=user_id, account_type="operator"
)
if is_agricultural_franchise(location):
ztbl = await ztbl_api.link_farmer_account(user_id, location)
return {"islamic_account": islamic, "ztbl_account": ztbl}
return {"islamic_account": islamic}
elif user_type == "appna_diaspora":
# Stripe Connect for US-based, with PKR settlement
return await stripe_service.create_connect_account(
user_id=user_id, country="US", currency="usd",
settlement_currency="pkr", kyc_type="appna"
)
elif user_type == "institutional":
# SWIFT/Wire for large transfers
return await wire_gateway.create_institutional_account(
user_id=user_id, expected_volume="high",
currencies=["USD", "SAR", "AED", "PKR"]
)
@router.post("/transfer")
async def process_investment_transfer(
user_id: str, pool_id: str, amount: float,
currency: str = "PKR", channel: BankChannel = None
):
"""Route payment through appropriate bank channel."""
if channel is None:
channel = await auto_detect_channel(user_id, amount, currency)
CHANNEL_MAP = {
BankChannel.ISLAMIC: islamic_bank_api.ibft_transfer,
BankChannel.GOVERNMENT: raast_api.instant_transfer,
BankChannel.ZTBL: ztbl_api.agri_credit_transfer,
BankChannel.MOBILE: mobile_money_api.p2p_transfer,
BankChannel.STRIPE: stripe_service.charge_and_convert,
BankChannel.WIRE: swift_gateway.initiate_transfer,
}
handler = CHANNEL_MAP[channel]
result = await handler(
from_account=user_id, to_pool=pool_id,
amount=amount, currency=currency
)
# Record in double-entry ledger
await ledger_service.record(
debit="1000_cash_" + channel.value,
credit="2000_partner_capital",
amount=amount, pool_id=pool_id, user_id=user_id,
description=f"Capital contribution via {channel.value}"
)
return resultAPPNA (Association of Physicians of Pakistani Descent of North America) represents 55,000+ physicians earning $250K-$1M+ annually. They send $2B+ in remittances yearly. Our platform channels this into structured Musharakah investments in their home communities — not charity, but profitable Shariah-compliant partnerships.
class APPNAGatewayService:
"""Handles all APPNA diaspora investment flows."""
async def register_appna_member(self, appna_id: str, ssn: str, passport: str):
# 1. Verify APPNA membership
member = await appna_sso.verify_membership(appna_id)
if not member.active: raise HTTPException(403, "Inactive APPNA membership")
# 2. US KYC via Stripe Identity
kyc = await stripe_identity.verify(ssn=ssn, passport=passport)
# 3. OFAC/SDN screening (required for US persons)
ofac = await ofac_screening.check(name=member.full_name, dob=member.dob)
if ofac.match: raise HTTPException(403, "OFAC screening flag — manual review")
# 4. Create Stripe Connect account for payouts
stripe_acct = await stripe.create_connect_account(
country="US", type="express",
capabilities={"transfers": {"requested": True}},
metadata={"appna_id": appna_id, "hometown": member.hometown_district}
)
return {"user_id": member.id, "kyc": "verified", "stripe": stripe_acct.id}
async def match_hometown_pools(self, user_id: str):
"""Find Musharakah pools near member's ancestral village."""
member = await get_user(user_id)
hometown = member.profile.hometown_district # e.g., "Rawalpindi"
pools = await pool_service.search(
province=member.profile.hometown_province,
district=hometown,
status="fundraising",
sort_by="proximity_to_hometown"
)
# Enrich with social impact data
for pool in pools:
pool.impact = await impact_service.calculate(pool.id)
pool.family_connections = await find_family_in_pool(user_id, pool.id)
return pools
async def invest_from_us(self, user_id: str, pool_id: str, amount_usd: float):
"""Process USD investment with FX conversion."""
# 1. Charge via Stripe
charge = await stripe.create_charge(
amount=int(amount_usd * 100), currency="usd",
customer=user_id, metadata={"pool_id": pool_id}
)
# 2. FX conversion at SBP market rate
rate = await fx_service.get_rate("USD", "PKR") # e.g., 278.50
amount_pkr = amount_usd * rate.mid
# 3. Transfer PKR to pool's Islamic bank account
transfer = await islamic_bank_api.ibft_transfer(
to_account=pool.bank_account, amount=amount_pkr,
reference=f"APPNA-{user_id}-{pool_id}"
)
# 4. Record in ledger
await ledger_service.record_multi_currency(
debit="1003_cash_stripe_usd", credit="2001_partner_capital_external",
amount_original=amount_usd, currency_original="USD",
amount_pkr=amount_pkr, fx_rate=rate.mid
)
return {"charge_id": charge.id, "pkr_amount": amount_pkr, "fx_rate": rate.mid}ZTBL (Zarai Taraqiati Bank Limited) serves 890,000 farmers with PKR 195B in annual agricultural loans. Our integration creates a bridge: ZTBL agricultural credit + Musharakah equity = farmer becomes franchise operator (food drying, dairy processing, solar) without pure debt.
| ZTBL Loan Type | Portfolio % | Rate | Term | Max Amount | Musharakah Bridge |
|---|---|---|---|---|---|
| Production (فصلی) | 45% | 12-15% | 1 year | Rs. 15 Lakh | Convert to Musharakah → Food drying franchise |
| Development (ترقیاتی) | 25% | 10-14% | 5-7 yrs | Rs. 50 Lakh | Solar induction cooking franchise setup |
| Livestock (مویشی) | 15% | 11-13% | 3-5 yrs | Rs. 25 Lakh | Dairy processing franchise |
| Tractor/Machinery | 10% | 9-12% | 5-7 yrs | Rs. 30 Lakh | Solar installation franchise tools |
| Kissan Card | 5% | 14-16% | Revolving | Rs. 5 Lakh | Micro-franchise starter capital |
Instead of pure interest-based ZTBL loans, we structure a hybrid: ZTBL provides equipment credit (Murabaha — cost-plus sale, Shariah-compliant). Community Musharakah pool provides working capital + training. Farmer operates franchise. ZTBL Murabaha is paid from franchise revenue. Community receives profit share. Farmer owns everything in 3-5 years.
Software: ZTBL API integration reads farmer's credit history, crop data, land records. Auto-qualifies for franchise types matching their agricultural expertise. ZTBL repayment schedule synced with Musharakah distribution calendar.
Pakistan's pension and investment funds hold PKR 1.77 trillion in assets. Currently invested in government bonds (low return) and stocks (volatile). Musharakah in real productive franchises offers a new asset class: asset-backed, Shariah-compliant, direct economic impact.
| Institution | AUM (PKR B) | Annual Allocation | Current Portfolio | Musharakah Allocation Target |
|---|---|---|---|---|
| EOBI (Pension) | 465 | Rs. 50B | Bonds 85%, Stocks 10% | 5% → PKR 23B for franchise Musharakah |
| NIT (Nat'l Investment) | 210 | Rs. 25B | Stocks 70%, Bonds 25% | 10% → PKR 21B for tech Musharakah |
| GPF (Govt Provident) | 280 | Rs. 30B | Govt bonds 100% | 3% → PKR 8.4B pilot allocation |
| Military Funds | 400 | Rs. 50B | Real estate, industry | 2% → PKR 8B franchise + datacenter |
| Benevolent Funds | 131 | Rs. 15B | Bonds, deposits | 5% → PKR 6.5B social impact |
| Akhuwat Foundation | 280 | Rs. 35B | Interest-free loans | Natural partner — 0% interest aligned |
| NRSP / Rural Support | — | Rs. 15B | Community lending | Field operations partner |
| TOTAL TARGET | 1,766+ | PKR 67B addressable in Year 1-3 |
Each of Pakistan's 50M households maps to an income tier. Each tier has a different Musharakah entry point, franchise type, and bank channel. The software auto-routes based on declared income and investment capacity.
| Tier | Monthly Income | Investment | Franchise Type | Bank Channel | Musharakah Model | Households |
|---|---|---|---|---|---|---|
| 🔴 Tier 1 | PKR 30,000 | PKR 20,000 | Food drying (micro) | JazzCash/Easypaisa | Community pool (mosque) | 15M |
| 🟠 Tier 2 | PKR 50,000 | PKR 40,000 | Induction cooking | Microfinance + mobile | Women's group pool | 12M |
| 🟡 Tier 3 | PKR 75,000 | PKR 80,000 | Solar installation | BankIslami | Village development pool | 10M |
| 🟢 Tier 4 | PKR 100,000 | PKR 125,000 | Dairy processing | Meezan + ZTBL | Bazaar merchant pool | 7M |
| 🔵 Tier 5 | PKR 150,000 | PKR 250,000 | AI kiosk + digital | Meezan/Private Islamic | University innovation pool | 4M |
| 🟣 Tier 6 | PKR 200,000 | PKR 500,000 | Multi-unit franchise | HBL/UBL Islamic window | District-level pool | 1.5M |
| 💎 Tier 7 | PKR 300,000 | PKR 1,000,000 | NoCodeAI platform | Private bank + Stripe | Provincial/diaspora pool | 500K |
When user registers and declares income, the system automatically: (1) assigns income tier, (2) calculates max investment capacity, (3) filters franchise types within budget, (4) selects appropriate bank channel, (5) recommends matching Musharakah pools, (6) generates tier-appropriate contract with scaled profit ratios. Tier 1-2 users get Urdu-first UI with voice guidance. Tier 5-7 get English dashboard with advanced analytics.
These are the 8 core processes that make the single-journey possible. Each runs as an independent microservice on Cloud Run, communicating via Pub/Sub events.
Accepts registration from web, mobile, USSD, or postal code center. Detects user type. Routes to appropriate KYC flow. Stores verified profile in Firestore. Triggers bank provisioning.
Provisions bank accounts. Routes investment transfers. Handles multi-channel payments (Islamic IBFT, mobile money, Stripe, SWIFT). Manages FX conversion. Settlement reconciliation.
Creates Musharakah pools. Validates parameters (min/max capital, profit ratios, geographic restrictions). Tracks capital commitments. Manages pool lifecycle (fundraising → active → distributing → completed). Handles multi-source capital aggregation.
AI pre-screening of contracts (Gemini). Human review queue for Shariah board. Rule-based validation (profit/loss ratios, Halal activities, transparency). Certificate generation. Ongoing transaction monitoring.
Generates trilingual contracts (EN/UR/AR) from templates. Injects pool-specific terms, partner details, financial schedules. PDF rendering via WeasyPrint. E-signature workflow. Version control for amendments.
Manages franchise lifecycle from funded → training → procurement → installation → launch → operating. Tracks equipment, vendor payments, training completion, quality inspections. Links to ZTBL for agricultural franchises.
Quarterly automated calculation. Multi-gateway payout (JazzCash for local, Stripe for APPNA, IBFT for bank-linked). Diminishing Musharakah equity updates. Zakat deduction. Tax reporting for US investors. BigQuery analytics.
APPNA SSO integration. US/UK/Gulf KYC. OFAC/FinCEN compliance. Stripe Connect for payouts. Hometown matching algorithm. Social impact dashboard. Tax document generation (K-1 equivalent). Annual convention integration.
# ═══════════════════════════════════════════ # GCP PROJECT: musharakah-franchise-platform # REGION: asia-south1 (Mumbai — closest to PK) # ═══════════════════════════════════════════ # Cloud Run Services (9 microservices) # ────────────────────────────────────── # 1. auth-service → Firebase Auth + RBAC + KYC routing # 2. banking-gateway → 40+ bank API integrations # 3. musharakah-engine → Pool CRUD, partner mgmt, capital tracking # 4. franchise-engine → Unit lifecycle, operator mgmt, training # 5. contract-engine → Template rendering, PDF gen, e-signatures # 6. financial-engine → Ledger, profit calc, distributions, Zakat # 7. ai-engine → Vertex AI matching, Gemini compliance # 8. appna-gateway → APPNA SSO, US compliance, Stripe Connect # 9. notification-engine → SMS (Twilio), Email, WhatsApp, FCM push # Data Layer # ────────────────────────────────────── # Firestore → Primary DB (users, pools, franchises, contracts, ledger) # BigQuery → Analytics, financial reporting, ML training data # Cloud Storage → Contract PDFs, KYC docs, franchise photos, manuals # Secret Manager → API keys (40+ banks, Stripe, Twilio, NADRA) # AI/ML Layer # ────────────────────────────────────── # Vertex AI → Franchise matching model, risk scoring # Gemini 2.5 Pro → Shariah compliance checker, contract Q&A # Claude API → Document analysis, multilingual generation # Document AI → CNIC scanning, contract parsing # Integration Layer # ────────────────────────────────────── # Cloud Pub/Sub → Event bus (9 services communicate via events) # Cloud Tasks → Async job queue (payment processing, PDF gen) # Cloud Scheduler → Cron: quarterly distributions, daily reconciliation # API Gateway → Rate limiting, API key auth, request routing # Estimated Monthly Cost # ────────────────────────────────────── # Cloud Run (9 services) : $80-250 # Firestore : $30-100 # BigQuery : $20-50 # Cloud Storage : $5-15 # Vertex AI + Gemini : $50-200 # Pub/Sub + Tasks : $10-20 # Firebase Auth : Free (up to 50K MAU) # Monitoring + Logging : $10-20 # TOTAL : $205-655/month
musharakah-franchise-platform/ ├── services/ │ ├── auth-service/ │ │ ├── main.py # FastAPI entry │ │ ├── routers/auth.py # Register, login, CNIC verify │ │ ├── routers/kyc.py # KYC routing (NADRA/Stripe/GCC) │ │ ├── services/nadra_api.py # NADRA CNIC verification │ │ ├── services/stripe_identity.py # US/international KYC │ │ ├── services/ofac_screening.py # OFAC/SDN list check │ │ ├── services/rbac.py # Role-based access control │ │ ├── Dockerfile │ │ └── requirements.txt │ │ │ ├── banking-gateway/ │ │ ├── main.py │ │ ├── routers/banks.py # Bank provisioning + transfers │ │ ├── routers/payments.py # Multi-channel payment routing │ │ ├── services/islamic_bank_api.py # Meezan, BankIslami, Dubai Islamic │ │ ├── services/govt_bank_api.py # NBP, BoP, Sindh, BoK │ │ ├── services/ztbl_api.py # ZTBL agricultural credit │ │ ├── services/raast_api.py # SBP RAAST instant payment │ │ ├── services/mobile_money_api.py # JazzCash, Easypaisa │ │ ├── services/stripe_service.py # Stripe (APPNA/international) │ │ ├── services/swift_gateway.py # Institutional wire transfers │ │ ├── services/fx_service.py # Currency conversion (SBP rates) │ │ ├── config/banks.yaml # All 40+ bank configurations │ │ ├── Dockerfile │ │ └── requirements.txt │ │ │ ├── musharakah-engine/ │ │ ├── main.py │ │ ├── routers/pools.py # Pool CRUD, lifecycle │ │ ├── routers/partners.py # Partner join/exit │ │ ├── routers/investments.py # Capital contribution flows │ │ ├── routers/diminishing.py # Diminishing Musharakah buyout │ │ ├── services/pool_service.py │ │ ├── services/profit_calculator.py # Shariah-compliant P&L │ │ ├── services/diminishing_engine.py # Equity buyout schedule │ │ ├── services/tier_router.py # Income tier → pool matching │ │ └── ... │ │ │ ├── franchise-engine/ │ │ ├── main.py │ │ ├── routers/units.py # Franchise unit CRUD │ │ ├── routers/operators.py │ │ ├── routers/training.py │ │ ├── services/matching_service.py # AI franchise matching │ │ ├── services/setup_wizard.py │ │ ├── services/ztbl_bridge.py # ZTBL↔franchise integration │ │ ├── franchise_types/ # 12+ YAML configs │ │ │ ├── induction_cooking.yaml │ │ │ ├── food_drying.yaml │ │ │ ├── solar_installation.yaml │ │ │ ├── dairy_processing.yaml │ │ │ ├── ai_services_kiosk.yaml │ │ │ ├── inventor_workshop.yaml │ │ │ ├── water_harvesting.yaml │ │ │ ├── textile_production.yaml │ │ │ └── digital_services.yaml │ │ └── ... │ │ │ ├── contract-engine/ │ │ ├── main.py │ │ ├── routers/generate.py │ │ ├── routers/signatures.py │ │ ├── templates/ # Trilingual contract templates │ │ │ ├── musharakah_master.html │ │ │ ├── franchise_musharakah.html │ │ │ ├── diminishing_schedule.html │ │ │ ├── appna_investment.html # US-specific disclosures │ │ │ ├── ztbl_murabaha_bridge.html # ZTBL hybrid contract │ │ │ ├── institutional_musharakah.html │ │ │ ├── shariah_certificate.html │ │ │ └── partner_exit.html │ │ ├── generators/pdf_generator.py # WeasyPrint HTML→PDF │ │ └── ... │ │ │ ├── financial-engine/ │ │ ├── main.py │ │ ├── routers/ledger.py │ │ ├── routers/distributions.py │ │ ├── routers/reports.py │ │ ├── services/ledger_service.py # Double-entry accounting │ │ ├── services/distribution_engine.py # Quarterly profit calc │ │ ├── services/zakat_service.py # 2.5% Zakat calculation │ │ ├── services/tax_service.py # US K-1 for APPNA, PK tax │ │ ├── services/reconciliation.py # Daily bank reconciliation │ │ └── ... │ │ │ ├── ai-engine/ │ │ ├── main.py │ │ ├── routers/matching.py # Franchise ↔ operator matching │ │ ├── routers/compliance.py # Shariah AI checker │ │ ├── routers/projections.py # Financial projections │ │ ├── prompts/shariah_compliance.txt │ │ ├── prompts/franchise_advisor.txt │ │ ├── services/vertex_service.py │ │ ├── services/gemini_service.py │ │ └── ... │ │ │ ├── appna-gateway/ │ │ ├── main.py │ │ ├── routers/appna.py # APPNA member registration │ │ ├── routers/hometown.py # Hometown pool matching │ │ ├── routers/impact.py # Social impact dashboard │ │ ├── services/appna_sso.py # APPNA OAuth2 integration │ │ ├── services/us_compliance.py # OFAC, FinCEN, FATCA │ │ ├── services/impact_service.py # Impact metrics calculation │ │ ├── services/tax_docs.py # K-1 generation for IRS │ │ └── ... │ │ │ └── notification-engine/ │ ├── main.py │ ├── services/sms.py # Twilio (Urdu + English) │ ├── services/whatsapp.py # WhatsApp Business API │ ├── services/email.py # SendGrid │ ├── services/push.py # Firebase Cloud Messaging │ └── templates/ # Notification templates │ ├── frontend/ │ └── web-app/ # Next.js 14 + Tailwind │ ├── src/app/ │ │ ├── (auth)/login|register|kyc/ │ │ ├── (dashboard)/pools|franchises|contracts|portfolio/ │ │ ├── (appna)/invest|impact|hometown/ # APPNA portal │ │ ├── (operator)/my-unit|reports|training/ │ │ ├── (shariah)/review|rulings/ │ │ └── (admin)/dashboard|kyc|pools/ │ └── ... │ ├── infrastructure/ │ ├── terraform/main.tf # All GCP resources │ ├── docker/base.Dockerfile │ └── cloudbuild.yaml # CI/CD pipeline │ ├── contracts/templates/ # 8 contract templates × 3 langs ├── data/franchise_types/ # 12+ YAML franchise configs ├── data/banks/config.yaml # 40+ bank API configurations └── docs/api/openapi.yaml # Full API specification
# ═══════════════════════════════════════════
# MUSHARAKAH INTEGRATION ENGINE — API v1
# Base URL: https://api.musharakah.kaamyabpakistan.org/v1
# ═══════════════════════════════════════════
# ── AUTH & KYC ──
POST /auth/register # Register (all user types)
POST /auth/login # Firebase token login
POST /auth/kyc/verify-cnic # NADRA CNIC verification
POST /auth/kyc/verify-us # US KYC (APPNA) via Stripe
POST /auth/kyc/verify-gulf # Gulf KYC (Emirates ID)
POST /auth/kyc/verify-institutional # Enhanced due diligence
GET /auth/kyc/status/{uid} # KYC status check
POST /auth/appna/sso # APPNA SSO login
# ── BANKING GATEWAY ──
POST /banking/provision # Auto-provision bank account
POST /banking/transfer # Route payment to bank
GET /banking/accounts/{uid} # User's linked accounts
POST /banking/jazzcash/pay # JazzCash payment
POST /banking/easypaisa/pay # Easypaisa payment
POST /banking/ibft # Islamic bank IBFT
POST /banking/raast # SBP RAAST instant
POST /banking/stripe/charge # Stripe (APPNA/intl)
POST /banking/swift # Institutional wire
GET /banking/fx/rate/{from}/{to} # FX rate (SBP market)
POST /banking/reconcile # Daily reconciliation
# ── MUSHARAKAH POOLS ──
GET /pools # List (filter: platform, region, status)
POST /pools # Create pool
GET /pools/{id} # Pool details
PUT /pools/{id} # Update pool
POST /pools/{id}/commit # Commit capital
POST /pools/{id}/activate # Activate (after target met)
GET /pools/{id}/partners # List partners
POST /pools/{id}/exit/{uid} # Partner exit with valuation
GET /pools/match/{uid} # AI-matched pools for user
GET /pools/hometown/{district} # Pools by hometown (APPNA)
GET /pools/tier/{tier_number} # Pools by income tier
# ── FRANCHISE UNITS ──
GET /franchises # List units
POST /franchises # Create unit
GET /franchises/{id} # Unit details
GET /franchises/types # Available franchise types
POST /franchises/{id}/deploy # Begin deployment
POST /franchises/{id}/train/complete # Mark training done
POST /franchises/{id}/inspect # Quality inspection
POST /franchises/{id}/launch # Launch operations
POST /franchises/{id}/reports # Submit monthly report
GET /franchises/{id}/performance # Performance dashboard
GET /franchises/match/{uid} # AI franchise matching
# ── CONTRACTS ──
POST /contracts/generate # Generate from template
GET /contracts/{id} # Get contract
GET /contracts/{id}/pdf # Download PDF
POST /contracts/{id}/sign # E-sign (with hash)
POST /contracts/{id}/shariah-review # Submit for review
POST /contracts/{id}/approve # Shariah board approve
GET /contracts/templates # Available templates
GET /contracts/my/{uid} # User's contracts
# ── FINANCIAL ──
GET /finance/ledger/{poolId} # Pool ledger entries
POST /finance/distribute/calculate # Calculate quarterly dist
POST /finance/distribute/approve # Approve distribution
POST /finance/distribute/execute # Execute multi-gateway payout
GET /finance/diminishing/{poolId} # Diminishing schedule
POST /finance/zakat/calculate # Zakat calculation
GET /finance/reports/{poolId} # Financial reports
GET /finance/tax/k1/{uid}/{year} # US K-1 for APPNA
POST /finance/reconcile/daily # Daily bank reconciliation
# ── AI SERVICES ──
POST /ai/match-franchise # AI franchise matching
POST /ai/match-pool # AI pool matching
POST /ai/risk-score # Investment risk assessment
POST /ai/shariah-check # Auto Shariah compliance
POST /ai/financial-projection # Revenue projection
POST /ai/translate # EN ↔ UR ↔ AR translation
POST /ai/contract-qa # Contract Q&A chatbot
# ── APPNA SPECIFIC ──
POST /appna/register # APPNA member registration
GET /appna/hometown-pools/{uid} # Hometown matching
POST /appna/invest # USD investment flow
GET /appna/impact/{uid} # Social impact dashboard
GET /appna/tax-docs/{uid}/{year} # US tax documents
GET /appna/chapter/{chapter_id} # Chapter aggregate stats
# ── ZTBL BRIDGE ──
POST /ztbl/link-farmer # Link ZTBL farmer account
GET /ztbl/credit-history/{cnic} # Farmer credit history
POST /ztbl/murabaha-bridge # Create Murabaha+Musharakah hybrid
GET /ztbl/eligible-franchises/{uid} # Franchises matching farm profile
# ── PENSION/INSTITUTIONAL ──
POST /institutional/register # Institutional registration
POST /institutional/due-diligence # Submit DD package
POST /institutional/allocate # Allocate fund capital
GET /institutional/portfolio/{id} # Fund portfolio view
GET /institutional/reports/{id} # Institutional reports
# ── NOTIFICATIONS ──
GET /notifications/{uid} # User notifications
PUT /notifications/{id}/read # Mark read
POST /notifications/broadcast/{poolId} # Broadcast to pool members
# ── ADMIN ──
GET /admin/dashboard # System-wide metrics
GET /admin/pools/pending # Pools awaiting review
GET /admin/kyc/queue # KYC review queue
POST /admin/kyc/{uid}/approve # Approve KYC
GET /admin/banks/health # Bank API health check
GET /admin/distributions/pending # Pending distributionsThese are the 8 critical specifications Claude Code needs to build every service correctly — data validation, security, queries, monitoring, testing, and the core financial algorithms.
# ═══════════════════════════════════════════════════════
# SHARED PYDANTIC SCHEMAS — Used across all services
# ═══════════════════════════════════════════════════════
from pydantic import BaseModel, Field, validator
from typing import Optional, List, Literal
from datetime import datetime
from enum import Enum
# ── Enums ──
class UserRole(str, Enum):
COMMUNITY_INVESTOR = "community_investor"
EXTERNAL_FINANCIER = "external_financier"
FRANCHISE_OPERATOR = "franchise_operator"
MANAGING_PARTNER = "managing_partner"
SHARIAH_ADVISOR = "shariah_advisor"
PLATFORM_ADMIN = "platform_admin"
class Platform(str, Enum):
KAAMYABPAKISTAN = "kaamyabpakistan"
YOUINVENT = "youinvent"
HOMEFRANCHISE = "homefranchise"
NOCODEAI = "nocodeai"
class PoolType(str, Enum):
SHIRKAT_AMWAL = "shirkat_amwal" # Capital partnership
SHIRKAT_AMAL = "shirkat_amal" # Services partnership
SHIRKAT_WUJUH = "shirkat_wujuh" # Goodwill partnership
MUSHARAKAH_MUTANAQISAH = "musharakah_mutanaqisah" # Diminishing
class PoolStatus(str, Enum):
DRAFT = "draft"
SHARIAH_REVIEW = "shariah_review"
FUNDRAISING = "fundraising"
ACTIVE = "active"
DISTRIBUTING = "distributing"
COMPLETED = "completed"
class FranchiseType(str, Enum):
INDUCTION_COOKING = "induction_cooking"
FOOD_DRYING = "food_drying"
WATER_HARVESTING = "water_harvesting"
SOLAR_INSTALLATION = "solar_installation"
AI_SERVICES_KIOSK = "ai_services_kiosk"
INVENTOR_WORKSHOP = "inventor_workshop"
DAIRY_PROCESSING = "dairy_processing"
TEXTILE_PRODUCTION = "textile_production"
HERBAL_PROCESSING = "herbal_processing"
DIGITAL_SERVICES = "digital_services"
SAFFRON_AQUAPONIC = "saffron_aquaponic"
FISH_POND_CHINESE = "fish_pond_chinese"
class BankChannel(str, Enum):
ISLAMIC = "islamic"
GOVERNMENT = "government"
ZTBL = "ztbl"
PRIVATE = "private"
MOBILE = "mobile_money"
STRIPE = "stripe"
WIRE = "wire"
class PaymentMethod(str, Enum):
JAZZCASH = "jazzcash"
EASYPAISA = "easypaisa"
BANK_IBFT = "bank_ibft"
STRIPE_CARD = "stripe_card"
STRIPE_WIRE = "stripe_wire"
# ── User Schemas ──
class UserRegisterRequest(BaseModel):
email: str
phone: str = Field(..., regex=r"^\+92[0-9]{10}$") # Pakistan format
full_name_en: str
full_name_ur: Optional[str] = None
cnic: Optional[str] = Field(None, regex=r"^[0-9]{5}-[0-9]{7}-[0-9]$")
passport: Optional[str] = None # For diaspora
role: UserRole
platform_affiliation: List[Platform]
province: Optional[str] = None
district: Optional[str] = None
postal_code: Optional[str] = None
class UserProfileResponse(BaseModel):
uid: str
email: str
phone: str
full_name: dict # {"en": "...", "ur": "..."}
role: UserRole
kyc_status: Literal["pending", "submitted", "verified", "rejected"]
bank_accounts: List[dict]
income_tier: Optional[int] = None # 1-7
created_at: datetime
# ── Musharakah Pool Schemas ──
class PoolCreateRequest(BaseModel):
pool_name: dict # {"en": "...", "ur": "..."}
platform: Platform
pool_type: PoolType
target_capital_pkr: float = Field(..., gt=0)
minimum_investment_pkr: float = Field(10000, ge=10000)
maximum_investment_pkr: Optional[float] = None
profit_sharing: dict # {"community_pct": 40, "financier_pct": 35, ...}
loss_sharing: str = "proportional_to_capital" # ALWAYS this per Shariah
diminishing_enabled: bool = False
buyout_period_months: Optional[int] = None
franchise_type: Optional[FranchiseType] = None
target_region: dict # {"province": "...", "district": "..."}
description: dict # {"en": "...", "ur": "..."}
@validator("profit_sharing")
def validate_profit_shares(cls, v):
total = sum(v.values())
if abs(total - 100) > 0.01:
raise ValueError(f"Profit shares must sum to 100%, got {total}%")
return v
class PoolResponse(BaseModel):
pool_id: str # MKP-2026-XXXXX
pool_name: dict
platform: Platform
pool_type: PoolType
status: PoolStatus
target_capital: float
raised_capital: float
partner_count: int
profit_sharing: dict
franchise_type: Optional[FranchiseType]
shariah_approved: bool
created_at: datetime
updated_at: datetime
class InvestRequest(BaseModel):
pool_id: str
amount_pkr: float = Field(..., ge=10000)
payment_method: PaymentMethod
payment_account_id: Optional[str] = None
class InvestResponse(BaseModel):
investment_id: str
pool_id: str
amount_pkr: float
equity_percentage: float
payment_status: Literal["pending", "completed", "failed"]
contract_id: str
transaction_ref: str
# ── Franchise Schemas ──
class FranchiseApplyRequest(BaseModel):
franchise_type: FranchiseType
pool_id: str
location: dict # {"province", "district", "tehsil", "postal_code", "lat", "lng"}
operator_cnic: str
skills_assessment: dict # From AI matching quiz
education_level: str
experience_years: int
class FranchiseUnitResponse(BaseModel):
franchise_id: str # HF-2026-XXXXX
franchise_type: FranchiseType
operator_id: str
pool_id: str
status: Literal["setup", "training", "operating", "paused", "closed"]
setup_cost_pkr: float
monthly_revenue_target: float
monthly_revenue_actual: float
operator_ownership_pct: float # Increases with diminishing Musharakah
training_progress: dict
equipment_status: dict
# ── Financial Schemas ──
class ProfitDistributionRequest(BaseModel):
pool_id: str
period: str # "2026-Q1" or "2026-03"
class ProfitDistributionResponse(BaseModel):
distribution_id: str
pool_id: str
period: str
total_revenue: float
total_expenses: float
net_profit: float # Can be negative (loss)
distributions: List[dict] # Per-partner breakdown
zakat_total: float
status: Literal["calculating", "review", "approved", "distributed"]
# ── Contract Schemas ──
class ContractGenerateRequest(BaseModel):
template_id: str # "musharakah_master", "franchise_musharakah", etc.
pool_id: str
parties: List[dict] # [{"user_id", "role", "name"}]
language: Literal["en", "ur", "bilingual", "trilingual"]
custom_clauses: Optional[List[str]] = None
class ContractSignRequest(BaseModel):
contract_id: str
signature_data: str # Base64 canvas signature
signer_uid: str
# ── Banking Schemas ──
class BankProvisionRequest(BaseModel):
user_id: str
user_type: UserRole
preferred_channel: Optional[BankChannel] = None
location: dict
class BankProvisionResponse(BaseModel):
account_id: str
bank_name: str
channel: BankChannel
account_number: str
iban: Optional[str] = None
wallet_id: Optional[str] = None
# ── APPNA Schemas ──
class APPNAInvestRequest(BaseModel):
appna_member_id: str
amount_usd: float = Field(..., ge=100)
hometown_postal_code: str # Pakistan postal code
preferred_platform: Optional[Platform] = None
preferred_franchise_type: Optional[FranchiseType] = None
payment_method: Literal["stripe_card", "stripe_ach", "wire"]
class APPNAMatchResponse(BaseModel):
member_id: str
hometown: dict
matching_pools: List[dict] # Ranked by relevance
social_impact_score: float
projected_roi_annual: float
fx_rate_usd_pkr: float
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// ── Helper functions ──
function isAuthenticated() {
return request.auth != null;
}
function isOwner(userId) {
return request.auth.uid == userId;
}
function hasRole(role) {
return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == role;
}
function isAdmin() {
return hasRole('platform_admin');
}
function isShariahAdvisor() {
return hasRole('shariah_advisor');
}
function isManagingPartner() {
return hasRole('managing_partner');
}
function isPartnerInPool(poolId) {
return request.auth.uid in get(/databases/$(database)/documents/pools/$(poolId)).data.partner_uids;
}
// ── Users collection ──
match /users/{userId} {
allow read: if isAuthenticated() && (isOwner(userId) || isAdmin() || isManagingPartner());
allow create: if isAuthenticated() && isOwner(userId);
allow update: if isAuthenticated() && (isOwner(userId) || isAdmin());
allow delete: if isAdmin();
// KYC subcollection
match /kyc_documents/{docId} {
allow read: if isAuthenticated() && (isOwner(userId) || isAdmin());
allow create: if isAuthenticated() && isOwner(userId);
allow update: if isAdmin();
}
}
// ── Musharakah Pools ──
match /pools/{poolId} {
allow read: if isAuthenticated(); // All authenticated users can browse
allow create: if isAuthenticated() && (isManagingPartner() || isAdmin());
allow update: if isAuthenticated() &&
(isManagingPartner() || isAdmin() ||
(isShariahAdvisor() && request.resource.data.diff(resource.data).affectedKeys()
.hasOnly(['shariah_approved','shariah_reviewer_id','shariah_notes','shariah_approved_at','status'])));
allow delete: if isAdmin() && resource.data.status == 'draft';
// Partners subcollection
match /partners/{partnerId} {
allow read: if isAuthenticated() && (isPartnerInPool(poolId) || isManagingPartner() || isAdmin());
allow create: if isAuthenticated(); // Anyone can join (invest)
allow update: if isAuthenticated() && (isManagingPartner() || isAdmin());
}
}
// ── Franchise Units ──
match /franchises/{franchiseId} {
allow read: if isAuthenticated();
allow create: if isAuthenticated() && (isManagingPartner() || isAdmin());
allow update: if isAuthenticated() &&
(resource.data.operator_id == request.auth.uid ||
isManagingPartner() || isAdmin());
// Monthly reports
match /reports/{reportId} {
allow read: if isAuthenticated() && (isPartnerInPool(resource.data.pool_id) || isAdmin());
allow create: if isAuthenticated() && resource.data.operator_id == request.auth.uid;
allow update: if isManagingPartner() || isAdmin();
}
}
// ── Contracts ──
match /contracts/{contractId} {
allow read: if isAuthenticated() &&
(request.auth.uid in resource.data.party_uids || isShariahAdvisor() || isAdmin());
allow create: if isAuthenticated() && (isManagingPartner() || isAdmin());
allow update: if isAuthenticated() &&
(request.auth.uid in resource.data.party_uids ||
isShariahAdvisor() || isAdmin());
}
// ── Ledger (financial records) — Read-only for partners ──
match /ledger/{entryId} {
allow read: if isAuthenticated() &&
(isPartnerInPool(resource.data.pool_id) || isManagingPartner() || isAdmin());
allow create: if isAuthenticated() && (isManagingPartner() || isAdmin());
allow update: if false; // Ledger entries are immutable
allow delete: if false; // Never delete financial records
}
// ── Profit Distributions ──
match /distributions/{distId} {
allow read: if isAuthenticated() &&
(isPartnerInPool(resource.data.pool_id) || isAdmin());
allow create: if isManagingPartner() || isAdmin();
allow update: if isManagingPartner() || isAdmin() || isShariahAdvisor();
}
// ── Platform Projects ──
match /projects/{projectId} {
allow read: if isAuthenticated();
allow write: if isManagingPartner() || isAdmin();
}
}
}
{
"indexes": [
{
"collectionGroup": "pools",
"queryScope": "COLLECTION",
"fields": [
{"fieldPath": "platform", "order": "ASCENDING"},
{"fieldPath": "status", "order": "ASCENDING"},
{"fieldPath": "created_at", "order": "DESCENDING"}
]
},
{
"collectionGroup": "pools",
"queryScope": "COLLECTION",
"fields": [
{"fieldPath": "target_region.province", "order": "ASCENDING"},
{"fieldPath": "pool_type", "order": "ASCENDING"},
{"fieldPath": "status", "order": "ASCENDING"}
]
},
{
"collectionGroup": "pools",
"queryScope": "COLLECTION",
"fields": [
{"fieldPath": "franchise_type", "order": "ASCENDING"},
{"fieldPath": "status", "order": "ASCENDING"},
{"fieldPath": "raised_capital", "order": "DESCENDING"}
]
},
{
"collectionGroup": "ledger",
"queryScope": "COLLECTION",
"fields": [
{"fieldPath": "pool_id", "order": "ASCENDING"},
{"fieldPath": "entry_type", "order": "ASCENDING"},
{"fieldPath": "created_at", "order": "DESCENDING"}
]
},
{
"collectionGroup": "franchises",
"queryScope": "COLLECTION",
"fields": [
{"fieldPath": "franchise_type", "order": "ASCENDING"},
{"fieldPath": "location.province", "order": "ASCENDING"},
{"fieldPath": "status", "order": "ASCENDING"}
]
},
{
"collectionGroup": "contracts",
"queryScope": "COLLECTION",
"fields": [
{"fieldPath": "pool_id", "order": "ASCENDING"},
{"fieldPath": "status", "order": "ASCENDING"},
{"fieldPath": "created_at", "order": "DESCENDING"}
]
},
{
"collectionGroup": "distributions",
"queryScope": "COLLECTION",
"fields": [
{"fieldPath": "pool_id", "order": "ASCENDING"},
{"fieldPath": "period", "order": "DESCENDING"}
]
},
{
"collectionGroup": "users",
"queryScope": "COLLECTION",
"fields": [
{"fieldPath": "role", "order": "ASCENDING"},
{"fieldPath": "location.province", "order": "ASCENDING"},
{"fieldPath": "kyc_status", "order": "ASCENDING"}
]
}
],
"fieldOverrides": []
}
# ═══════════════════════════════════════════════════════
# SHARIAH-COMPLIANT PROFIT DISTRIBUTION ENGINE
# Key rule: Profit per AGREED ratio, Loss per CAPITAL ratio
# ═══════════════════════════════════════════════════════
from dataclasses import dataclass
from typing import List, Optional
from decimal import Decimal, ROUND_HALF_UP
import logging
logger = logging.getLogger("financial_engine.profit_distribution")
@dataclass
class PartnerShare:
user_id: str
partner_type: str # community_investor | external_financier | operator | managing_partner
capital_contributed: Decimal
capital_percentage: Decimal # For LOSS allocation (Shariah: proportional to capital)
profit_ratio: Decimal # For PROFIT allocation (can differ from capital %)
zakat_opt_in: bool = False
@dataclass
class DistributionResult:
user_id: str
partner_type: str
gross_amount: Decimal
zakat_deducted: Decimal
platform_fee: Decimal
net_amount: Decimal
is_profit: bool # True = profit distribution, False = loss allocation
def calculate_distribution(
pool_id: str,
period: str,
total_revenue: Decimal,
total_expenses: Decimal,
partners: List[PartnerShare],
platform_fee_pct: Decimal = Decimal("5.0"),
zakat_rate: Decimal = Decimal("2.5"),
zakat_annual_prorate: bool = True, # Prorate 2.5% annually to period
period_months: int = 3, # Quarterly = 3
) -> List[DistributionResult]:
"""
Core Shariah-compliant profit/loss distribution.
PROFIT: distributed per agreed profit_ratio (may reward active management)
LOSS: distributed per capital_percentage ONLY (Shariah requirement)
"""
net_profit = total_revenue - total_expenses
results = []
logger.info(f"Pool {pool_id} | Period {period} | Revenue: {total_revenue} | "
f"Expenses: {total_expenses} | Net: {net_profit}")
if net_profit > 0:
# ── PROFIT SCENARIO ──
# Step 1: Deduct platform fee
platform_fee_total = (net_profit * platform_fee_pct / 100).quantize(Decimal("0.01"))
distributable = net_profit - platform_fee_total
# Step 2: Distribute per AGREED PROFIT RATIO
for partner in partners:
gross = (distributable * partner.profit_ratio / 100).quantize(
Decimal("0.01"), rounding=ROUND_HALF_UP
)
# Step 3: Optional Zakat deduction
zakat = Decimal("0")
if partner.zakat_opt_in:
if zakat_annual_prorate:
# Prorate 2.5% annual to this period
zakat = (gross * zakat_rate / 100 * period_months / 12).quantize(Decimal("0.01"))
else:
zakat = (gross * zakat_rate / 100).quantize(Decimal("0.01"))
# Per-partner platform fee (proportional)
partner_platform_fee = (platform_fee_total * partner.profit_ratio / 100).quantize(Decimal("0.01"))
results.append(DistributionResult(
user_id=partner.user_id,
partner_type=partner.partner_type,
gross_amount=gross,
zakat_deducted=zakat,
platform_fee=partner_platform_fee,
net_amount=gross - zakat,
is_profit=True,
))
logger.info(f"PROFIT distributed to {len(partners)} partners. Platform fee: {platform_fee_total}")
elif net_profit < 0:
# ── LOSS SCENARIO ──
# Shariah requirement: Loss MUST be proportional to CAPITAL only
# profit_ratio is IGNORED for losses
loss = abs(net_profit)
for partner in partners:
loss_share = (loss * partner.capital_percentage / 100).quantize(
Decimal("0.01"), rounding=ROUND_HALF_UP
)
results.append(DistributionResult(
user_id=partner.user_id,
partner_type=partner.partner_type,
gross_amount=-loss_share, # Negative = loss
zakat_deducted=Decimal("0"),
platform_fee=Decimal("0"), # No fee on losses
net_amount=-loss_share,
is_profit=False,
))
logger.warning(f"LOSS of {loss} allocated to {len(partners)} partners by capital ratio")
else:
# Break-even: no distribution
logger.info(f"Break-even for pool {pool_id} period {period}")
return results
# ═══════════════════════════════════════════════════════
# DIMINISHING MUSHARAKAH SCHEDULE ENGINE
# Operator buys out financier equity units over time
# ═══════════════════════════════════════════════════════
@dataclass
class BuyoutScheduleEntry:
period: int # Month number
units_purchased: int
unit_price: Decimal
payment_amount: Decimal
operator_units_after: int
financier_units_after: int
operator_ownership_pct: Decimal
cumulative_paid: Decimal
def generate_diminishing_schedule(
total_units: int,
buyout_period_months: int,
unit_price_method: str, # "book_value" or "fair_market"
initial_unit_price: Decimal,
appreciation_rate_annual: Decimal = Decimal("0"), # For fair_market
buyout_frequency_months: int = 1, # Monthly buyout
) -> List[BuyoutScheduleEntry]:
"""
Generate complete diminishing Musharakah buyout schedule.
Operator purchases equity units each period until 100% ownership.
"""
units_per_period = total_units // (buyout_period_months // buyout_frequency_months)
remainder = total_units % (buyout_period_months // buyout_frequency_months)
schedule = []
operator_units = 0
cumulative = Decimal("0")
monthly_appreciation = (1 + appreciation_rate_annual / 100) ** (Decimal("1") / 12)
for period in range(buyout_frequency_months, buyout_period_months + 1, buyout_frequency_months):
# Calculate unit price for this period
if unit_price_method == "book_value":
price = initial_unit_price # Fixed
else: # fair_market — appreciates
months_elapsed = period
price = (initial_unit_price * monthly_appreciation ** months_elapsed).quantize(Decimal("0.01"))
# Last period gets remainder units
units_this = units_per_period + (remainder if period >= buyout_period_months else 0)
payment = (price * units_this).quantize(Decimal("0.01"))
operator_units += units_this
cumulative += payment
financier_units = total_units - operator_units
ownership_pct = (Decimal(operator_units) / total_units * 100).quantize(Decimal("0.01"))
schedule.append(BuyoutScheduleEntry(
period=period,
units_purchased=units_this,
unit_price=price,
payment_amount=payment,
operator_units_after=operator_units,
financier_units_after=financier_units,
operator_ownership_pct=ownership_pct,
cumulative_paid=cumulative,
))
return schedule
# ── Base dependencies (all services) ── fastapi==0.109.0 uvicorn[standard]==0.27.0 pydantic==2.5.3 python-dotenv==1.0.0 httpx==0.26.0 google-cloud-firestore==2.14.0 google-cloud-storage==2.14.0 google-cloud-secret-manager==2.18.0 firebase-admin==6.4.0 python-jose[cryptography]==3.3.0 # JWT passlib[bcrypt]==1.7.4 python-multipart==0.0.6 structlog==24.1.0 # Structured logging tenacity==8.2.3 # Retry logic
-r ../shared/requirements-base.txt # ── Financial engine specific ── google-cloud-bigquery==3.17.0 google-cloud-scheduler==2.13.0 pandas==2.1.4 numpy==1.26.3 forex-python==1.8 # FX rates
-r ../shared/requirements-base.txt # ── Contract engine specific ── weasyprint==60.2 # HTML → PDF jinja2==3.1.3 # Template rendering google-cloud-documentai==2.24.0
-r ../shared/requirements-base.txt # ── AI engine specific ── google-cloud-aiplatform==1.40.0 # Vertex AI anthropic==0.18.0 # Claude API google-generativeai==0.4.0 # Gemini scikit-learn==1.4.0 # Matching algo
-r ../shared/requirements-base.txt # ── Banking gateway specific ── stripe==8.4.0 requests==2.31.0 # JazzCash/Easypaisa REST cryptography==42.0.0 # HMAC for payment signatures
-r ../shared/requirements-base.txt # ── APPNA gateway specific ── stripe==8.4.0 stripe-identity==0.1.0 # Stripe Identity (KYC) ofac-screening==1.2.0 # OFAC/SDN check us-tax-forms==0.3.0 # K-1 generation
-r ../shared/requirements-base.txt # ── Notification specific ── twilio==8.12.0 # SMS sendgrid==6.11.0 # Email firebase-admin>=6.4.0 # Push (FCM)
{
"dependencies": {
"next": "14.1.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.4.1",
"firebase": "10.8.0",
"@stripe/stripe-js": "2.4.0",
"recharts": "2.10.3",
"react-hook-form": "7.49.3",
"zod": "3.22.4",
"next-intl": "3.5.4",
"signature_pad": "4.1.7",
"date-fns": "3.3.1",
"lucide-react": "0.312.0",
"@radix-ui/react-dialog": "1.0.5",
"@radix-ui/react-dropdown-menu": "2.0.6"
}
}
# ═══════════════════════════════════════════════════════
# STRUCTURED LOGGING — All services use this
# Sends to Google Cloud Logging automatically on Cloud Run
# ═══════════════════════════════════════════════════════
import structlog
import google.cloud.logging
from google.cloud.logging_v2.handlers import CloudLoggingHandler
def setup_logging(service_name: str):
"""Initialize structured logging for a service."""
client = google.cloud.logging.Client()
handler = CloudLoggingHandler(client, name=service_name)
structlog.configure(
processors=[
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.add_log_level,
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.JSONRenderer(),
],
wrapper_class=structlog.BoundLogger,
context_class=dict,
logger_factory=structlog.PrintLoggerFactory(),
)
return structlog.get_logger(service=service_name)
# Usage in any service:
# logger = setup_logging("musharakah-engine")
# logger.info("pool_created", pool_id="MKP-2026-00001", capital=500000)
# logger.warning("shariah_review_pending", pool_id="MKP-2026-00001")
# logger.error("payment_failed", user_id="...", amount=10000, provider="jazzcash")
# ═══════════════════════════════════════════════════════
# CLOUD MONITORING — Alerts for critical operations
# ═══════════════════════════════════════════════════════
resource "google_monitoring_alert_policy" "payment_failures" {
display_name = "Payment Failure Rate > 5%"
combiner = "OR"
conditions {
display_name = "High payment failure rate"
condition_threshold {
filter = "resource.type=\"cloud_run_revision\" AND metric.type=\"logging.googleapis.com/user/payment_failed\""
comparison = "COMPARISON_GT"
threshold_value = 5
duration = "300s"
aggregations {
alignment_period = "60s"
per_series_aligner = "ALIGN_RATE"
}
}
}
notification_channels = [google_monitoring_notification_channel.ops_email.name]
}
resource "google_monitoring_alert_policy" "shariah_queue" {
display_name = "Shariah Review Queue > 50 pending"
combiner = "OR"
conditions {
display_name = "Shariah review backlog"
condition_threshold {
filter = "resource.type=\"cloud_run_revision\" AND metric.type=\"logging.googleapis.com/user/shariah_review_pending\""
comparison = "COMPARISON_GT"
threshold_value = 50
duration = "600s"
}
}
notification_channels = [google_monitoring_notification_channel.ops_email.name]
}
resource "google_monitoring_alert_policy" "pool_funding_complete" {
display_name = "Pool Fully Funded"
combiner = "OR"
conditions {
display_name = "Pool reached target capital"
condition_threshold {
filter = "metric.type=\"logging.googleapis.com/user/pool_fully_funded\""
comparison = "COMPARISON_GT"
threshold_value = 0
duration = "0s"
}
}
notification_channels = [google_monitoring_notification_channel.ops_email.name]
}
resource "google_monitoring_notification_channel" "ops_email" {
display_name = "Operations Team"
type = "email"
labels = { email_address = "ops@kaamyabpakistan.org" }
}
# Custom metrics for dashboard
resource "google_monitoring_dashboard" "musharakah_dashboard" {
dashboard_json = jsonencode({
displayName = "Musharakah Platform Dashboard"
gridLayout = { columns = 3, widgets = [
{ title = "Active Pools", scorecard = { timeSeriesQuery = { timeSeriesFilter = { filter = "metric.type=\"logging.googleapis.com/user/active_pools\"" }}}},
{ title = "Total Invested (PKR)", scorecard = { timeSeriesQuery = { timeSeriesFilter = { filter = "metric.type=\"logging.googleapis.com/user/total_invested\"" }}}},
{ title = "Franchise Units Live", scorecard = { timeSeriesQuery = { timeSeriesFilter = { filter = "metric.type=\"logging.googleapis.com/user/franchise_units_active\"" }}}},
{ title = "Payment Success Rate", scorecard = { timeSeriesQuery = { timeSeriesFilter = { filter = "metric.type=\"logging.googleapis.com/user/payment_success_rate\"" }}}},
{ title = "APPNA Investments", scorecard = { timeSeriesQuery = { timeSeriesFilter = { filter = "metric.type=\"logging.googleapis.com/user/appna_investments\"" }}}},
{ title = "Shariah Queue", scorecard = { timeSeriesQuery = { timeSeriesFilter = { filter = "metric.type=\"logging.googleapis.com/user/shariah_review_pending\"" }}}},
]}
})
}
# ═══════════════════════════════════════════════════════
# SEED DATA — Run once to populate dev/staging Firestore
# python scripts/seed_data.py --env=dev
# ═══════════════════════════════════════════════════════
import firebase_admin
from firebase_admin import credentials, firestore
import json, sys, os
def seed_franchise_types(db):
"""Seed 12 franchise type configurations."""
types = [
{"id": "induction_cooking", "name_en": "48V DC Solar Induction Cooking", "name_ur": "سولر انڈکشن کوکنگ",
"setup_cost_min": 72000, "setup_cost_max": 113000, "setup_cost_typical": 85000,
"monthly_revenue_target": 65000, "monthly_operating_cost": 8000, "break_even_months": 2,
"equipment": [
{"item": "4x 400W Solar Panels", "cost": 17500},
{"item": "MPPT Controller 48V/60A", "cost": 10000},
{"item": "LiFePO4 Battery 48V 100Ah", "cost": 45000},
{"item": "DC Induction Cooker (local)", "cost": 8000},
{"item": "Wiring + Installation", "cost": 4500}
],
"training_modules": ["Solar Installation 8hr", "Cooker Operation 6hr", "Food Dehydration 4hr", "Business Mgmt 6hr"],
"target_regions": ["Thar", "Cholistan", "Southern Punjab", "Balochistan"]},
{"id": "food_drying", "name_en": "Solar Food Drying Unit", "name_ur": "سولر فوڈ ڈرائنگ",
"setup_cost_typical": 95000, "monthly_revenue_target": 80000, "break_even_months": 2,
"target_regions": ["Sindh", "Punjab", "Balochistan"]},
{"id": "water_harvesting", "name_en": "Desiccant Water Harvesting", "name_ur": "پانی کی کٹائی",
"setup_cost_typical": 120000, "monthly_revenue_target": 45000, "break_even_months": 4,
"target_regions": ["Thar", "Cholistan", "Thal Desert"]},
{"id": "solar_installation", "name_en": "Solar System Installation", "name_ur": "سولر سسٹم انسٹالیشن",
"setup_cost_typical": 150000, "monthly_revenue_target": 100000, "break_even_months": 2},
{"id": "ai_services_kiosk", "name_en": "NoCodeAI Service Kiosk", "name_ur": "AI سروس کیوسک",
"setup_cost_typical": 200000, "monthly_revenue_target": 120000, "break_even_months": 3},
{"id": "dairy_processing", "name_en": "Dairy Processing Unit", "name_ur": "ڈیری پروسیسنگ",
"setup_cost_typical": 250000, "monthly_revenue_target": 150000, "break_even_months": 3},
{"id": "textile_production", "name_en": "Home Textile Production", "name_ur": "ٹیکسٹائل پروڈکشن",
"setup_cost_typical": 180000, "monthly_revenue_target": 90000, "break_even_months": 3},
{"id": "saffron_aquaponic", "name_en": "Saffron Indoor Aquaponic Farm", "name_ur": "زعفران ایکواپونک",
"setup_cost_typical": 500000, "monthly_revenue_target": 300000, "break_even_months": 4},
{"id": "fish_pond_chinese", "name_en": "Chinese Integrated Pond System", "name_ur": "چینی مچھلی تالاب",
"setup_cost_typical": 350000, "monthly_revenue_target": 200000, "break_even_months": 3},
]
for ft in types:
db.collection("franchise_types").document(ft["id"]).set(ft)
print(f" ✅ Seeded {len(types)} franchise types")
def seed_sample_pool(db):
"""Create a sample Musharakah pool for testing."""
pool = {
"pool_id": "MKP-2026-00001",
"pool_name": {"en": "Thar Solar Cooking Musharakah", "ur": "تھر سولر کوکنگ مشارکہ"},
"platform": "homefranchise", "pool_type": "musharakah_mutanaqisah",
"status": "fundraising", "target_capital": 500000, "raised_capital": 0,
"minimum_investment": 10000, "maximum_investment": 100000,
"profit_sharing": {"community_pct": 40, "financier_pct": 30, "managing_pct": 15, "operator_pct": 10, "platform_pct": 5},
"loss_sharing": "proportional_to_capital",
"diminishing_enabled": True, "buyout_period_months": 36,
"franchise_type": "induction_cooking",
"target_region": {"province": "Sindh", "district": "Tharparkar"},
"partners": [], "partner_uids": [],
"shariah_approved": False, "created_at": firestore.SERVER_TIMESTAMP,
}
db.collection("pools").document(pool["pool_id"]).set(pool)
print(f" ✅ Seeded sample pool: {pool['pool_id']}")
def seed_test_users(db):
"""Create test users for each role."""
users = [
{"uid": "test-admin-001", "email": "admin@kaamyabpakistan.org", "role": "platform_admin", "full_name": {"en": "Admin User"}},
{"uid": "test-investor-001", "email": "investor@test.pk", "role": "community_investor", "cnic": "41303-1234567-1", "income_tier": 3},
{"uid": "test-operator-001", "email": "operator@test.pk", "role": "franchise_operator", "cnic": "41303-7654321-2"},
{"uid": "test-shariah-001", "email": "shariah@test.pk", "role": "shariah_advisor"},
{"uid": "test-appna-001", "email": "doctor@appna.org", "role": "external_financier", "appna_member_id": "APPNA-12345"},
]
for u in users:
db.collection("users").document(u["uid"]).set({**u, "kyc_status": "verified", "created_at": firestore.SERVER_TIMESTAMP})
print(f" ✅ Seeded {len(users)} test users")
if __name__ == "__main__":
env = sys.argv[1].replace("--env=", "") if len(sys.argv) > 1 else "dev"
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred, {"projectId": f"musharakah-franchise-{env}"})
db = firestore.client()
print(f"Seeding {env} environment...")
seed_franchise_types(db)
seed_sample_pool(db)
seed_test_users(db)
print("✅ Seed complete!")
# ═══════════════════════════════════════════════════════
# TESTS — Profit Distribution Algorithm
# Run: pytest services/financial-engine/tests/ -v
# ═══════════════════════════════════════════════════════
import pytest
from decimal import Decimal
from algorithms.profit_distribution import (
calculate_distribution, generate_diminishing_schedule, PartnerShare
)
@pytest.fixture
def sample_partners():
return [
PartnerShare(user_id="community-1", partner_type="community_investor",
capital_contributed=Decimal("200000"), capital_percentage=Decimal("40"),
profit_ratio=Decimal("40"), zakat_opt_in=True),
PartnerShare(user_id="financier-1", partner_type="external_financier",
capital_contributed=Decimal("200000"), capital_percentage=Decimal("40"),
profit_ratio=Decimal("30")),
PartnerShare(user_id="operator-1", partner_type="franchise_operator",
capital_contributed=Decimal("50000"), capital_percentage=Decimal("10"),
profit_ratio=Decimal("20")), # Higher profit ratio rewards active management
PartnerShare(user_id="manager-1", partner_type="managing_partner",
capital_contributed=Decimal("50000"), capital_percentage=Decimal("10"),
profit_ratio=Decimal("10")),
]
class TestProfitDistribution:
def test_profit_shares_sum_correctly(self, sample_partners):
"""All profit distributions + platform fee = net profit."""
results = calculate_distribution(
pool_id="TEST-001", period="2026-Q1",
total_revenue=Decimal("200000"), total_expenses=Decimal("50000"),
partners=sample_partners, platform_fee_pct=Decimal("5"),
)
total_distributed = sum(r.gross_amount for r in results)
net = Decimal("150000") * Decimal("0.95") # After 5% fee
assert abs(total_distributed - net) < Decimal("1") # Rounding tolerance
def test_loss_uses_capital_ratio_not_profit_ratio(self, sample_partners):
"""Shariah rule: Loss MUST be proportional to capital, never profit ratio."""
results = calculate_distribution(
pool_id="TEST-001", period="2026-Q1",
total_revenue=Decimal("50000"), total_expenses=Decimal("80000"),
partners=sample_partners,
)
# Loss = 30000. Community has 40% capital → should bear 12000
community = next(r for r in results if r.user_id == "community-1")
assert community.net_amount == Decimal("-12000.00")
assert community.is_profit == False
# Operator has 10% capital → bears 3000 (NOT 20% which is profit ratio)
operator = next(r for r in results if r.user_id == "operator-1")
assert operator.net_amount == Decimal("-3000.00")
def test_no_platform_fee_on_loss(self, sample_partners):
"""Platform should not charge fees when partnership is losing money."""
results = calculate_distribution(
pool_id="TEST-001", period="2026-Q1",
total_revenue=Decimal("10000"), total_expenses=Decimal("30000"),
partners=sample_partners,
)
assert all(r.platform_fee == Decimal("0") for r in results)
def test_zakat_deduction_prorated(self, sample_partners):
"""Zakat 2.5% annual should be prorated to quarterly (÷4)."""
results = calculate_distribution(
pool_id="TEST-001", period="2026-Q1",
total_revenue=Decimal("200000"), total_expenses=Decimal("50000"),
partners=sample_partners, period_months=3,
)
community = next(r for r in results if r.user_id == "community-1")
assert community.zakat_deducted > 0
# Quarterly zakat = gross * 2.5% * 3/12 = gross * 0.625%
expected_zakat = (community.gross_amount * Decimal("0.00625")).quantize(Decimal("0.01"))
assert community.zakat_deducted == expected_zakat
def test_zakat_not_deducted_if_not_opted_in(self, sample_partners):
"""Only partners who opt in should have Zakat deducted."""
results = calculate_distribution(
pool_id="TEST-001", period="2026-Q1",
total_revenue=Decimal("200000"), total_expenses=Decimal("50000"),
partners=sample_partners,
)
financier = next(r for r in results if r.user_id == "financier-1")
assert financier.zakat_deducted == Decimal("0")
def test_break_even_returns_empty(self, sample_partners):
"""Zero net profit/loss = no distributions."""
results = calculate_distribution(
pool_id="TEST-001", period="2026-Q1",
total_revenue=Decimal("100000"), total_expenses=Decimal("100000"),
partners=sample_partners,
)
assert len(results) == 0
class TestDiminishingMusharakah:
def test_full_buyout_reaches_100_percent(self):
"""After all periods, operator should own 100%."""
schedule = generate_diminishing_schedule(
total_units=100, buyout_period_months=36,
unit_price_method="book_value", initial_unit_price=Decimal("1000"),
)
last = schedule[-1]
assert last.operator_ownership_pct == Decimal("100.00")
assert last.financier_units_after == 0
def test_cumulative_payment_correct(self):
"""Total paid should equal units × price for book value method."""
schedule = generate_diminishing_schedule(
total_units=100, buyout_period_months=36,
unit_price_method="book_value", initial_unit_price=Decimal("1000"),
)
last = schedule[-1]
assert last.cumulative_paid == Decimal("100000.00") # 100 units × 1000
def test_fair_market_appreciates(self):
"""Fair market method should have increasing unit prices."""
schedule = generate_diminishing_schedule(
total_units=100, buyout_period_months=36,
unit_price_method="fair_market", initial_unit_price=Decimal("1000"),
appreciation_rate_annual=Decimal("10"),
)
assert schedule[-1].unit_price > schedule[0].unit_price
def test_ownership_monotonically_increases(self):
"""Operator ownership should only increase, never decrease."""
schedule = generate_diminishing_schedule(
total_units=100, buyout_period_months=36,
unit_price_method="book_value", initial_unit_price=Decimal("1000"),
)
for i in range(1, len(schedule)):
assert schedule[i].operator_ownership_pct >= schedule[i-1].operator_ownership_pct
# ═══════════════════════════════════════════════════════
# TESTS — Pool CRUD Operations
# ═══════════════════════════════════════════════════════
import pytest
from httpx import AsyncClient
from main import app
@pytest.fixture
def test_app():
return AsyncClient(app=app, base_url="http://test")
class TestPoolCreation:
@pytest.mark.asyncio
async def test_create_pool_valid(self, test_app):
resp = await test_app.post("/api/v1/pools", json={
"pool_name": {"en": "Test Pool", "ur": "ٹیسٹ پول"},
"platform": "homefranchise",
"pool_type": "musharakah_mutanaqisah",
"target_capital_pkr": 500000,
"minimum_investment_pkr": 10000,
"profit_sharing": {"community_pct": 40, "financier_pct": 30, "managing_pct": 15, "operator_pct": 10, "platform_pct": 5},
"franchise_type": "induction_cooking",
"target_region": {"province": "Sindh", "district": "Tharparkar"},
"description": {"en": "Test", "ur": "ٹیسٹ"},
})
assert resp.status_code == 201
data = resp.json()
assert data["pool_id"].startswith("MKP-2026-")
assert data["status"] == "draft"
@pytest.mark.asyncio
async def test_reject_profit_shares_not_100(self, test_app):
resp = await test_app.post("/api/v1/pools", json={
"pool_name": {"en": "Bad Pool"}, "platform": "homefranchise",
"pool_type": "shirkat_amwal", "target_capital_pkr": 100000,
"profit_sharing": {"community_pct": 40, "financier_pct": 30}, # Only 70%
"target_region": {"province": "Punjab"}, "description": {"en": "Test"},
})
assert resp.status_code == 422 # Validation error
@pytest.mark.asyncio
async def test_invest_below_minimum_rejected(self, test_app):
resp = await test_app.post("/api/v1/investments/contribute", json={
"pool_id": "MKP-2026-00001", "amount_pkr": 5000, # Below 10K minimum
"payment_method": "jazzcash",
})
assert resp.status_code == 400
@pytest.mark.asyncio
async def test_shariah_advisor_can_approve(self, test_app):
# With shariah_advisor auth header
resp = await test_app.post(
"/api/v1/pools/MKP-2026-00001/approve-shariah",
json={"approved": True, "notes": "Compliant with AAOIFI Std 12"},
headers={"Authorization": "Bearer shariah_advisor_token"}
)
assert resp.status_code == 200
# ═══════════════════════════════════════════
# STEP 1: GCP Project Setup
# ═══════════════════════════════════════════
gcloud projects create musharakah-franchise-platform
gcloud config set project musharakah-franchise-platform
gcloud services enable \
run.googleapis.com firestore.googleapis.com \
cloudbuild.googleapis.com secretmanager.googleapis.com \
aiplatform.googleapis.com documentai.googleapis.com \
pubsub.googleapis.com cloudscheduler.googleapis.com \
cloudtasks.googleapis.com
# ═══════════════════════════════════════════
# STEP 2: Create Pub/Sub Topics (Event Bus)
# ═══════════════════════════════════════════
for topic in user-registered kyc-verified bank-provisioned \
pool-created investment-committed contract-generated \
contract-signed pool-activated franchise-deployed \
report-submitted distribution-calculated distribution-executed \
ownership-transferred; do
gcloud pubsub topics create $topic
done
# ═══════════════════════════════════════════
# STEP 3: Build & Deploy Services
# ═══════════════════════════════════════════
SERVICES="auth-service banking-gateway musharakah-engine \
franchise-engine contract-engine financial-engine \
ai-engine appna-gateway notification-engine"
for svc in $SERVICES; do
cd services/$svc
gcloud builds submit --tag gcr.io/musharakah-franchise-platform/$svc
gcloud run deploy $svc \
--image gcr.io/musharakah-franchise-platform/$svc \
--region asia-south1 --platform managed \
--set-env-vars GCP_PROJECT=musharakah-franchise-platform
cd ../..
done
# ═══════════════════════════════════════════
# STEP 4: Cloud Scheduler (Quarterly Distribution)
# ═══════════════════════════════════════════
gcloud scheduler jobs create http quarterly-distribution \
--schedule="0 2 1 1,4,7,10 *" \
--uri="https://financial-engine-xxx.run.app/api/v1/finance/distribute/calculate-all" \
--http-method=POST \
--time-zone="Asia/Karachi"
# Daily bank reconciliation
gcloud scheduler jobs create http daily-reconciliation \
--schedule="0 3 * * *" \
--uri="https://banking-gateway-xxx.run.app/api/v1/banking/reconcile" \
--http-method=POST
# ═══════════════════════════════════════════
# STEP 5: Frontend Deploy
# ═══════════════════════════════════════════
cd frontend/web-app
npm run build
firebase deploy --only hosting# GCP GCP_PROJECT_ID=musharakah-franchise-platform GCP_REGION=asia-south1 # Firebase FIREBASE_API_KEY=xxx FIREBASE_AUTH_DOMAIN=musharakah-franchise-platform.firebaseapp.com # AI VERTEX_AI_LOCATION=asia-south1 GEMINI_MODEL=gemini-2.5-pro ANTHROPIC_API_KEY=xxx CLAUDE_MODEL=claude-sonnet-4-5-20250929 # Banking — Islamic MEEZAN_API_URL=https://api.meezanbank.com/v1 MEEZAN_API_KEY=xxx BANKISLAMI_API_URL=https://api.bankislami.com.pk/v1 BANKISLAMI_API_KEY=xxx # Banking — Government NBP_API_URL=https://api.nbp.com.pk/corporate/v1 RAAST_API_URL=https://api.raast.sbp.org.pk/v1 ZTBL_API_URL=https://api.ztbl.com.pk/agri/v1 # Mobile Money JAZZCASH_MERCHANT_ID=xxx JAZZCASH_PASSWORD=xxx JAZZCASH_SALT=xxx EASYPAISA_STORE_ID=xxx EASYPAISA_TOKEN=xxx # International STRIPE_SECRET_KEY=xxx STRIPE_WEBHOOK_SECRET=xxx # APPNA APPNA_SSO_CLIENT_ID=xxx APPNA_SSO_SECRET=xxx OFAC_API_KEY=xxx # Notifications TWILIO_ACCOUNT_SID=xxx TWILIO_AUTH_TOKEN=xxx SENDGRID_API_KEY=xxx WHATSAPP_BUSINESS_TOKEN=xxx # NADRA NADRA_API_URL=https://api.nadra.gov.pk/e-sahulat/v1 NADRA_API_KEY=xxx
• PKR 10,000 minimum entry — accessible to Tier 1 households
• No interest (Riba-free) — purely Halal returns
• Mobile money integration — JazzCash from any corner shop
• Franchise in own village — no migration needed
• 3-5 year path to full franchise ownership
• Women's groups earn independent income
• 50M households addressable across 7 tiers
• Invest in hometown from Houston/Chicago/NYC
• $500 minimum — physician-friendly amounts
• US-compliant: OFAC, FATCA, IRS reporting built-in
• Real-time impact dashboard — see franchise working
• Not charity — real Shariah-compliant ROI (15-40%)
• Connect with hometown community digitally
• 55,000 physicians × $10K avg = $550M potential
• New asset class: asset-backed, Shariah-compliant
• PKR 67B addressable from pension/investment funds
• Diversification away from govt bonds + stocks
• Real economic impact — verifiable at unit level
• AAOIFI Standard 12 compliant structures
• Diminishing Musharakah provides clean exit path
• Carbon credit potential (solar franchises)
• Convert interest-based loans to Musharakah
• Add franchise revenue to agricultural income
• 890,000 existing farmers as pipeline
• Food drying creates 8-15× value from harvest waste
• Solar reduces energy costs to zero after payback
• ZTBL Murabaha bridge = Shariah-compliant equipment
• Existing ZTBL relationship lowers onboarding friction
• KaamyabPakistan: Innovation hubs funded via Social Impact Musharakah
• YouInvent: Patent + prototype funding via Innovation Musharakah
• HomeFranchise: Franchise units funded via Franchise Musharakah
• NoCodeAI: AI platform development via Technology Musharakah
• All 4 platforms connected, single user identity
• PKR 500-5,000/month SaaS feeds recurring revenue
• Co-located datacenters next to power plants
• 50M households × 7 tiers = PKR 42.6T annual GDP impact
• 100,000+ franchise units by 2030
• $2B+ diaspora remittances channeled productively
• 890K farmers diversify beyond agriculture
• Women workforce participation increase
• Indoor air pollution deaths reduced (induction cooking)
• Carbon credits from solar + clean cooking