# Backend-Architektur im Manacore Monorepo

Diese Dokumentation beschreibt die Backend-Implementierungen aller Projekte im Manacore Monorepo.

## Übersicht

Das Monorepo enthält 6 Hauptprojekte mit unterschiedlichen Backend-Architekturen:

| Projekt | Backend-Typ | Datenbank | Status |
|---------|-------------|-----------|--------|
| **Maerchenzauber** | NestJS v10 | Supabase (PostgreSQL) | Aktiv |
| **Manadeck** | NestJS v11 | PostgreSQL + Drizzle ORM | Aktiv |
| **Uload** | NestJS v11 | PostgreSQL + Drizzle ORM | Aktiv |
| **Picture** | Kein Backend | - | Frontend-only |
| **Memoro** | Kein Backend | - | Frontend-only |
| **Manacore** | Kein Backend (extern) | - | Externes Backend |

---

## 1. Maerchenzauber

**Pfad:** `/maerchenzauber/apps/backend`

**Zweck:** KI-gestützte Kindergeschichten-Generierung mit benutzerdefinierten Charakteren.

### Technologie-Stack

- **Framework:** NestJS 10.0.0
- **Datenbank:** Supabase (PostgreSQL)
- **ORM:** `@supabase/supabase-js` v2.81.1
- **AI-Services:** Azure OpenAI, Google Gemini, Replicate

### Architektur

```
apps/backend/
├── src/
│   ├── character/          # Charakter-Modul
│   │   ├── character.controller.ts
│   │   ├── character.service.ts
│   │   └── character.repository.ts
│   ├── story/              # Story-Modul
│   │   ├── story.controller.ts
│   │   ├── story.service.ts
│   │   └── pipelines/      # Story-Generierung-Pipelines
│   ├── core/               # Kern-Services
│   │   └── services/
│   │       └── prompting.service.ts
│   ├── settings/           # Benutzereinstellungen
│   ├── health/             # Health-Checks
│   └── feedback/           # Feedback-Modul
```

### Datenbank-Schema

**Tabellen:**
- `characters` - Benutzercharaktere
- `stories` - Generierte Geschichten
- `story_collections` - Sammlungen von Geschichten
- `user_settings` - Benutzereinstellungen

**Sicherheit:** Row-Level Security (RLS) für Datenzugriffskontrolle

### Authentifizierung

Mana Core Integration via `@mana-core/nestjs-integration`:

```typescript
// Beispiel: Geschützter Endpoint
@UseGuards(AuthGuard)
@Get('characters')
async getCharacters(@CurrentUser() user: User) {
  return this.characterService.findByUser(user.id);
}
```

**Auth-Endpoint:** `https://mana-core-middleware-111768794939.europe-west3.run.app`

### AI-Services

| Service | Verwendung | API |
|---------|------------|-----|
| Azure OpenAI (GPT-4) | Story-Generierung | `MAERCHENZAUBER_AZURE_OPENAI_ENDPOINT` |
| Google Gemini | Charakter-Generierung | `GOOGLE_GEMINI_API_KEY` |
| Replicate (Flux) | Bildgenerierung | `REPLICATE_API_TOKEN` |

### File Storage

- **Provider:** Supabase Storage
- **Bucket:** `maerchenzauber`
- **Verwendung:** Charakter- und Story-Bilder

### Deployment

- **Plattform:** Google Cloud Run
- **Region:** europe-west3
- **URL:** `https://storyteller-backend-111768794939.europe-west3.run.app`
- **Port:** 3002 (Development)

---

## 2. Manadeck

**Pfad:** `/manadeck/apps/backend`

**Zweck:** KI-gestützte Lernkarten-Generierung (Flashcards, Quizzes, Mixed).

### Technologie-Stack

- **Framework:** NestJS 11.0.1
- **Datenbank:** PostgreSQL 16
- **ORM:** Drizzle ORM
- **AI-Service:** Google Gemini API

### Architektur

```
apps/backend/
├── src/
│   ├── api.controller.ts       # Haupt-API-Endpoints
│   ├── public.controller.ts    # Öffentliche Endpoints
│   ├── health.controller.ts    # Health-Checks
│   ├── ai.service.ts           # AI-Generierung
│   └── repositories/
│       ├── deck.repository.ts
│       ├── card.repository.ts
│       ├── user-stats.repository.ts
│       └── deck-template.repository.ts
```

