---
title: "FitaLabs Gateway — 1P Bundle + LiteLLM Proxy Journey"
description: "Documentation: FitaLabs Gateway — 1P Bundle + LiteLLM Proxy Journey"
type: reference
tags: [infra, gateway, litellm, bundle, 1p, docker, reverse-engineering]
timestamp: 2026-07-06
---

# FitaLabs Gateway — 1P Bundle + LiteLLM Proxy Journey

Complete documentation of the migration from custom gateway to LiteLLM Proxy Server
and the hosting of the Claude Desktop 1P bundle on `claude.unifita.app`.

## Final Architecture

```
Caddy (TLS)
├── claude.unifita.app  → SPA React 1P (bundle ion-dist + CDN chunks)
├── api.unifita.app     → LiteLLM Proxy (models, inference)
├── gateway.unifita.app → LiteLLM Admin UI (/ui)
├── docs.unifita.app    → Docusaurus (OpenAPI docs)
├── get.unifita.app     → DMG downloads
└── status/search/crawley → auxiliary services

Docker Compose:
├── caddy        — reverse proxy + TLS
├── gateway      — LiteLLM Proxy Server (FastAPI)
├── postgres     — proxy database (users, keys, spend)
├── redis        — prompt cache
├── searxng      — meta-search
├── crawl4ai     — web crawler
└── uptime-kuma  — monitoring
```

## Models (4 Claude aliases + 4 provider-native)

| ant_alias | model_id | display_name |
|-----------|----------|-------------|
| `claude-haiku-4-7[1m]` | `deepseek-v4-flash` | Haiku Seek Flash |
| `claude-sonnet-4-6[1m]` | `mimo-v2.5` | Monnet v2.5 |
| `claude-opus-4-6[1m]` | `mimo-v2.5-pro` | Mopus v2.5 Pro |
| `claude-opus-4.7[1m]` | `deepseek-v4-pro` | Dopus Pro |

Provider-native: `deepseek-v4-flash[1m]`, `mimo-v2.5[1m]`, `mimo-v2.5-pro[1m]`, `deepseek-v4-pro[1m]`
Audio: `tts-1`, `whisper-1`

## Gateway Evolution

### Phase 1: Custom FastAPI (Jun 2026)
- `gateway.py` — custom FastAPI app with manual Tier x Effort routing
- `router.py` (304L) — routing table Haiku/Sonnet/Opus x Low/Med/High
- `handlers/messages.py` — manual HTTP forwarding to MiMo/DeepSeek
- `services/forwarding.py`, `services/fallback.py` — custom proxy code
- MiMo provider registered via monkey-patch in `ProviderConfigManager`

### Phase 2: LiteLLM Router as Library
- `litellm_router.py` — singleton loading `model_list` from YAML
- `router.acompletion()` replaces manual forwarding
- Custom hooks registered in pipeline (`hooks/pipeline.py`)

### Phase 3: LiteLLM Proxy Server (Jul 2026)
- **Critical discovery**: `CONFIG_FILE_PATH` (not `LITELLM_CONFIG_PATH`) is the env var the proxy reads at startup
- `app = litellm.proxy.proxy_server.app` — the proxy IS the gateway
- Custom routes (voice WS, MCP, search, API handlers) added to the proxy app
- PostgreSQL required for admin UI (login, key management, spend tracking)
- Prisma: LiteLLM's default schema is PostgreSQL, not SQLite. `libatomic1` required in Dockerfile
- Migrations: `prisma migrate deploy` runs the `litellm_proxy_extras` migrations
- Admin UI at `/ui`, login `admin` / `admin` (UI_USERNAME/UI_PASSWORD)

### Phase 4: 1P Bundle (Jul 2026)
- Bundle extracted from 1P Desktop via CDP → `~/.bezetacil/workdir/claude-desktop/ion-dist/`
- 47 files copied to `webapp/claude/` (React 7.2MB + 35 chunks + CSS + fonts)
- CDN fallback in Caddy: missing chunks downloaded on-demand from `assets-proxy.anthropic.com`
- Caddy injects `Authorization: Bearer sk-gateway-local` in all API calls (no Service Worker)
- SPA fallback: client-side routes (`/login`, `/new`, `/onboarding`) serve `index.html`
- API routes (`/api/*`, `/v1/*`, `/bootstrap`, `/account_profile`, `/edge-api/*`, `/accounts/*`) proxied to gateway

