Skip to main content

Architecture

Component Overview

Key Design Decisions

Single-Process Architecture

Puma and Solid Queue run in the same container process. This simplifies deployment — a single Docker container runs everything except PostgreSQL. The tradeoff is that you can't scale the web server and job workers independently.

garak as a Subprocess

NVIDIA garak is a Python library. Scanner invokes it as a separate process and communicates via a Unix socket. This isolates Python dependency management from the Rails app and lets garak run with its own environment.

The RunGarakScan service class manages the garak subprocess lifecycle. Scan results are streamed back through the socket and written to the database in real time.

Multi-Database PostgreSQL

Rails 8's multi-database support splits concerns across four databases:

DatabasePurpose
scanner_productionApplication data (targets, scans, reports, users)
scanner_production_queueSolid Queue job tables
scanner_production_cacheRails cache store
scanner_production_cableAction Cable subscription data

This improves isolation and allows different retention/backup policies per database.

Multi-Tenancy

Scanner uses acts_as_tenant for row-level multi-tenancy. Every company's data is scoped to their tenant in all queries. Encrypted fields use per-tenant keys derived from SECRET_KEY_BASE.

important

All code that accesses encrypted fields must run within a tenant scope:

ActsAsTenant.with_tenant(company) { ... }

Controllers handle this automatically. Background jobs must do it explicitly.

Encryption at Rest

Sensitive fields are encrypted using ActiveRecord Encryption:

ModelEncrypted Fields
Targetjson_config, web_config
EnvironmentVariableenv_value

Encryption keys are derived per-tenant from SECRET_KEY_BASE via HMAC. See config/initializers/active_record_encryption.rb.

Extension Points

See Extension Points for the full API. The three extension points are:

  • Scanner.configure — service class overrides and lifecycle hooks
  • BrandConfig.configure — branding and theming
  • ProbeSourceRegistry — additional probe data sources

Technology Stack

LayerTechnology
FrameworkRuby on Rails 8
DatabasePostgreSQL 18
Background jobsSolid Queue (in-process with Puma)
FrontendStimulus + Turbo (Hotwire), Tailwind CSS
AI ScannerNVIDIA garak (Python)
AuthDevise
HTTP proxyThruster (HTTP/2, asset compression)
ContainerizationDocker