### Datenbank-Package

Das Datenbank-Schema ist in einem separaten Package ausgelagert:

**Pfad:** `/packages/manadeck-database`

```typescript
// Verwendung im Backend
import { db, schema } from '@manacore/manadeck-database';

const decks = await db.query.decks.findMany({
  where: eq(schema.decks.userId, userId)
});
```

**Drizzle-Konfiguration:**
```typescript
// drizzle.config.ts
export default {
  schema: './src/schema/*',
  out: './migrations',
  driver: 'pg',
  dbCredentials: {
    connectionString: process.env.DATABASE_URL
  }
};
```

### Authentifizierung

```typescript
import { AuthGuard, CurrentUser } from '@mana-core/nestjs-integration';

@Controller('api')
@UseGuards(AuthGuard)
export class ApiController {
  @Post('decks')
  async createDeck(@CurrentUser() user: User, @Body() dto: CreateDeckDto) {
    // Credit-Prüfung und Deck-Erstellung
  }
}
```

### Credit-System

Integration mit Mana Core Credit Service:

```typescript
import { CreditClientService } from '@mana-core/nestjs-integration';

@Injectable()
export class AiService {
  constructor(private creditClient: CreditClientService) {}

  async generateDeck(userId: string, input: GenerateInput) {
    // 1. Credit-Balance prüfen
    const hasCredits = await this.creditClient.checkBalance(userId, 'DECK_CREATION');

    // 2. Deck generieren
    const deck = await this.generateWithGemini(input);

    // 3. Credits abziehen
    await this.creditClient.deduct(userId, 'DECK_CREATION');

    return deck;
  }
}
```

### AI-Generierung

**Unterstützte Kartentypen:**
- `text` - Textbasierte Karten
- `flashcard` - Klassische Lernkarten
- `quiz` - Multiple-Choice Quiz
- `mixed` - Gemischte Inhalte

**Schwierigkeitsgrade:**
- `beginner`
- `intermediate`
- `advanced`

### Docker-Setup

```yaml
# docker-compose.yml (Lokale Entwicklung)
services:
  postgres:
    image: postgres:16
    ports:
      - "5433:5432"
    environment:
      POSTGRES_DB: manadeck
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres

  pgadmin:
    image: dpage/pgadmin4
    ports:
      - "5050:80"
```

### Deployment

- **Docker Image:** Multi-stage Build (Node 18-alpine)
- **Port:** 8080
- **Health-Check:** `/health`

---

## 3. Uload

**Pfad:** `/uload/apps/backend`

**Zweck:** URL-Shortener mit Link-Analytics.

### Technologie-Stack

- **Framework:** NestJS 11.0.1
- **Datenbank:** PostgreSQL 16
- **ORM:** Drizzle ORM
- **Cache:** Redis (optional)

### Architektur

```
uload/apps/backend/
├── src/
│   ├── main.ts
│   ├── app.module.ts
│   ├── config/
│   │   └── validation.schema.ts
│   ├── controllers/
│   │   ├── redirect.controller.ts    # GET /:code (public redirect)
│   │   ├── links.controller.ts       # CRUD /api/links
│   │   ├── analytics.controller.ts   # GET /api/analytics
│   │   └── health.controller.ts
│   ├── services/
│   │   ├── links.service.ts
│   │   ├── redirect.service.ts
│   │   └── analytics.service.ts
│   └── database/
│       ├── database.module.ts
│       └── repositories/
│           ├── link.repository.ts
│           └── click.repository.ts
├── Dockerfile
└── package.json
```

### Datenbank-Package

**Pfad:** `/packages/uload-database`

```typescript
// Verwendung im Backend
import { db, links, clicks, eq, desc } from '@manacore/uload-database';

const userLinks = await db.query.links.findMany({
  where: eq(links.userId, userId),
  orderBy: desc(links.createdAt)
});
```

### API Endpoints

| Endpoint | Method | Auth | Beschreibung |
|----------|--------|------|--------------|
| `/:code` | GET | Public | Redirect zu Original-URL |
| `/api/links` | GET | Protected | Liste aller Links |
| `/api/links` | POST | Protected | Link erstellen |
| `/api/links/:id` | GET | Protected | Link Details |
| `/api/links/:id` | PATCH | Protected | Link aktualisieren |
| `/api/links/:id` | DELETE | Protected | Link löschen |
| `/api/analytics/:linkId` | GET | Protected | Link-Statistiken |
| `/health` | GET | Public | Health Check |