## 1P Bundle Discoveries

### Chunks and Code Splitting
- The main bundle (`index-BW29VlNm.js`, 7.2MB) imports 35+ chunks via dynamic `import()`
- Chunks follow Vite/Rollup pattern: `vendor-react-B9b0-tId.js`, `c34d1f91f-DIhRpeoW.js`, etc
- Complete chunk list obtained from browser 404 errors
- CDN URL: `https://assets-proxy.anthropic.com/claude-ai/v2/assets/v1/`

### Authentication
- SPA uses Google OAuth (`accounts.google.com/gsi/status`) as main provider
- Magic link implemented: `POST /api/auth/send_magic_link` + `GET /api/auth/verify_magic_link`
- Login methods: `GET /api/auth/login_methods?email=...`
- SPA does PUT `/api/account_profile` to update onboarding settings

### Onboarding
- SPA checks `has_finished_claudeai_onboarding` and `has_started_claudeai_onboarding` on account
- Mutations `E()` and `be()` do PUT on `/api/account_profile` with settings
- `invites` array must exist (even empty) on account — `e?.invites.some()` crashes if undefined

### Critical Endpoints Called by 1P SPA
- `GET /edge-api/bootstrap?statsig_hashing_algorithm=djb2&growthbook_format=sdk&include_system_prompts=false`
- `GET /api/account_profile`
- `PUT /api/account_profile` — atualiza settings
- `POST /api/accounts/me/organizations/get_or_create_chat_organization`
- `GET /api/auth/login_methods?email=...`
- `POST /api/auth/send_magic_link`
- `POST /api/event_logging/v2/batch`
- `GET /api/updates` — version check

## Caddy Configuration

### claude.unifita.app
```
file_server (root /var/www/claude)
reverse_proxy /api/* → gateway:4000 (with auth header injection)
reverse_proxy /v1/* → gateway:4000
SPA fallback: client-side routes → index.html (only Accept: text/html)
CDN fallback: handle_errors 404 → proxy assets-proxy.anthropic.com
```

### gateway.unifita.app
```
redir / → /ui (admin panel)
/swagger → /docs (OpenAPI)
```

## Docker

### docker-compose.yml
- PostgreSQL 16 Alpine with `pg_isready` healthcheck
- `prisma-cache` volume for Prisma binaries
- Bind mounts for dev: `src/`, `litellm_config.yaml`, `data/`
- Env vars in `.env` (not in compose), following project convention

### Dockerfile
```dockerfile
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
RUN apt-get install -y ffmpeg curl libatomic1
RUN uv sync --frozen --no-dev
CMD ["uv", "run", "uvicorn", "gateway:app", "--host", "0.0.0.0", "--port", "4000"]
```

## Lessons Learned

1. **LiteLLM Proxy, not Router**: `proxy_server.app` is the gateway. `Router` is just a library.
2. **CONFIG_FILE_PATH**: The env var the proxy actually reads. `LITELLM_CONFIG_PATH` is ignored.
3. **PostgreSQL required**: Admin UI, key management, spend tracking all need Postgres.
4. **`libatomic1`**: Required in Dockerfile for Prisma/Node binaries.
5. **Caddy auth injection > Service Worker**: SW has caching issues. Caddy `header_up` is server-side and reliable.
6. **SPA fallback with Accept header**: `header Accept *text/html*` avoids serving HTML for JS imports.
7. **CDN fallback with `handle_errors 404`**: Chunks downloaded on-demand, no need for pre-download.

## References
- [[fitalabs-gateway-modelos]] — routing table
- [[fitalabs-infra]] — complete stack
- [[claude-desktop-bundles]] — 1P vs 3P bundle architecture
- [[claude-desktop-feature-flags]] — 226 feature flags
- [[bezetacil-toolset]] — ASAR RE tools
