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:
- Dashboard: GitLab OAuth + signed session cookie.
- API: Bearer token (
TEACHER_API_TOKEN) or dashboard session. - 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 eventssweep_expired_ci_scenarios(every 15 min) - auto-rollback expired CI scenariosperiodic_enrich_all(every 4 hours) - re-fetch issues and MRs from GitLabperiodic_metrics_all(every 1 hour) - recompute compliance metricscleanup_old_reports(every 24 hours) - delete old report filesperiodic_membership_sync(every 2 hours) - sync team memberships from GitLabsweep_expired_conflict_challenges(every 1 hour) - expire unresolved challengessweep_unverified_conflicts(every 30 min) - verify conflict resolutionssweep_stale_projects(every 1 hour) - re-fetch data for inactive projectsperiodic_llm_analysis(every 6 hours) - LLM analysis of open MRsperiodic_telemetry_snapshot(every 24 hours) - weekly compliance snapshotssweep_stale_background_jobs(every 24 hours) - cleanup stuck/old jobssweep_dlq_auto_resurrect- auto-retry dead-letter queue eventsperiodic_docker_reverify(every 24 hours) - re-analyze Dockerfilesperiodic_enrich_users(every 24 hours) - refresh user profiles from GitLabperiodic_verify_webhooks- verify webhook registrationssweep_dead_projects(every 24 hours) - detect unreachable projectscleanup_old_events(every 24 hours) - prune processed webhook eventscleanup_old_metric_snapshots(every 24 hours) - prune snapshots older than 180 dayscleanup_old_audit_logs(every 24 hours) - prune audit logs older than 180 dayssweep_discover_new_projects- auto-discover new GitLab group projectssweep_email_queue(every 2 min) - deliver pending emails via SMTP
Deployment model¶
Production compose services:
postgresredisapiworkerschedulercaddy
Optional monitoring profile adds:
prometheusgrafanajaeger