### Authentifizierung

Mana Core Integration via `@mana-core/nestjs-integration`:

```typescript
import { AuthGuard, CurrentUser } from '@mana-core/nestjs-integration';

@Controller('api/links')
@UseGuards(AuthGuard)
export class LinksController {
  @Get()
  async getLinks(@CurrentUser() user: any) {
    return this.linksService.getLinks(user.sub);
  }
}
```

### Deployment

- **Docker Image:** Multi-stage Build (Node 20-alpine)
- **Port:** 3003
- **Health-Check:** `/health`

---

## 4. Picture

**Pfad:** `/picture`

**Zweck:** Bild- und Medienverwaltung.

### Architektur

**Kein dediziertes Backend.** Picture verwendet:

- SvelteKit Server-Routes für Backend-Logik
- Mana Core für Authentifizierung
- Shared Packages aus `/packages`

```
picture/
├── apps/
│   ├── mobile/           # React Native Expo
│   ├── web/              # SvelteKit
│   └── landing/          # Astro
└── packages/
    ├── design-tokens/    # Design System
    ├── mobile-ui/        # Mobile UI Components
    └── shared/           # Utilities
```

---

## 5. Memoro

**Pfad:** `/memoro`

**Zweck:** Legacy-Content und Memory-Preservation.

### Architektur

**Kein dediziertes Backend.** Memoro verwendet:

- SvelteKit Server-Routes
- Mana Core für Authentifizierung
- Supabase (Legacy-Konfiguration vorhanden)

```
memoro/
├── apps/
│   ├── mobile/
│   ├── web/
│   └── landing/
└── supabase/             # Legacy Supabase Config
```

---

## 6. Manacore

**Pfad:** `/manacore`

**Zweck:** Core-Authentifizierung und Credit-System.

### Architektur

Das Manacore-Backend ist **extern gehostet** und nicht Teil des Monorepos:

- **URL:** `https://mana-core-middleware-111768794939.europe-west3.run.app`
- **Integration:** Via `@mana-core/nestjs-integration` Package

```
manacore/
├── apps/
│   ├── mobile/           # Auth-Flow UI
│   ├── web/              # Dashboard
│   └── landing/          # Marketing
```

---

## Shared Packages für Backend

### @manacore/manadeck-database

PostgreSQL-Datenbankschema für Manadeck.

```
packages/manadeck-database/
├── src/
│   ├── schema/           # Drizzle Schema
│   ├── client.ts         # DB Client
│   └── index.ts          # Exports
├── drizzle.config.ts
└── docker-compose.yml
```

### @manacore/uload-database

PostgreSQL-Datenbankschema für Uload URL-Shortener.

```
packages/uload-database/
├── src/
│   ├── schema/
│   │   ├── users.ts
│   │   ├── links.ts
│   │   ├── clicks.ts
│   │   ├── tags.ts
│   │   ├── workspaces.ts
│   │   ├── accounts.ts
│   │   └── relations.ts
│   ├── client.ts         # DB Client
│   └── index.ts          # Exports
├── drizzle.config.ts
└── docker-compose.yml
```

### @mana-core/nestjs-integration

Externe Dependency für Backend-Integration:

```typescript
// Installation via git
"@mana-core/nestjs-integration": "git+https://github.com/mana-core/nestjs-integration.git"
```

**Bereitgestellte Features:**
- `AuthGuard` - JWT-Authentifizierung
- `@CurrentUser()` - User-Context Decorator
- `CreditClientService` - Credit-Operationen
- Konfigurationsmodule

---

## Authentifizierungs-Pattern

Alle Projekte nutzen zentrale **Mana Core Authentifizierung**:

```
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│    Frontend     │────▶│  Project Backend │────▶│   Mana Core     │
│  (Web/Mobile)   │     │  (NestJS/etc.)   │     │   Middleware    │
└─────────────────┘     └─────────────────┘     └─────────────────┘
        │                        │                       │
        │                        │                       │
        ▼                        ▼                       ▼
   shared-auth              AuthGuard              JWT Validation
   shared-auth-ui          @CurrentUser            Credit Service
   shared-auth-stores      CreditClient            User Management
```

