Extension Points
AI Scanner is designed as an extensible base application. All features work out of the box. Organizations can add custom functionality via three extension points, without modifying core code.
Extensions are typically packaged as vendored Rails Engines.
Scanner.configure
The main configuration DSL, defined in lib/scanner/configuration.rb.
Scanner.configure do |config|
# Swap the probe access class
config.probe_access_class = MyCustomProbeAccess
# Swap the retention strategy
config.retention_strategy_class = MyRetentionStrategy
# Register OAuth providers
config.auth_providers = [:google_oauth2, :github]
# Enable portal export
config.portal_export_enabled = true
# Set a custom validation probe
config.validation_probe = "my_probes.ValidationProbe"
end
Configuration Options
| Option | Type | Description |
|---|---|---|
probe_access_class | Class | Controls which probes are accessible. Default allows all community probes. |
retention_strategy_class | Class | Determines report retention logic. Default uses RETENTION_DAYS. |
auth_providers | Array | OAuth provider symbols (e.g., :google_oauth2). |
portal_export_enabled | Boolean | Enables export to an external portal. |
validation_probe | String | Probe name used for target validation. |
Lifecycle Hooks
Register hooks to run at specific points in the scan lifecycle:
Scanner.register_hook(:after_report_process) do |context|
# context contains: report, company, scan
MyNotificationService.notify(context[:report])
end
Run hooks from your own code:
Scanner.run_hooks(:after_report_process, { report: @report, company: current_company })
Available hook events:
:after_report_process: after a scan report is processed and saved
BrandConfig.configure
Customize branding and white-labeling, defined in lib/brand_config.rb.
BrandConfig.configure do |config|
config.brand_name = "Acme AI Scanner"
config.logo_path = "acme_logo.svg"
config.font_family = "Inter, sans-serif"
config.powered_by = "Powered by Scanner"
config.host_url = "https://scanner.acme.com"
end
Configuration Options
| Option | Type | Description |
|---|---|---|
brand_name | String | Displayed in the navbar and page titles |
logo_path | String | Asset path to your logo file |
font_family | String | CSS font-family for the UI |
powered_by | String | Footer attribution text |
host_url | String | Canonical host URL (used in syslog messages and links) |
ProbeSourceRegistry
Register additional probe data sources for SyncProbesJob, defined in app/services/probe_source_registry.rb.
ProbeSourceRegistry.register(MyCustomProbeSource)
Implementing a Probe Source
class MyCustomProbeSource
def self.sync_probes
probe_definitions.each do |probe_data|
probe = Probe.find_or_initialize_by(name: probe_data[:name])
probe.update!(
description: probe_data[:description],
family: probe_data[:family],
tags: probe_data[:tags] || []
)
end
end
def self.probe_definitions
[
{
name: "my_probes.CustomJailbreak",
description: "Tests for custom jailbreak patterns",
family: "jailbreak",
tags: ["custom", "jailbreak"]
}
]
end
end
SyncProbesJob calls .sync_probes on every registered source when it runs. The job runs automatically on boot and can be triggered manually:
docker compose exec scanner rails runner "SyncProbesJob.perform_now"
Listing Registered Sources
ProbeSourceRegistry.sources
# => [GarakCommunityProbeSource, MyCustomProbeSource]