File size: 2,398 Bytes
cf5e005
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
"""RMI Backend β€” FastAPI app factory.

The single source of truth for app composition. Every concern
(lifespan, middleware, error handlers, routers) lives in its own
module and is wired together here.

Composition order (matters):
  1. Create FastAPI instance with metadata
  2. Register error handlers (before middleware so they can format responses)
  3. Register middleware (must be at module level, not lifespan)
  4. Mount routers (after middleware so routes can use it)
  5. Lifespan runs on startup/shutdown

Per v4.0 Β§T01 + ADR-0001 (strangler fig), this factory:
  - Replaces the 8475-line legacy monolith
  - Mounts new v1 routers as the ONLY backend surface
  - Each mount is isolated (one failure does not break others)
  - Frozen file: no mass regex allowed; targeted edits only
"""
from __future__ import annotations

import logging
from typing import Final

from fastapi import FastAPI

log = logging.getLogger(__name__)


# ── Public constants ────────────────────────────────────────────────
VERSION: Final = "2026.06.21"
TITLE: Final = "RMI Backend"
DESCRIPTION: Final = (
    "Rug Munch Intelligence β€” institutional-grade crypto intelligence API. "
    "13+ chains, 96 data providers, 8 MCP tools, x402 paid tier, sovereign-first FOSS."
)


def create_app() -> FastAPI:
    """Build the FastAPI app. Single source of truth for composition.

    Every concern delegates to its own module:
      - app.lifespan.lifespan            startup/shutdown
      - app.middleware_setup.register    middleware
      - app.error_handlers.register      exception handlers
      - app.mount.mount_all              every router
    """
    from app.lifespan import lifespan
    from app.middleware_setup import register_middleware
    from app.error_handlers import register_error_handlers
    from app.mount import mount_all

    log.info("rmi_backend_creating v=%s", VERSION)

    app = FastAPI(
        title=TITLE,
        version=VERSION,
        description=DESCRIPTION,
        lifespan=lifespan,
    )

    # Order matters: handlers before middleware before routes
    register_error_handlers(app)
    register_middleware(app)
    mounted = mount_all(app)

    log.info(
        "rmi_backend_ready mounted=%d total_routes=%d",
        mounted, len(app.routes),
    )
    return app