### Frontend-Integration

```typescript
// Shared Auth Store (Svelte)
import { authStore } from '@manacore/shared-auth-stores';

// Login
await authStore.login(email, password);

// Token für API-Requests
const token = authStore.getAccessToken();
```

### Backend-Integration

```typescript
// NestJS Module Setup
@Module({
  imports: [
    ManaCoreModule.forRoot({
      serviceKey: process.env.MANA_CORE_SERVICE_KEY,
      baseUrl: process.env.MANA_CORE_URL,
    }),
  ],
})
export class AppModule {}
```

---

## Datenbank-Migrationen

### Manadeck (Drizzle)

```bash
# Migration generieren
pnpm --filter @manacore/manadeck-database drizzle-kit generate

# Migration ausführen
pnpm --filter @manacore/manadeck-database drizzle-kit push
```

### Maerchenzauber (Supabase)

```bash
# Supabase CLI
supabase migration new <name>
supabase db push
```

---

## Umgebungsvariablen

### Maerchenzauber Backend

```env
# Supabase
SUPABASE_URL=
SUPABASE_SERVICE_ROLE_KEY=

# Mana Core
MANA_CORE_URL=https://mana-core-middleware-111768794939.europe-west3.run.app
MANA_CORE_SERVICE_KEY=

# AI Services
MAERCHENZAUBER_AZURE_OPENAI_ENDPOINT=
AZURE_OPENAI_API_KEY=
GOOGLE_GEMINI_API_KEY=
REPLICATE_API_TOKEN=
```

### Manadeck Backend

```env
# Database
DATABASE_URL=postgresql://postgres:postgres@localhost:5433/manadeck

# Mana Core
MANA_CORE_URL=
MANA_CORE_SERVICE_KEY=

# AI
GOOGLE_GEMINI_API_KEY=

# Server
PORT=8080
```

### Uload

```env
# Database
DATABASE_URL=postgresql://...

# Redis
REDIS_URL=redis://localhost:6379

# PocketBase
POCKETBASE_URL=
```

---

## Lokale Entwicklung

### Maerchenzauber Backend

```bash
cd maerchenzauber/apps/backend
pnpm install
pnpm run start:dev
# Läuft auf Port 3002
```

### Manadeck Backend

```bash
# 1. Datenbank starten
cd packages/manadeck-database
docker-compose up -d

# 2. Backend starten
cd manadeck/apps/backend
pnpm install
pnpm run start:dev
# Läuft auf Port 8080
```

### Uload

```bash
cd uload
docker-compose up -d  # PostgreSQL + Redis
pnpm install
pnpm run dev
```

---

## Zusammenfassung

Das Manacore Monorepo verwendet verschiedene Backend-Strategien:

1. **Full Backend (NestJS):** Maerchenzauber, Manadeck - Für komplexe Geschäftslogik und AI-Integration
2. **Embedded Database (PocketBase):** Uload - Für einfache CRUD-Operationen
3. **Frontend-only:** Picture, Memoro - Server-Routes in SvelteKit
4. **External Backend:** Manacore - Zentrale Auth/Credit-Services

Alle Projekte teilen sich:
- Gemeinsame Authentifizierung via Mana Core
- Shared Packages für UI, Auth, Types
- Einheitliches Deployment-Pattern (Docker + Cloud Run)

---

## Vereinheitlichungs-Roadmap

### Aktuelle Fragmentierung

| Aspekt | Maerchenzauber | Manadeck | Uload |
|--------|----------------|----------|-------|
| Framework | NestJS v10 | NestJS v11 | PocketBase |
| Datenbank | Supabase | PostgreSQL | PocketBase + PG |
| ORM | @supabase/js | Drizzle | Drizzle |
| Auth | Mana Core | Mana Core | PocketBase + Mana Core |

---

### Strategie 1: Shared NestJS Backend Package

**Ziel:** Ein gemeinsames `@manacore/shared-backend` Package mit wiederverwendbaren Modulen.

```
packages/shared-backend/
├── src/
│   ├── auth/
│   │   ├── auth.module.ts
│   │   ├── auth.guard.ts
│   │   └── current-user.decorator.ts
│   ├── database/
│   │   ├── database.module.ts
│   │   ├── drizzle.provider.ts
│   │   └── base.repository.ts
│   ├── health/
│   │   └── health.module.ts
│   ├── credits/
│   │   └── credits.module.ts
│   └── common/
│       ├── filters/
│       ├── interceptors/
│       └── pipes/
```

