> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vultlocal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> Internal architecture of the OLIVE Gateway service

# Gateway Architecture

This document covers the internal architecture of the Gateway service, including the middleware stack, handler organization, and request lifecycle.

## Component Overview

```mermaid theme={null}
graph TB
    subgraph "Entry"
        REQ[HTTP Request]
    end

    subgraph "Middleware Stack"
        CORS[CORS]
        LOG[Request Logger]
        REC[Recovery]
        RL[Rate Limiter]
        AUTH[Auth Middleware]
        AUDIT[Audit Logger]
    end

    subgraph "Handlers"
        SH[Subscriber Handler]
        CH[Card Handler]
        WH[Wallet Handler]
        AH[Agent Handler]
        PH[POS Handler]
        CPH[Compliance Handler]
        ADH[Admin Handler]
        WHK[Webhook Handler]
    end

    subgraph "Services"
        WC[Wallet Client]
        DB[Database]
    end

    subgraph "External"
        WCORE[Wallet-Core gRPC]
    end

    REQ --> CORS --> LOG --> REC --> RL --> AUTH --> AUDIT
    AUDIT --> SH & CH & WH & AH & PH & CPH & ADH & WHK
    SH & CH & WH & AH & PH --> WC
    CPH & ADH --> WC & DB
    WHK --> WC
    WC --> WCORE
```

## Middleware Stack

Middleware is applied in order, each adding functionality:

| Order | Middleware     | Purpose                       |
| ----- | -------------- | ----------------------------- |
| 1     | CORS           | Cross-origin request handling |
| 2     | Request Logger | Log incoming requests         |
| 3     | Recovery       | Panic recovery with logging   |
| 4     | Rate Limiter   | Per-client request throttling |
| 5     | Auth           | Authentication verification   |
| 6     | Audit Logger   | Operation audit trail         |

### Middleware Files

```
internal/middleware/
├── auth.go              # JWT validation
├── api_key_auth.go      # API key authentication
├── service_auth.go      # Internal service HMAC auth
├── hmac_auth.go         # POS HMAC authentication
├── partner_api_auth.go  # Partner API authentication
├── rate_limit.go        # Request rate limiting
├── cors.go              # CORS configuration
├── logging.go           # Request/response logging
├── recovery.go          # Panic recovery
├── audit.go             # Audit logging
├── roles.go             # Role-based authorization
└── combined_auth.go     # AllowServiceOrUser helper
```

## Handler Organization

Handlers are organized by domain, each handling a specific resource type:

### Handler Files

| File                                 | Endpoints                       | Count |
| ------------------------------------ | ------------------------------- | ----- |
| `subscriber_handler.go`              | Register, lookup, update, block | 6     |
| `card_handler.go`                    | Link, block, unblock, upload    | 6     |
| `wallet_handler.go`                  | Balance, payments, transfers    | 5     |
| `agent_handler.go`                   | Lookup, cashin, transfer        | 5     |
| `pos_handler.go`                     | Payment, verify-card            | 3     |
| `compliance_handler.go`              | Check, alerts, rules            | 8     |
| `admin_handler.go`                   | Login, users, settings          | 10+   |
| `api_key_handler.go`                 | Create, list, revoke keys       | 4     |
| `audit_handler.go`                   | List, query audit logs          | 3     |
| `processor_handler.go`               | Merchant/processor ops          | 6     |
| `webhook_handler.go`                 | VULT cashin webhook             | 2     |
| `pep_access_handler.go`              | PEP access flows                | 2     |
| `fee_settings_handler.go`            | Fee configuration               | 4     |
| `notifications.go`                   | Push notifications              | 2     |
| `suspicious_transactions_handler.go` | Fraud monitoring                | 4     |

## Request Lifecycle

### Standard Request Flow

```mermaid theme={null}
sequenceDiagram
    participant C as Client
    participant MW as Middleware
    participant H as Handler
    participant WC as Wallet Client
    participant G as Wallet-Core (gRPC)

    C->>MW: HTTP Request
    MW->>MW: CORS check
    MW->>MW: Log request
    MW->>MW: Rate limit check
    MW->>MW: Authenticate
    MW->>MW: Authorize
    MW->>H: Validated request
    H->>H: Parse & validate body
    H->>WC: Business operation
    WC->>G: gRPC call
    G-->>WC: gRPC response
    WC-->>H: Mapped response
    H->>MW: HTTP response
    MW->>MW: Log response
    MW->>MW: Audit log
    MW-->>C: JSON response
```

### Authentication Flow

```mermaid theme={null}
flowchart TD
    REQ[Request] --> CHECK{Auth Header?}
    CHECK -->|No| UNAUTH[401 Unauthorized]
    CHECK -->|Yes| PARSE{Parse Token}
    
    PARSE -->|Bearer API Key| APIKEY[Validate API Key]
    PARSE -->|Bearer JWT| JWT[Validate JWT]
    PARSE -->|HMAC| HMAC[Verify HMAC Signature]
    PARSE -->|Service-Auth| SVC[Verify Service Token]
    
    APIKEY -->|Valid| CONTEXT[Set User Context]
    JWT -->|Valid| CONTEXT
    HMAC -->|Valid| CONTEXT
    SVC -->|Valid| CONTEXT
    
    APIKEY -->|Invalid| UNAUTH
    JWT -->|Invalid| UNAUTH
    HMAC -->|Invalid| UNAUTH
    SVC -->|Invalid| UNAUTH
    
    CONTEXT --> HANDLER[Continue to Handler]
```

