# Module Dependency Graph

## Visual Hierarchy

```
┌─────────────────────────────────────────────────────────┐
│                    Root Project                          │
│                     (Amethyst)                           │
└─────────────────────────────────────────────────────────┘
                          │
         ┌────────────────┼────────────────┬────────────┐
         │                │                │            │
         ▼                ▼                ▼            ▼
┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌──────────┐
│  :amethyst  │  │ :desktopApp │  │ :benchmark  │  │:ammolite │
│  (Android)  │  │   (JVM)     │  │  (Android)  │  │ (Support)│
└─────────────┘  └─────────────┘  └─────────────┘  └──────────┘
       │                │                │
       │                │                │
       └────────────────┼────────────────┘
                        │
                        ▼
                ┌─────────────┐
                │  :commons   │
                │  (KMP UI)   │
                │             │
                │ jvmAndroid  │
                │  /      \   │
                │ jvm   android│
                └─────────────┘
                        │
                        │
                        ▼
                ┌─────────────┐
                │  :quartz    │
                │(KMP Library)│
                │             │
                │ commonMain  │
                │     │       │
                │ jvmAndroid  │
                │  /  |  \    │
                │jvm and ios  │
                └─────────────┘
```

## Module Details

### :quartz (KMP Nostr Library)

**Type:** Kotlin Multiplatform Library
**Targets:** JVM, Android, iOS (iosX64, iosArm64, iosSimulatorArm64)
**Dependencies:**

- External: secp256k1, jackson, okhttp, kotlinx.coroutines, kotlinx.collections.immutable
- Source sets: commonMain → jvmAndroid → {androidMain, jvmMain}, iosMain

**Role:** Core Nostr protocol implementation, shared across all platforms

### :commons (Shared UI Components)

**Type:** Kotlin Multiplatform Library
**Targets:** JVM, Android
**Dependencies:**

- Module: `:quartz`
- External: Compose Multiplatform, Material3, kotlinx.collections.immutable
- Source sets: commonMain → jvmAndroid → {androidMain, jvmMain}

**Role:** Shared Compose UI components for Desktop and Android

### :desktopApp (Desktop Application)

**Type:** JVM Application
**Targets:** JVM (Desktop)
**Dependencies:**

- Modules: `:commons`, `:quartz`
- External: Compose Desktop, kotlinx.coroutines.swing

**Role:** Desktop-specific navigation, layouts, and entry point

### :amethyst (Android Application)

**Type:** Android Application
**Targets:** Android
**Dependencies:**

- Modules: `:commons`, `:quartz`, `:ammolite`
- External: Android SDK, AndroidX, Firebase, Tor

**Role:** Android-specific navigation, layouts, and entry point

### :benchmark (Android Benchmark)

**Type:** Android Library
**Targets:** Android
**Dependencies:**

- Modules: `:commons`, `:quartz`
- External: AndroidX Benchmark

**Role:** Performance benchmarking for Android builds

### :ammolite (Support Module)

**Type:** Android Library
**Targets:** Android
**Dependencies:** Android-specific utilities

**Role:** Android support utilities for amethyst

## Dependency Flow Patterns

### Desktop Build Chain

```
:desktopApp → :commons (jvmMain) → :quartz (jvmMain)
                                         ↓
                                   jvmAndroid
                                         ↓
                                   commonMain
```

### Android Build Chain

```
:amethyst → :commons (androidMain) → :quartz (androidMain)
    ↓                                      ↓
:ammolite                            jvmAndroid
                                         ↓
                                   commonMain
```

## Source Set Dependencies

### :quartz Source Sets

```
commonMain (base)
    ├─ jvmAndroid (shared JVM code)
    │   ├─ androidMain (Android platform)
    │   └─ jvmMain (Desktop platform)
    └─ iosMain (iOS platform)
        ├─ iosX64Main
        ├─ iosArm64Main
        └─ iosSimulatorArm64Main
```

**Key Dependencies per Source Set:**

- **commonMain**: secp256k1-kmp, kotlinx.coroutines, collection, immutable collections
- **jvmAndroid**: jackson, okhttp, url-detector, rfc3986
- **androidMain**: secp256k1-kmp-jni-android, lazysodium-android, jna (aar)
- **jvmMain**: secp256k1-kmp-jni-jvm, lazysodium-java, jna (jar)