**Vorteile:**
- Einheitliche Auth-Integration
- Wiederverwendbare Module
- Konsistente Error-Handling

**Aufwand:** Mittel

---

### Strategie 2: Einheitliche Datenbank-Strategie

#### Option A: Alles auf Drizzle + PostgreSQL (Empfohlen)

```typescript
// packages/shared-database/src/base-schema.ts
export const baseColumns = {
  id: uuid('id').primaryKey().defaultRandom(),
  createdAt: timestamp('created_at').defaultNow(),
  updatedAt: timestamp('updated_at').defaultNow(),
  userId: text('user_id').notNull(),
};

// Projekt-spezifische Erweiterung
// maerchenzauber/database/schema/characters.ts
import { baseColumns } from '@manacore/shared-database';

export const characters = pgTable('characters', {
  ...baseColumns,
  name: text('name').notNull(),
  traits: jsonb('traits'),
});
```

**Migration von Supabase:**
- Supabase ist PostgreSQL → Schema kann übernommen werden
- RLS-Policies in Application-Layer verschieben
- Storage → S3/Cloudflare R2

#### Option B: Alles auf Supabase

```typescript
// packages/shared-supabase/src/client.ts
export const createProjectClient = (project: 'maerchenzauber' | 'manadeck' | 'uload') => {
  return createClient(
    process.env[`${project.toUpperCase()}_SUPABASE_URL`],
    process.env[`${project.toUpperCase()}_SUPABASE_KEY`]
  );
};
```

**Vorteile Supabase:**
- Eingebaute Auth (optional nutzbar)
- Storage inklusive
- Realtime-Subscriptions
- Edge Functions möglich

**Nachteile Supabase:**
- Vendor Lock-in
- Weniger Kontrolle über Schema

**Empfehlung:** Drizzle + PostgreSQL wegen Type-Safety, moderner API und keinem Vendor Lock-in.

---

### Strategie 3: Einheitliche Monorepo Backend Struktur

**Ziel-Architektur:**

```
packages/
├── shared-backend/           # Gemeinsame NestJS Module
│   ├── auth/
│   ├── database/
│   ├── health/
│   └── credits/
├── shared-database/          # Drizzle Basis-Schema
│   ├── base-schema.ts
│   ├── migrations/
│   └── client.ts
├── maerchenzauber-database/  # Projekt-Schema
├── manadeck-database/        # ✓ Existiert bereits
└── uload-database/           # Neu

apps/
├── maerchenzauber-backend/   # Nutzt shared-backend
├── manadeck-backend/         # Nutzt shared-backend
└── uload-backend/            # Neues NestJS Backend (ersetzt PocketBase)
```

---

### Strategie 4: Shared Backend als Service-Layer

**Ziel:** Gemeinsamer Service-Layer, projekt-spezifische Controller.

```typescript
// packages/shared-backend/src/services/ai.service.ts
@Injectable()
export class BaseAiService {
  constructor(
    private gemini: GeminiClient,
    private credits: CreditService,
  ) {}

  protected async generateWithCredits<T>(
    userId: string,
    operation: string,
    generator: () => Promise<T>
  ): Promise<T> {
    await this.credits.check(userId, operation);
    const result = await generator();
    await this.credits.deduct(userId, operation);
    return result;
  }
}

// maerchenzauber/backend/src/story/story.service.ts
@Injectable()
export class StoryService extends BaseAiService {
  async generateStory(userId: string, input: StoryInput) {
    return this.generateWithCredits(userId, 'STORY_GENERATION', async () => {
      // Projekt-spezifische Logik
    });
  }
}
```

---

### Strategie 5: API-Gateway Pattern (Optional)

**Ziel:** Ein zentrales Gateway vor allen Backends.

```
                    ┌─────────────────┐
                    │   API Gateway   │
                    │  (Kong/Traefik) │
                    └────────┬────────┘
                             │
        ┌────────────────────┼────────────────────┐
        │                    │                    │
        ▼                    ▼                    ▼
┌───────────────┐   ┌───────────────┐   ┌───────────────┐
│ Maerchenzauber│   │   Manadeck    │   │    Uload      │
│    Backend    │   │    Backend    │   │   Backend     │
└───────────────┘   └───────────────┘   └───────────────┘
```

