Architecture Overview
This page describes the internal architecture of nfr-review — how the components fit together and where the extension points are.
Pipeline overview
Section titled “Pipeline overview”nfr-review follows a three-phase pipeline:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐│ Collectors │────▶│ Rules │────▶│ Renderers ││ (extract) │ │ (evaluate) │ │ (output) │└─────────────┘ └─────────────┘ └─────────────┘ │ │ │ Evidence Findings Reports (typed payloads) (RAG + severity) (CSV/JSONL/SARIF/MD/HTML/PDF)- Collectors scan the target repository and emit typed
Evidencerecords - Rules consume evidence and produce
Findingrecords with RAG/severity - Renderers format findings into output reports
Key components
Section titled “Key components”Engine (src/nfr_review/engine.py)
Section titled “Engine (src/nfr_review/engine.py)”The Engine class orchestrates the pipeline:
- Accepts collector and rule registries
- Runs collectors (optionally in parallel via
ThreadPoolExecutor) - Passes evidence to all applicable rules
- Returns a
RunResultcontaining findings, rule results, and warnings - Handles failures gracefully — collector/rule errors become warnings
Registries (src/nfr_review/registry.py)
Section titled “Registries (src/nfr_review/registry.py)”The Registry[T] generic class manages named collections of collectors and
rules. Two registry instances exist:
| Registry | Purpose |
|---|---|
collector_registry / rule_registry |
Core NFR collectors and rules |
hygiene_collector_registry / hygiene_rule_registry |
Hygiene audit (separate concern) |
Registries support auto-discovery — modules register via side-effect imports at startup.
Protocols (src/nfr_review/protocols.py)
Section titled “Protocols (src/nfr_review/protocols.py)”The extension contracts:
Collector—name,version,collect(repo_path, config) → list[Evidence]Rule—id,band,required_collectors,evaluate(evidence, context) → RuleResultEvidence—collector_name,kind,locator,payloadFinding—rule_id,rag,severity,summary,evidence_locator
FieldRule framework (src/nfr_review/rules/framework.py)
Section titled “FieldRule framework (src/nfr_review/rules/framework.py)”The recommended base class for writing rules. Handles evidence filtering,
payload coercion, and finding construction. Rules only implement check().
Tech detection (src/nfr_review/detect.py)
Section titled “Tech detection (src/nfr_review/detect.py)”Runs before collectors to identify which technologies are present. Returns a
dict[str, bool] that gates tech-specific collectors. Supports 18
technology keys.
CLI (src/nfr_review/cli.py)
Section titled “CLI (src/nfr_review/cli.py)”Click-based CLI with commands:
run— single scan, emit findingsreport— full report with scoringhygiene— standalone hygiene auditlist-rules/explain— rule discoverybaseline— interaction baseline managementmonitor— live OTLP monitoringissues— GitHub issue syncdeps— dependency analysisinit— create starter config
Data flow
Section titled “Data flow”Target repo │ ▼┌── Tech Detection ──┐│ detect.py ││ → dict[str,bool] │└─────────┬──────────┘ │ ▼┌── Collector Phase ──────────────────┐│ For each registered collector: ││ • Skip if required_tech missing ││ • Skip if in config.skip list ││ • Run collect() → Evidence[] ││ (parallel via ThreadPoolExecutor) │└─────────┬──────────────────────────┘ │ ▼┌── Rule Phase ───────────────────────┐│ For each registered rule: ││ • Skip if required collectors ││ didn't produce evidence ││ • Run evaluate() → RuleResult ││ • Collect findings + skipped │└─────────┬──────────────────────────┘ │ ▼┌── Output Phase ─────────────────────┐│ • Classify findings (origin, etc.) ││ • Compute maturity score ││ • Baseline diff (if configured) ││ • Render to selected formats ││ • GitHub issue sync (if enabled) │└─────────────────────────────────────┘Band system
Section titled “Band system”Rules are organised into three bands based on analysis depth:
| Band | Name | How it works |
|---|---|---|
| 1 | Static | Pattern matching and structural analysis on collected evidence |
| 2 | Composite/LLM | Joins multiple evidence types or uses LLM for semantic analysis |
| 3 | Dynamic | Analyses runtime traces (OTLP spans) from production or staging |
Band 1 rules require no external dependencies. Band 2 may require an LLM API key. Band 3 requires trace data.
Extension points
Section titled “Extension points”| Extension | How to add | See |
|---|---|---|
| New collector | Implement Collector protocol, place in collectors/ |
Custom Collectors |
| New rule | Subclass FieldRule or implement Rule protocol, place in rules/ |
Custom Rules |
| New output format | Add a renderer module in output/ |
Source: src/nfr_review/output/ |
| New tech detection | Add a detector function in detect.py |
Tech Detection |
| New compliance mapping | Add entries in compliance_mapping.py |
Compliance |