### :commons Source Sets

```
commonMain (base UI)
    └─ jvmAndroid (shared JVM UI)
        ├─ androidMain (Android UI utilities)
        └─ jvmMain (Desktop UI utilities)
```

**Key Dependencies per Source Set:**

- **commonMain**: Compose Multiplatform, Material3, :quartz
- **jvmAndroid**: url-detector
- **androidMain**: AndroidX Compose tooling
- **jvmMain**: Compose Desktop

## Critical Dependency Patterns

### 1. secp256k1 Variants

```kotlin
// commonMain - API only
api(libs.secp256k1.kmp.common)

// androidMain - JNI Android
api(libs.secp256k1.kmp.jni.android)

// jvmMain - JNI JVM
implementation(libs.secp256k1.kmp.jni.jvm)
```

**Why:** Different JNI bindings for Android vs Desktop JVM

### 2. JNA Variants (for LibSodium)

```kotlin
// androidMain
implementation("com.goterl:lazysodium-android:5.2.0@aar")
implementation("net.java.dev.jna:jna:5.18.1@aar")

// jvmMain
implementation(libs.lazysodium.java)
implementation(libs.jna)  // JAR variant
```

**Why:** Android needs AAR packaging, JVM needs JAR

### 3. Compose Alignment

```kotlin
// commons/build.gradle.kts
implementation(compose.ui)              // Compose Multiplatform BOM
implementation(compose.material3)

// Version catalog alignment
composeMultiplatform = "1.9.3"
composeBom = "2025.12.01"  // AndroidX Compose
```

**Why:** Two Compose ecosystems (Multiplatform + AndroidX) must align

## Dependency Configuration Types

### API vs Implementation

**Use `api` when:**

- Dependency types appear in module's public API
- Used in expect/actual declarations visible to consumers
- Example: `secp256k1-kmp-common` in quartz (public types)

**Use `implementation` when:**

- Internal implementation detail
- Not exposed to module consumers
- Example: `okhttp` in quartz (internal network client)

### Example from quartz

```kotlin
// Public API - exposed to consumers
api(libs.secp256k1.kmp.common)
api(libs.jackson.module.kotlin)  // Event serialization public

// Internal implementation
implementation(libs.okhttp)
implementation(libs.kotlinx.coroutines.core)
```

## Transitive Dependency Impact

### When :desktopApp depends on :commons

- Gets `:quartz` transitively (via :commons)
- Gets `secp256k1-kmp-jvm` transitively (via :quartz jvmMain)
- Does NOT get Android-specific dependencies (scoped to androidMain)

### When :amethyst depends on :commons

- Gets `:quartz` transitively (via :commons)
- Gets `secp256k1-kmp-jni-android` transitively (via :quartz androidMain)
- Does NOT get JVM/Desktop-specific dependencies (scoped to jvmMain)

## Verifying Dependencies

### Check Module Dependencies

```bash
./gradlew :desktopApp:dependencies
./gradlew :amethyst:dependencies
```

### Check Specific Library

```bash
./gradlew dependencyInsight --dependency secp256k1
./gradlew dependencyInsight --dependency compose-ui
```

### Visualize with Build Scan

```bash
./gradlew :desktopApp:dependencies --scan
# Opens interactive dependency graph in browser
```

## Common Dependency Issues

### Issue 1: Wrong secp256k1 Variant in Desktop

**Symptom:** `UnsatisfiedLinkError: no secp256k1jni in java.library.path`
**Cause:** Desktop using Android JNI variant
**Fix:** Ensure jvmMain uses `secp256k1-kmp-jni-jvm`

### Issue 2: Compose Version Mismatch

**Symptom:** `IllegalStateException: Version mismatch`
**Cause:** Compose Multiplatform plugin vs runtime version mismatch
**Fix:** Align `composeMultiplatform` version in libs.versions.toml with Kotlin plugin

### Issue 3: Duplicate JNA Classes

**Symptom:** `DuplicateClassException: com.sun.jna.Native`
**Cause:** Both JAR and AAR JNA variants in classpath
**Fix:** Use AAR (@aar) in androidMain, JAR in jvmMain (never in shared source sets)