**Vorteile:**
- Zentrale Auth-Validierung
- Rate Limiting
- Request Logging
- Einheitliche API-Struktur

**Aufwand:** Hoch - Empfohlen erst bei Skalierungsbedarf

---

### Empfohlene Implementierungsreihenfolge

#### Phase 1: Shared Backend Package

**Priorität:** Hoch
**Aufwand:** 2-3 Wochen

Neues Package `packages/shared-backend/` mit:
- Auth Module (wraps @mana-core/nestjs-integration)
- Health Module
- Credits Module
- Base Repository Pattern
- Common Decorators, Guards, Filters

#### Phase 2: Datenbank-Vereinheitlichung

**Priorität:** Hoch
**Aufwand:** 3-4 Wochen

1. `packages/shared-database/` mit Drizzle Basis-Schema erstellen
2. Maerchenzauber von Supabase auf Drizzle migrieren
3. Uload PocketBase durch PostgreSQL + Drizzle ersetzen

#### Phase 3: Uload Backend Neubau (Optional)

**Priorität:** Mittel
**Aufwand:** 2-3 Wochen

PocketBase → NestJS Migration:
- Konsistenz mit anderen Projekten
- Bessere Integration mit Mana Core
- Einheitliches Deployment

---

### Optionen-Vergleich

| Option | Aufwand | Benefit | Empfehlung |
|--------|---------|---------|------------|
| Shared Backend Package | Mittel | Hoch | ✅ Priorität 1 |
| Drizzle überall | Mittel-Hoch | Hoch | ✅ Priorität 2 |
| Uload auf NestJS | Hoch | Mittel | ⚡ Optional |
| API Gateway | Sehr Hoch | Mittel | ⏳ Später |

---

### Quick Wins (sofort umsetzbar)

1. **NestJS Version angleichen** → Alle auf v11
2. **Einheitliche Health-Endpoints** → `/health`, `/health/ready`
3. **Gemeinsame ESLint/Prettier Config** → `@manacore/eslint-config-backend`
4. **Einheitliche Error-Response-Struktur:**

```typescript
// Einheitliches Error-Format für alle Backends
interface ApiError {
  statusCode: number;
  error: string;
  message: string;
  timestamp: string;
  path: string;
}
```

5. **Einheitliche Logging-Struktur:**

```typescript
// packages/shared-backend/src/logging/logger.service.ts
@Injectable()
export class AppLogger {
  log(context: string, message: string, meta?: Record<string, any>) {
    console.log(JSON.stringify({
      level: 'info',
      context,
      message,
      timestamp: new Date().toISOString(),
      ...meta,
    }));
  }
}
```

---

### Ziel-Architektur nach Vereinheitlichung

```
┌─────────────────────────────────────────────────────────────┐
│                     Shared Packages                          │
├─────────────────┬─────────────────┬─────────────────────────┤
│ shared-backend  │ shared-database │ shared-types            │
│ - AuthModule    │ - baseColumns   │ - ApiError              │
│ - HealthModule  │ - drizzleClient │ - User                  │
│ - CreditsModule │ - migrations    │ - CreditOperation       │
│ - BaseRepo      │                 │                         │
└────────┬────────┴────────┬────────┴────────┬────────────────┘
         │                 │                 │
         ▼                 ▼                 ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│  Maerchenzauber │ │    Manadeck     │ │     Uload       │
│     Backend     │ │    Backend      │ │    Backend      │
├─────────────────┤ ├─────────────────┤ ├─────────────────┤
│ NestJS v11      │ │ NestJS v11      │ │ NestJS v11      │
│ PostgreSQL      │ │ PostgreSQL      │ │ PostgreSQL      │
│ Drizzle ORM     │ │ Drizzle ORM     │ │ Drizzle ORM     │
│ Port: 3002      │ │ Port: 8080      │ │ Port: 3003      │
└─────────────────┘ └─────────────────┘ └─────────────────┘
         │                 │                 │
         └─────────────────┼─────────────────┘
                           ▼
                ┌─────────────────────┐
                │     Mana Core       │
                │   (Auth + Credits)  │
                └─────────────────────┘
```
