Files
alex 2682e0268c feat: container monitoring integration + polish (PR-3)
- Integration tests: SSE auth, connection limits, lifecycle hooks, event persistence (6 tests)
- Instance events history API: GET /instances/{id}/events
- Documentation updates: terminal.md, backend.md, frontend.md
- Performance: SSE max 5 connections, health monitor write-on-change

Quality gates: pytest 21 monitoring passed, 172 unit passed (4 pre-existing), vitest 14 passed, tsc clean, eslint clean, ruff clean
2026-05-29 10:25:00 +02:00

9.3 KiB

Backend Architecture

Overview

The Headquarter backend is built with FastAPI and follows a layered architecture pattern.

Architecture Diagram

┌─────────────────────────────────────────────────────────────┐
│                         FastAPI App                          │
├─────────────────────────────────────────────────────────────┤
│  Middleware: CORS → Request Logging → Exception Logging      │
├─────────────────────────────────────────────────────────────┤
│  API Layer (src/api/)                                        │
│  ┌─────────┐ ┌──────────┐ ┌────────┐ ┌──────────┐          │
│  │  Auth   │ │ Projects │ │ Users  │ │   Git    │          │
│  │ Routes  │ │ Routes   │ │ Routes │ │ Repos    │          │
│  └────┬────┘ └────┬─────┘ └───┬────┘ └────┬─────┘          │
│  ┌──────────┐ ┌──────────┐                                  │
│  │ ToolInst │ │  Events  │                                  │
│  │ Routes   │ │ Routes   │                                  │
│  └────┬─────┘ └────┬─────┘                                  │
├───────┼───────────┼───────────┼───────────┼─────────────────┤
│       │           │           │           │                  │
│  Auth │  Project  │   User    │   Git     │                  │
│ Layer │  Service  │  Service  │ Service   │                  │
│       │           │           │           │                  │
├───────┴───────────┴───────────┴───────────┴─────────────────┤
│  Data Layer                                                  │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                   │
│  │  Models  │  │ Database │  │   Config │                   │
│  │(SQLAlch) │  │(AsyncPG) │  │(Pydantic)│                   │
│  └──────────┘  └──────────┘  └──────────┘                   │
└─────────────────────────────────────────────────────────────┘

Directory Structure

src/
├── api/                    # API Routes
│   ├── auth.py            # Authentication endpoints
│   ├── projects.py        # Project endpoints
│   ├── git_repositories.py # Repository endpoints
│   ├── users.py           # User endpoints
│   ├── tool_types.py      # Tool type endpoints
│   ├── tool_instances.py  # Tool instance endpoints
│   ├── ssh_keys.py        # SSH key endpoints
│   ├── events.py          # SSE streaming endpoint
│   └── dashboard.py       # Dashboard endpoints
├── auth/                   # Authentication
│   ├── session.py         # Session management
│   ├── oidc.py            # OAuth2 client
│   ├── dependencies.py    # Auth dependencies
│   └── cookies.py         # Cookie utilities
├── models/                 # Database Models
│   ├── user.py            # User model
│   ├── project.py         # Project model
│   ├── git_repository.py  # Repository model
│   ├── tool_type.py       # Tool type model
│   ├── ssh_key.py         # SSH key model
│   ├── instance_event.py  # Instance event audit model
│   ├── health_check.py    # Health check snapshot model
│   └── user_config.py     # User config model
├── services/               # Services
│   ├── docker.py          # Docker operations
│   ├── terminal_manager.py # Terminal session manager
│   ├── event_bus.py       # Instance event bus (pub/sub)
│   ├── health_monitor.py  # Background health monitoring
│   └── lifecycle_hooks.py # Instance lifecycle events
├── utils/                  # Utilities
│   ├── git_url_parser.py  # URL parsing
│   ├── git_files.py       # Git file operations
│   └── git_history.py     # Git history operations
├── config.py              # Configuration
├── database.py            # Database setup
└── main.py                # Application entry point

Layers

1. API Layer (src/api/)

Responsibilities:

  • Define HTTP endpoints
  • Parse request parameters
  • Return HTTP responses
  • Use dependencies for auth and DB

Pattern:

@router.get("/projects")
async def list_projects(
    session: AsyncSession = Depends(get_db_session),
    user_id: str = Depends(get_current_user_id),
):
    # Call service layer
    projects = await project_service.list(session, user_id)
    return projects

2. Auth Layer (src/auth/)

Responsibilities:

  • Session management (create, verify, expire)
  • OAuth2 flow (login, callback)
  • User authentication dependencies

Key Components:

  • session.py: HMAC-SHA256 signed cookies
  • oidc.py: OAuth2 token exchange
  • dependencies.py: FastAPI dependencies for auth

3. Data Layer (src/models/, src/database.py)

Responsibilities:

  • Database schema definition
  • Async database sessions
  • Connection management

Technology:

  • SQLAlchemy 2.0 with async support
  • asyncpg driver for PostgreSQL
  • Alembic for migrations

4. Utility Layer (src/utils/)

Responsibilities:

  • Git operations (file browsing, history)
  • URL parsing
  • Helper functions

Data Flow

Request Lifecycle

1. Request arrives at FastAPI
2. Middleware processes (CORS, logging)
3. Auth dependency verifies session
4. Route handler processes request
5. Database session executes queries
6. Response returned to client

Authentication Flow

1. User clicks login
2. Backend redirects to Authentik
3. User authenticates
4. Authentik redirects with code
5. Backend exchanges code for token
6. Backend fetches user info
7. Backend creates session cookie
8. User is authenticated

Dependencies

Database Session

async def get_db_session() -> AsyncGenerator[AsyncSession, None]:
    async with SessionLocal() as session:
        yield session

Current User

async def get_current_user_id(
    request: Request,
    settings: Settings = Depends(get_settings),
) -> str:
    # Verify session cookie
    # Return user_id

Configuration

Configuration is managed via Pydantic Settings:

class Settings(BaseSettings):
    app_env: str = "development"
    database_url: str = "..."
    authentik_domain: str = "..."
    # ...

Environment variables are automatically loaded from .env files.

Error Handling

Errors are handled at multiple levels:

  1. Validation: Pydantic validates request bodies
  2. HTTP Exceptions: FastAPI HTTPException for client errors
  3. Middleware: ExceptionLoggingMiddleware logs server errors
  4. Database: SQLAlchemy errors converted to HTTP responses

Testing

  • Unit tests: SQLite in-memory database
  • Integration tests: PostgreSQL with transaction rollback
  • Fixtures: Shared in conftest.py

Monitoring & Notifications

The backend includes a real-time monitoring system:

Components

  • InstanceEventBus (services/event_bus.py): Typed pub/sub singleton for instance lifecycle events
  • HealthMonitor (services/health_monitor.py): Asyncio background task polling container health every 15s
  • SSE Endpoint (api/events.py): Server-Sent Events streaming for real-time frontend updates
  • Lifecycle Hooks (services/lifecycle_hooks.py): Publishes events on create/start/stop/restart/delete

Event Flow

Container Action → Lifecycle Hook → EventBus → SSE Stream → Frontend Toast

Event Types

Event When Fired
instance.created After DB insert
instance.starting Before docker compose up
instance.running After readiness probe succeeds
instance.error Build fail, crash, or probe fail
instance.stopped After docker compose stop

Technology Stack

Component Technology Version
Web Framework FastAPI ^0.104
ORM SQLAlchemy ^2.0
Database Driver asyncpg ^0.29
Validation Pydantic ^2.0
Migrations Alembic ^1.12
HTTP Client httpx ^0.25
Testing pytest ^7.4