Skip to content

System architecture

Verified against implementation on 2026-05-07.

Runtime architecture

flowchart LR
    subgraph Edge["Edge Layer"]
        Caddy["Caddy :80/:443"]
    end

    subgraph App["Application Layer"]
        API["FastAPI\n/api/v1 + /dashboard"]
        W["RQ Worker\nhigh / default / low"]
        SCH["rq-scheduler"]
    end

    subgraph Data["Data Layer"]
        PG[("PostgreSQL 16")]
        RD[("Redis 7")]
    end

    subgraph Ext["External"]
        GL["GitLab"]
    end

    subgraph Obs["Observability"]
        Prom["Prometheus"]
        Graf["Grafana"]
        J["Jaeger"]
    end

    GL -->|"Webhook + OAuth + API"| Caddy
    Caddy --> API
    API --> PG
    API --> RD
    RD --> W
    SCH --> RD
    W --> PG
    W --> GL
    API --> Prom
    Prom --> Graf
    API -. "OTLP" .-> J
    W -. "OTLP" .-> J

Components and responsibilities

Component Responsibility
Caddy TLS termination and reverse proxy
FastAPI REST API, dashboard routes, health/metrics endpoints
PostgreSQL persistent data (courses, teams, events, metrics, reports)
Redis queue backend, idempotency locks, short-lived cache
RQ Worker webhook processing, enrichment, metric computation, report generation
rq-scheduler periodic jobs (sweep, enrichment, recompute, cleanup)

Async pipeline (webhook -> metrics)

sequenceDiagram
    participant GL as GitLab
    participant API as FastAPI
    participant DB as PostgreSQL
    participant RQ as Redis/RQ
    participant W as Worker

    GL->>API: POST /api/v1/webhooks/gitlab
    API->>API: verify X-Gitlab-Token
    API->>DB: store raw event
    API->>RQ: enqueue process_event (high)
    API-->>GL: 202 accepted

    RQ->>W: dequeue process_event
    W->>DB: upsert entities
    W->>RQ: enqueue enrichment/metrics (default)

    RQ->>W: dequeue compute_metrics
    W->>DB: save MetricSnapshot

Authentication architecture

flowchart TB
    U["User"] -->|"/dashboard/login"| OAuth["GitLab OAuth"]
    OAuth -->|callback| Sess["gitpulse_session cookie"]
    Sess --> Dash["/dashboard/..."]

    APIClient["API client"] -->|"Authorization Bearer"| ApiAuth["/api/v1/..."]
    Sess -->|alternative| ApiAuth

    GitLabWH["GitLab webhook"] -->|"X-Gitlab-Token"| WH["/api/v1/webhooks/gitlab"]

Auth layers:

  1. Dashboard: GitLab OAuth + signed session cookie.
  2. API: Bearer token (TEACHER_API_TOKEN) or dashboard session.
  3. Webhook endpoint: per-project secret (X-Gitlab-Token).

Queues and scheduled jobs

Queue Purpose Priority
high webhook ingest processing highest
default enrichment, sync, metrics recompute medium
low reports and cleanup lowest

Scheduled jobs (22 tasks, all gated by feature flags):

  • sweep_unprocessed_events (every 15 min) - retry unprocessed webhook events
  • sweep_expired_ci_scenarios (every 15 min) - auto-rollback expired CI scenarios
  • periodic_enrich_all (every 4 hours) - re-fetch issues and MRs from GitLab
  • periodic_metrics_all (every 1 hour) - recompute compliance metrics
  • cleanup_old_reports (every 24 hours) - delete old report files
  • periodic_membership_sync (every 2 hours) - sync team memberships from GitLab
  • sweep_expired_conflict_challenges (every 1 hour) - expire unresolved challenges
  • sweep_unverified_conflicts (every 30 min) - verify conflict resolutions
  • sweep_stale_projects (every 1 hour) - re-fetch data for inactive projects
  • periodic_llm_analysis (every 6 hours) - LLM analysis of open MRs
  • periodic_telemetry_snapshot (every 24 hours) - weekly compliance snapshots
  • sweep_stale_background_jobs (every 24 hours) - cleanup stuck/old jobs
  • sweep_dlq_auto_resurrect - auto-retry dead-letter queue events
  • periodic_docker_reverify (every 24 hours) - re-analyze Dockerfiles
  • periodic_enrich_users (every 24 hours) - refresh user profiles from GitLab
  • periodic_verify_webhooks - verify webhook registrations
  • sweep_dead_projects (every 24 hours) - detect unreachable projects
  • cleanup_old_events (every 24 hours) - prune processed webhook events
  • cleanup_old_metric_snapshots (every 24 hours) - prune snapshots older than 180 days
  • cleanup_old_audit_logs (every 24 hours) - prune audit logs older than 180 days
  • sweep_discover_new_projects - auto-discover new GitLab group projects
  • sweep_email_queue (every 2 min) - deliver pending emails via SMTP

Deployment model

Production compose services:

  • postgres
  • redis
  • api
  • worker
  • scheduler
  • caddy

Optional monitoring profile adds:

  • prometheus
  • grafana
  • jaeger