Skip to main content

Conventions

Commit Messages

Follow Conventional Commits: <type>(<scope>): <description>

Types

TypeTriggers Release?When to Use
featYes (minor)New feature
fixYes (patch)Bug fix
securityYes (patch)Security fix
perfYes (patch)Performance improvement
docsNoDocumentation only
refactorNoCode restructuring without behavior change
testNoAdding or fixing tests
styleNoFormatting, whitespace
choreNoMaintenance tasks
ciNoCI/CD changes

Scope

Use the issue key if available (e.g., feat(SCAN-123): add probe filtering), otherwise the component name (e.g., fix(reports): correct scan count).

Breaking Changes

Add BREAKING CHANGE: to the commit footer for changes that require migration steps:

feat(targets): restructure JSON config format

BREAKING CHANGE: target.json_config now uses snake_case keys.
Run `rails db:migrate` and update any custom targets.

Examples

feat(probes): add community probe filtering
fix(reports): correct scan count in summary
docs: update quick start guide
chore(deps): bump rails to 8.1
test(scans): add scheduled scan job specs

Branch Naming

PatternWhen to Use
feature/short-descriptionNew feature
fix/short-descriptionBug fix
chore/short-descriptionMaintenance
docs/short-descriptionDocumentation
hotfix/short-descriptionUrgent production fix

Examples: feature/add-json-validator, fix/escape-file-paths-mac, docs/docusaurus-site

Code Style

Ruby

RuboCop is the enforcer. Run before committing:

bundle exec rubocop -A  # auto-fix
bundle exec rubocop # check only

Key style decisions:

  • 2-space indentation
  • Single quotes for strings (unless interpolation needed)
  • Frozen string literals enabled

Views

  • Use semantic class names in views, not raw Tailwind utilities directly
  • Define reusable styles in application.css using @apply
  • Icons use heroicons only — defined in icons.css, not inline SVGs
<%# Good %>
<button class="btn-primary">Run Scan</button>

<%# Avoid %>
<button class="bg-blue-600 hover:bg-blue-700 text-white font-medium px-4 py-2 rounded">Run Scan</button>

JavaScript / Stimulus

  • Chart configurations go in app/javascript/config/chartConfig.js
  • Use shared config functions (e.g., getGaugeChartConfig()) — no duplicate chart code
  • ASR color scale must match between scores_helper.rb and chartConfig.js

Security Conventions

  • Never commit secrets — use environment variables
  • Always Shellwords.escape for shell interpolation
  • Encrypted fields must be accessed within a tenant scope:
    ActsAsTenant.with_tenant(company) { target.json_config }
  • Don't use .pluck on encrypted fields — use .select(:field).map(&:field) instead
  • Non-deterministic encryption means saved_change_to_<encrypted_field>? always returns true — compare decrypted values instead

Database Conventions

  • Keep migrations small and reversible
  • Add a comment explaining non-obvious migrations
  • Partial indexes are preferred for scoped queries (see add_partial_index_for_active_reports)
  • Background jobs must explicitly scope tenant context with ActsAsTenant.with_tenant

Pull Requests

  • PR title must follow Conventional Commits format (enforced by CI)
  • Keep PRs focused — ideally under ~300 lines of diff
  • Target main branch
  • Two approvals required for changes touching core services, background jobs, migrations, or security-sensitive code