Skip to main content

Architecture Overview

GhostPour is a FastAPI middleware layer that sits between your iOS app and upstream services (LLM providers, Apple StoreKit, feature services). It owns subscription state, usage enforcement, model routing, and feature gating — your iOS app just talks to one API.

System Diagram

Ownership Boundaries

ConcernOwner
Payment processing, receipts, trials, renewalsApple (StoreKit 2)
Purchase UI, entitlement detection, fallback UXiOS app
Tier state, allocation tracking, model routing, quota enforcementGhostPour (server)

Key principle: GhostPour is the source of truth for the user's tier and allocation. The iOS app tells GhostPour what StoreKit says, and GhostPour decides what the user gets.

Request Flow

Every chat request passes through a pipeline of checks before reaching the LLM:

API Endpoints

EndpointPurpose
POST /auth/appleApple identity token verification, JWT issuance
POST /v1/verify-receiptSubscription purchase verification, tier update
POST /v1/sync-subscriptionReconcile tier state on every app launch
POST /v1/chatMain chat endpoint with full enforcement pipeline
GET /v1/usage/meUsage stats, tier constraints, feature states
GET /v1/tiersServer-driven subscription UI catalog (public)
GET /v1/config/{slug}Remote config delivery to iOS app
/v1/quilt/*Context Quilt proxy endpoints
/adminAdmin dashboard web UI

Tech Stack

  • Framework: FastAPI (Python)
  • Database: SQLite persisted in Docker volume
  • LLM routing: LiteLLM for multi-provider pricing and routing
  • Auth: Apple Sign In → JWT
  • Deployment: Docker on GCP, Nginx Proxy Manager, GitHub Actions CI/CD

Source Code Layout

app/
├── routers/
│ ├── chat.py # Main chat, verify-receipt, sync-subscription, usage/me
│ └── webhooks.py # Admin set-tier, simulate-tier
├── services/
│ └── usage_tracker.py # check_quota, record_cost, model access
├── models/
│ └── user.py # UserRecord with allocation fields
└── database.py # Users table schema + migrations

config/
├── tiers.yml # Tier definitions, limits, features, StoreKit IDs
├── features.yml # Feature display metadata
└── remote/
├── idle-tips.json
├── protected-prompts.json
├── llm-providers.json
└── model-capabilities.json