## gRPC Client

The wallet client wraps gRPC calls to wallet-core:

```go theme={null}
// internal/wallet/client.go
type Client struct {
    conn       *grpc.ClientConn
    subscriber olive.SubscriberServiceClient
    card       olive.CardServiceClient
    wallet     wallet.WalletServiceClient
    agent      olive.AgentServiceClient
    compliance olive.ComplianceServiceClient
    // ... other service clients
}

func (c *Client) GetBalance(ctx context.Context, userID, currency string) (*Balance, error) {
    resp, err := c.wallet.GetBalance(ctx, &wallet.GetBalanceRequest{
        UserId:   userID,
        Currency: currency,
    })
    if err != nil {
        return nil, mapGRPCError(err)
    }
    return &Balance{
        UserID:   resp.UserId,
        Currency: resp.Currency,
        Balance:  resp.Balance,
    }, nil
}
```

## Route Registration

Routes are registered in `cmd/server/main.go`:

```go theme={null}
func setupRoutes(r *gin.Engine, h *handler.Handler, mw *middleware.Middleware) {
    // Public routes
    r.GET("/health", h.HealthCheck)
    r.GET("/version", h.Version)
    
    // Public subscriber registration
    public := r.Group("/api/v1/public")
    {
        public.POST("/subscribers", h.RegisterSubscriberPublic)
    }
    
    // Protected routes
    api := r.Group("/api/v1")
    api.Use(mw.Auth())
    {
        // Subscribers
        api.POST("/subscribers", h.RegisterSubscriber)
        api.GET("/subscribers/lookup", h.LookupSubscriber)
        api.GET("/subscribers/:id", h.GetSubscriber)
        
        // Wallet
        api.GET("/balance/:user_id", h.GetBalance)
        api.POST("/payments", h.CreatePayment)
        api.GET("/transactions", h.ListTransactions)
        
        // ... more routes
    }
    
    // Admin routes
    admin := r.Group("/api/v1/admin")
    admin.Use(mw.JWT(), mw.RequireRole("system_admin"))
    {
        admin.GET("/users", h.ListAdminUsers)
        admin.POST("/api-keys", h.CreateAPIKey)
    }
    
    // POS routes with HMAC auth
    pos := r.Group("/pos")
    pos.Use(mw.HMACAuth())
    {
        pos.POST("/payment", h.POSPayment)
        pos.POST("/verify-card", h.POSVerifyCard)
    }
}
```

## Error Handling

### Standard Error Response

```go theme={null}
type ErrorResponse struct {
    Error   string      `json:"error"`
    Code    string      `json:"code,omitempty"`
    Details interface{} `json:"details,omitempty"`
}

func respondError(c *gin.Context, status int, err error) {
    var code string
    switch {
    case errors.Is(err, ErrNotFound):
        code = "NOT_FOUND"
    case errors.Is(err, ErrInsufficientBalance):
        code = "INSUFFICIENT_BALANCE"
    case errors.Is(err, ErrUnauthorized):
        code = "UNAUTHORIZED"
    default:
        code = "INTERNAL_ERROR"
    }
    
    c.JSON(status, ErrorResponse{
        Error: err.Error(),
        Code:  code,
    })
}
```

### gRPC Error Mapping

```go theme={null}
func mapGRPCError(err error) error {
    st, ok := status.FromError(err)
    if !ok {
        return err
    }
    
    switch st.Code() {
    case codes.NotFound:
        return ErrNotFound
    case codes.InvalidArgument:
        return ErrBadRequest
    case codes.PermissionDenied:
        return ErrForbidden
    case codes.ResourceExhausted:
        return ErrRateLimited
    default:
        return ErrInternal
    }
}
```

## Configuration Loading

```go theme={null}
// internal/config/config.go
type Config struct {
    Server     ServerConfig     `yaml:"server"`
    Database   DatabaseConfig   `yaml:"database"`
    WalletCore WalletCoreConfig `yaml:"wallet_core"`
    Auth       AuthConfig       `yaml:"auth"`
    RateLimit  RateLimitConfig  `yaml:"rate_limit"`
    Logging    LoggingConfig    `yaml:"logging"`
}

func Load(path string) (*Config, error) {
    cfg := &Config{}
    
    // Load YAML file
    data, err := os.ReadFile(path)
    if err != nil {
        return nil, err
    }
    
    // Expand environment variables
    expanded := os.ExpandEnv(string(data))
    
    if err := yaml.Unmarshal([]byte(expanded), cfg); err != nil {
        return nil, err
    }
    
    // Apply overrides from environment
    applyEnvOverrides(cfg)
    
    return cfg, nil
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/gateway/authentication">
    Detailed auth configuration
  </Card>

  <Card title="Configuration" icon="gear" href="/gateway/configuration">
    config.yaml reference
  </Card>
</CardGroup>
