Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Eljakani/ward/llms.txt
Use this file to discover all available pages before exploring further.
Design Principles
Ward is built on four core architectural principles:Interface-First
Every component (Scanner, Provider, Reporter, Resolver) is a Go interface, enabling easy extension and testing
Event-Driven
Scanners emit findings through an event bus; the TUI subscribes to real-time updates
Shared Context
Resolvers build a ProjectContext once; all scanners consume it independently
Rules as Data
YAML-based security rules — no recompilation needed to add or modify checks
Component Overview
Ward’s architecture is organized into distinct, loosely-coupled components:Core Components
Orchestrator
Location:internal/orchestrator/orchestrator.go
The Orchestrator is the pipeline coordinator that executes the 5-stage scan workflow. It:
- Manages the scan lifecycle from start to completion
- Publishes events to the EventBus at each pipeline stage
- Coordinates all scanners and handles their results
- Applies post-processing (deduplication, filtering, baseline comparison)
- Triggers report generation in multiple formats
Event Bus
Location:internal/eventbus/
The EventBus provides a decoupled publish-subscribe mechanism for real-time communication between components.
Key Features:
- Type-safe event system with 12+ event types
- Synchronous event delivery
- Support for both typed and wildcard subscriptions
- Thread-safe using
sync.RWMutex
Scan Lifecycle Events
Scan Lifecycle Events
EventScanStarted— Scan beginsEventScanCompleted— Scan finishes successfullyEventScanFailed— Scan encounters an error
Pipeline Stage Events
Pipeline Stage Events
EventStageStarted— A pipeline stage begins (Provider, Resolvers, etc.)EventStageCompleted— A pipeline stage completes
Scanner Events
Scanner Events
EventScannerRegistered— Scanner is registeredEventScannerStarted— Scanner begins executionEventScannerCompleted— Scanner finishesEventScannerFailed— Scanner encounters an errorEventScannerSkipped— Scanner is disabled/skipped
Finding Events
Finding Events
EventFindingDiscovered— A new security finding is detected
Context Events
Context Events
EventContextResolved— Project metadata has been resolved
Interfaces
Ward defines clean interfaces for all major components:- Scanner
- Provider
- Resolver
- Reporter
Location: The
internal/models/scanner.goAll security scanners implement this interface:emit callback allows scanners to stream findings in real-time to the TUI.Shared Context
TheProjectContext structure holds all resolved project metadata that scanners consume:
Location: internal/models/context.go
- Performance: No redundant parsing
- Consistency: All scanners see the same project state
- Independence: Scanners don’t need to know how to parse Laravel files
Directory Structure
Data Flow
Here’s how data flows through Ward during a scan:CLI Invocation
User runs
ward scan ./my-appThe scan.go command:- Creates an EventBus
- Loads configuration from
~/.ward/config.yaml - Creates an Orchestrator
- Launches the TUI (if TTY available) or headless mode
Provider Stage
The Orchestrator uses a SourceProvider to acquire the project:
LocalProvidervalidates the path existsGitProviderperforms a shallow clone- Returns a
SourceResultwith root path and Laravel detection
Resolvers Stage
Resolvers run in priority order to build the ProjectContext:
FrameworkResolverparsescomposer.jsonand.envPackageResolverreadscomposer.lockfor installed packages
EventContextResolvedScanners Stage
All scanners run independently with the shared ProjectContext:
env-scannerchecks.envfilesconfig-scanneranalyzesconfig/*.phpdependency-scannerqueries OSV.dev for CVEsrules-scannerexecutes YAML pattern rules
EventFindingDiscoveredPost-Process Stage
The Orchestrator processes all findings:
- Deduplication — Removes duplicate findings (same ID + file + line)
- Severity filtering — Applies minimum severity from config
- Baseline comparison — Suppresses known findings if baseline is provided
- History diff — Compares with last scan to show new/resolved findings
Terminal UI Integration
The TUI is built with Bubble Tea and subscribes to the EventBus:Extending Ward
Adding a New Scanner
Adding a New Scanner
- Create a new package under
internal/scanner/ - Implement the
Scannerinterface - Register it in
orchestrator.go:52-56
Adding a New Resolver
Adding a New Resolver
- Create a new file in
internal/resolver/ - Implement the
ContextResolverinterface - Register it in
orchestrator.go:111-114
Adding a New Reporter
Adding a New Reporter
- Create a new file in
internal/reporter/ - Implement the
Reporterinterface - Add a case in
orchestrator.go:326-338
Related Pages
Scan Pipeline
Deep dive into the 5-stage scan pipeline
Security Scanners
Overview of all built-in scanners