@ash-technologia/fathom 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/LICENSE +21 -0
- package/README.md +725 -0
- package/dist/analyzers/architecture/graph.d.ts +29 -0
- package/dist/analyzers/architecture/graph.d.ts.map +1 -0
- package/dist/analyzers/architecture/graph.js +347 -0
- package/dist/analyzers/architecture/graph.js.map +1 -0
- package/dist/analyzers/architecture/imports.d.ts +24 -0
- package/dist/analyzers/architecture/imports.d.ts.map +1 -0
- package/dist/analyzers/architecture/imports.js +155 -0
- package/dist/analyzers/architecture/imports.js.map +1 -0
- package/dist/analyzers/architecture/index.d.ts +13 -0
- package/dist/analyzers/architecture/index.d.ts.map +1 -0
- package/dist/analyzers/architecture/index.js +217 -0
- package/dist/analyzers/architecture/index.js.map +1 -0
- package/dist/analyzers/architecture/types.d.ts +65 -0
- package/dist/analyzers/architecture/types.d.ts.map +1 -0
- package/dist/analyzers/architecture/types.js +2 -0
- package/dist/analyzers/architecture/types.js.map +1 -0
- package/dist/analyzers/cicd/index.d.ts +11 -0
- package/dist/analyzers/cicd/index.d.ts.map +1 -0
- package/dist/analyzers/cicd/index.js +157 -0
- package/dist/analyzers/cicd/index.js.map +1 -0
- package/dist/analyzers/dependencies/index.d.ts +11 -0
- package/dist/analyzers/dependencies/index.d.ts.map +1 -0
- package/dist/analyzers/dependencies/index.js +403 -0
- package/dist/analyzers/dependencies/index.js.map +1 -0
- package/dist/analyzers/dependencies/lockfiles.d.ts +19 -0
- package/dist/analyzers/dependencies/lockfiles.d.ts.map +1 -0
- package/dist/analyzers/dependencies/lockfiles.js +172 -0
- package/dist/analyzers/dependencies/lockfiles.js.map +1 -0
- package/dist/analyzers/dependencies/online.d.ts +19 -0
- package/dist/analyzers/dependencies/online.d.ts.map +1 -0
- package/dist/analyzers/dependencies/online.js +116 -0
- package/dist/analyzers/dependencies/online.js.map +1 -0
- package/dist/analyzers/dependencies/types.d.ts +49 -0
- package/dist/analyzers/dependencies/types.d.ts.map +1 -0
- package/dist/analyzers/dependencies/types.js +2 -0
- package/dist/analyzers/dependencies/types.js.map +1 -0
- package/dist/analyzers/documentation/index.d.ts +11 -0
- package/dist/analyzers/documentation/index.d.ts.map +1 -0
- package/dist/analyzers/documentation/index.js +166 -0
- package/dist/analyzers/documentation/index.js.map +1 -0
- package/dist/analyzers/git/index.d.ts +11 -0
- package/dist/analyzers/git/index.d.ts.map +1 -0
- package/dist/analyzers/git/index.js +180 -0
- package/dist/analyzers/git/index.js.map +1 -0
- package/dist/analyzers/project/index.d.ts +11 -0
- package/dist/analyzers/project/index.d.ts.map +1 -0
- package/dist/analyzers/project/index.js +95 -0
- package/dist/analyzers/project/index.js.map +1 -0
- package/dist/analyzers/quality/index.d.ts +11 -0
- package/dist/analyzers/quality/index.d.ts.map +1 -0
- package/dist/analyzers/quality/index.js +198 -0
- package/dist/analyzers/quality/index.js.map +1 -0
- package/dist/analyzers/security/index.d.ts +11 -0
- package/dist/analyzers/security/index.d.ts.map +1 -0
- package/dist/analyzers/security/index.js +236 -0
- package/dist/analyzers/security/index.js.map +1 -0
- package/dist/analyzers/testing/index.d.ts +11 -0
- package/dist/analyzers/testing/index.d.ts.map +1 -0
- package/dist/analyzers/testing/index.js +134 -0
- package/dist/analyzers/testing/index.js.map +1 -0
- package/dist/baseline/baseline.d.ts +20 -0
- package/dist/baseline/baseline.d.ts.map +1 -0
- package/dist/baseline/baseline.js +134 -0
- package/dist/baseline/baseline.js.map +1 -0
- package/dist/baseline/compare.d.ts +14 -0
- package/dist/baseline/compare.d.ts.map +1 -0
- package/dist/baseline/compare.js +113 -0
- package/dist/baseline/compare.js.map +1 -0
- package/dist/baseline/types.d.ts +25 -0
- package/dist/baseline/types.d.ts.map +1 -0
- package/dist/baseline/types.js +2 -0
- package/dist/baseline/types.js.map +1 -0
- package/dist/cli/commands.d.ts +39 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +277 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +29 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/options.d.ts +55 -0
- package/dist/cli/options.d.ts.map +1 -0
- package/dist/cli/options.js +258 -0
- package/dist/cli/options.js.map +1 -0
- package/dist/core/analyzer.d.ts +33 -0
- package/dist/core/analyzer.d.ts.map +1 -0
- package/dist/core/analyzer.js +19 -0
- package/dist/core/analyzer.js.map +1 -0
- package/dist/core/context.d.ts +90 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +159 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/errors.d.ts +74 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +109 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/findings.d.ts +59 -0
- package/dist/core/findings.d.ts.map +1 -0
- package/dist/core/findings.js +34 -0
- package/dist/core/findings.js.map +1 -0
- package/dist/core/orchestrator.d.ts +44 -0
- package/dist/core/orchestrator.d.ts.map +1 -0
- package/dist/core/orchestrator.js +160 -0
- package/dist/core/orchestrator.js.map +1 -0
- package/dist/core/result.d.ts +169 -0
- package/dist/core/result.d.ts.map +1 -0
- package/dist/core/result.js +2 -0
- package/dist/core/result.js.map +1 -0
- package/dist/detectors/framework.d.ts +22 -0
- package/dist/detectors/framework.d.ts.map +1 -0
- package/dist/detectors/framework.js +147 -0
- package/dist/detectors/framework.js.map +1 -0
- package/dist/detectors/language.d.ts +13 -0
- package/dist/detectors/language.d.ts.map +1 -0
- package/dist/detectors/language.js +100 -0
- package/dist/detectors/language.js.map +1 -0
- package/dist/detectors/package-manager.d.ts +17 -0
- package/dist/detectors/package-manager.d.ts.map +1 -0
- package/dist/detectors/package-manager.js +67 -0
- package/dist/detectors/package-manager.js.map +1 -0
- package/dist/detectors/project-type.d.ts +20 -0
- package/dist/detectors/project-type.d.ts.map +1 -0
- package/dist/detectors/project-type.js +48 -0
- package/dist/detectors/project-type.js.map +1 -0
- package/dist/diff/analyzer.d.ts +16 -0
- package/dist/diff/analyzer.d.ts.map +1 -0
- package/dist/diff/analyzer.js +296 -0
- package/dist/diff/analyzer.js.map +1 -0
- package/dist/diff/git-diff.d.ts +44 -0
- package/dist/diff/git-diff.d.ts.map +1 -0
- package/dist/diff/git-diff.js +256 -0
- package/dist/diff/git-diff.js.map +1 -0
- package/dist/diff/types.d.ts +75 -0
- package/dist/diff/types.d.ts.map +1 -0
- package/dist/diff/types.js +2 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/integrations/github/context.d.ts +22 -0
- package/dist/integrations/github/context.d.ts.map +1 -0
- package/dist/integrations/github/context.js +115 -0
- package/dist/integrations/github/context.js.map +1 -0
- package/dist/integrations/github/types.d.ts +30 -0
- package/dist/integrations/github/types.d.ts.map +1 -0
- package/dist/integrations/github/types.js +2 -0
- package/dist/integrations/github/types.js.map +1 -0
- package/dist/plugins/context.d.ts +13 -0
- package/dist/plugins/context.d.ts.map +1 -0
- package/dist/plugins/context.js +102 -0
- package/dist/plugins/context.js.map +1 -0
- package/dist/plugins/examples/react.d.ts +8 -0
- package/dist/plugins/examples/react.d.ts.map +1 -0
- package/dist/plugins/examples/react.js +129 -0
- package/dist/plugins/examples/react.js.map +1 -0
- package/dist/plugins/index.d.ts +5 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/registry.d.ts +45 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +236 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/plugins/types.d.ts +148 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +2 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/reporters/html.d.ts +11 -0
- package/dist/reporters/html.d.ts.map +1 -0
- package/dist/reporters/html.js +1352 -0
- package/dist/reporters/html.js.map +1 -0
- package/dist/reporters/json.d.ts +10 -0
- package/dist/reporters/json.d.ts.map +1 -0
- package/dist/reporters/json.js +11 -0
- package/dist/reporters/json.js.map +1 -0
- package/dist/reporters/markdown.d.ts +7 -0
- package/dist/reporters/markdown.d.ts.map +1 -0
- package/dist/reporters/markdown.js +74 -0
- package/dist/reporters/markdown.js.map +1 -0
- package/dist/reporters/sarif.d.ts +133 -0
- package/dist/reporters/sarif.d.ts.map +1 -0
- package/dist/reporters/sarif.js +268 -0
- package/dist/reporters/sarif.js.map +1 -0
- package/dist/reporters/terminal.d.ts +17 -0
- package/dist/reporters/terminal.d.ts.map +1 -0
- package/dist/reporters/terminal.js +423 -0
- package/dist/reporters/terminal.js.map +1 -0
- package/dist/rules/categories.d.ts +8 -0
- package/dist/rules/categories.d.ts.map +1 -0
- package/dist/rules/categories.js +23 -0
- package/dist/rules/categories.js.map +1 -0
- package/dist/rules/definitions.d.ts +25 -0
- package/dist/rules/definitions.d.ts.map +1 -0
- package/dist/rules/definitions.js +429 -0
- package/dist/rules/definitions.js.map +1 -0
- package/dist/rules/registry.d.ts +36 -0
- package/dist/rules/registry.d.ts.map +1 -0
- package/dist/rules/registry.js +64 -0
- package/dist/rules/registry.js.map +1 -0
- package/dist/rules/severity.d.ts +13 -0
- package/dist/rules/severity.d.ts.map +1 -0
- package/dist/rules/severity.js +15 -0
- package/dist/rules/severity.js.map +1 -0
- package/dist/scoring/confidence.d.ts +12 -0
- package/dist/scoring/confidence.d.ts.map +1 -0
- package/dist/scoring/confidence.js +22 -0
- package/dist/scoring/confidence.js.map +1 -0
- package/dist/scoring/score.d.ts +27 -0
- package/dist/scoring/score.d.ts.map +1 -0
- package/dist/scoring/score.js +81 -0
- package/dist/scoring/score.js.map +1 -0
- package/dist/scoring/weights.d.ts +11 -0
- package/dist/scoring/weights.d.ts.map +1 -0
- package/dist/scoring/weights.js +26 -0
- package/dist/scoring/weights.js.map +1 -0
- package/dist/utils/filesystem.d.ts +65 -0
- package/dist/utils/filesystem.d.ts.map +1 -0
- package/dist/utils/filesystem.js +299 -0
- package/dist/utils/filesystem.js.map +1 -0
- package/dist/utils/git.d.ts +47 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +125 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +25 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/paths.d.ts +30 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +48 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/timing.d.ts +12 -0
- package/dist/utils/timing.d.ts.map +1 -0
- package/dist/utils/timing.js +19 -0
- package/dist/utils/timing.js.map +1 -0
- package/package.json +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,725 @@
|
|
|
1
|
+
# FATHOM
|
|
2
|
+
|
|
3
|
+
> **Know what's beneath the surface.**
|
|
4
|
+
|
|
5
|
+
[](https://github.com/Ash-Technologia/Fathom/actions)
|
|
6
|
+
[](https://www.npmjs.com/package/@ash-technologia/fathom)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](https://nodejs.org)
|
|
9
|
+
[](https://github.com/Ash-Technologia/Fathom)
|
|
10
|
+
[](https://github.com/Ash-Technologia/Fathom/blob/main/CONTRIBUTING.md)
|
|
11
|
+
|
|
12
|
+
**Fathom** is a local-first repository intelligence CLI for developers. It analyzes software repositories and produces an actionable understanding of health, architecture, security hygiene, Git hygiene, dependencies, testing maturity, documentation quality, and CI/CD readiness.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## ⚡ Quick Start
|
|
17
|
+
|
|
18
|
+
Analyze any repository directly with `npx`:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @ash-technologia/fathom .
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or install globally:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g @ash-technologia/fathom
|
|
28
|
+
fathom .
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 🧭 Why Fathom?
|
|
34
|
+
|
|
35
|
+
Most linters focus exclusively on syntax or code formatting, and full security scanners are often slow, cloud-dependent, or noisy.
|
|
36
|
+
|
|
37
|
+
Fathom answers a different question:
|
|
38
|
+
|
|
39
|
+
> *"What is really going on inside this codebase, and what should I address before continuing work or shipping it?"*
|
|
40
|
+
|
|
41
|
+
### Core Principles
|
|
42
|
+
|
|
43
|
+
- 🔒 **Local-First & Privacy-Focused**: Never uploads code or telemetry. Safe, read-only operations only.
|
|
44
|
+
- 🎯 **Deterministic**: Same repository state produces the exact same score and findings every time.
|
|
45
|
+
- 🚫 **Safe Secrets Handling**: Detects exposed credentials without ever printing or logging secret values.
|
|
46
|
+
- 🧩 **Extensible Architecture**: 9 isolated analyzers with typed findings, metrics, and scoring.
|
|
47
|
+
- ⚡ **Blazing Fast**: Single filesystem traversal index; completes typical repository scans in under 200ms.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 📊 Terminal UX
|
|
52
|
+
|
|
53
|
+
Running `fathom .` produces a clean, readable overview:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
FATHOM
|
|
57
|
+
Know what's beneath the surface.
|
|
58
|
+
|
|
59
|
+
Scanning my-app...
|
|
60
|
+
|
|
61
|
+
Detected: Node.js, TypeScript, React, Next.js
|
|
62
|
+
|
|
63
|
+
────────────────────────────────────────────────────────
|
|
64
|
+
|
|
65
|
+
HEALTH
|
|
66
|
+
|
|
67
|
+
88 / 100
|
|
68
|
+
Healthy
|
|
69
|
+
|
|
70
|
+
Project 100
|
|
71
|
+
Git 94
|
|
72
|
+
Security 85
|
|
73
|
+
Dependencies 90
|
|
74
|
+
Code Quality 85
|
|
75
|
+
Testing 80
|
|
76
|
+
Documentation 85
|
|
77
|
+
CI/CD 90
|
|
78
|
+
|
|
79
|
+
────────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
ATTENTION
|
|
82
|
+
|
|
83
|
+
HIGH
|
|
84
|
+
Environment file may not be gitignored: .env
|
|
85
|
+
.env
|
|
86
|
+
|
|
87
|
+
MEDIUM
|
|
88
|
+
Low test-to-source file ratio
|
|
89
|
+
Test files represent only 8% of source files (2 tests vs 24 source files).
|
|
90
|
+
|
|
91
|
+
LOW
|
|
92
|
+
12 debug statements found across source files
|
|
93
|
+
|
|
94
|
+
────────────────────────────────────────────────────────
|
|
95
|
+
|
|
96
|
+
NEXT STEPS
|
|
97
|
+
|
|
98
|
+
1. Add ".env" to .gitignore to prevent accidental commits.
|
|
99
|
+
2. Increase test coverage for critical application logic.
|
|
100
|
+
3. Remove or gate debug statements before shipping to production.
|
|
101
|
+
|
|
102
|
+
────────────────────────────────────────────────────────
|
|
103
|
+
|
|
104
|
+
✓ Project
|
|
105
|
+
✓ Git
|
|
106
|
+
✓ Security
|
|
107
|
+
✓ Dependencies
|
|
108
|
+
✓ Code Quality
|
|
109
|
+
✓ Testing
|
|
110
|
+
✓ Documentation
|
|
111
|
+
✓ CI/CD
|
|
112
|
+
✓ Architecture
|
|
113
|
+
|
|
114
|
+
Completed in 142ms
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 🛠️ CLI Commands & Options
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# Analyze current directory
|
|
123
|
+
fathom .
|
|
124
|
+
|
|
125
|
+
# Analyze specific repository path
|
|
126
|
+
fathom /path/to/repo
|
|
127
|
+
|
|
128
|
+
# Output machine-readable JSON to stdout
|
|
129
|
+
fathom --json
|
|
130
|
+
|
|
131
|
+
# Save JSON report directly to a file
|
|
132
|
+
fathom --json -o report.json
|
|
133
|
+
|
|
134
|
+
# Output SARIF 2.1.0 to stdout
|
|
135
|
+
fathom --sarif
|
|
136
|
+
|
|
137
|
+
# Save SARIF 2.1.0 report directly to a file for GitHub Code Scanning
|
|
138
|
+
fathom --sarif -o fathom.sarif
|
|
139
|
+
|
|
140
|
+
# Display all findings without truncation (disables the default 10-finding limit)
|
|
141
|
+
fathom --verbose
|
|
142
|
+
|
|
143
|
+
# Generate self-contained HTML report
|
|
144
|
+
fathom --html report.html
|
|
145
|
+
|
|
146
|
+
# Save a deterministic baseline to .fathom/baseline.json
|
|
147
|
+
fathom --baseline
|
|
148
|
+
|
|
149
|
+
# Compare current analysis against saved baseline and report regressions
|
|
150
|
+
fathom --compare
|
|
151
|
+
|
|
152
|
+
# Compare against baseline and output machine-readable JSON
|
|
153
|
+
fathom --compare --json
|
|
154
|
+
|
|
155
|
+
# Compare against baseline and generate interactive HTML report
|
|
156
|
+
fathom --compare --html report.html
|
|
157
|
+
|
|
158
|
+
# Analyze changes introduced by Git diff (auto-detects base branch)
|
|
159
|
+
fathom --diff
|
|
160
|
+
|
|
161
|
+
# Analyze changes against a specific branch, commit, or remote ref
|
|
162
|
+
fathom --diff main
|
|
163
|
+
fathom --diff HEAD~1
|
|
164
|
+
fathom --diff origin/main
|
|
165
|
+
|
|
166
|
+
# PR analysis with machine-readable JSON output
|
|
167
|
+
fathom --diff main --json
|
|
168
|
+
|
|
169
|
+
# View architecture hierarchy and graph warnings in terminal
|
|
170
|
+
fathom --architecture
|
|
171
|
+
|
|
172
|
+
# Inspect dependency inventory and lockfile metrics (offline)
|
|
173
|
+
fathom --deps
|
|
174
|
+
|
|
175
|
+
# Inspect dependency inventory with opt-in vulnerability & freshness checks
|
|
176
|
+
fathom --deps --online
|
|
177
|
+
|
|
178
|
+
# Run in CI mode (compact logging, fails if critical/high findings exist)
|
|
179
|
+
fathom --ci
|
|
180
|
+
|
|
181
|
+
# Fail CI build if overall health score is below threshold, regression is detected, or PR diff introduces findings
|
|
182
|
+
fathom --ci --fail-under 80
|
|
183
|
+
|
|
184
|
+
# Display version or help
|
|
185
|
+
fathom --version
|
|
186
|
+
fathom --help
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Exit Codes
|
|
190
|
+
|
|
191
|
+
| Code | Meaning |
|
|
192
|
+
|:----:|:--------|
|
|
193
|
+
| **0** | Analysis successful and meets health thresholds |
|
|
194
|
+
| **1** | Analysis complete, but `--fail-under` threshold failed, critical findings found in CI mode, regression detected in CI mode, or PR diff introduces findings |
|
|
195
|
+
| **2** | Invalid CLI usage, missing/corrupted baseline, Git diff error (e.g. not a git repo, unresolvable base ref), or configuration syntax error |
|
|
196
|
+
| **3** | Repository access error or fatal system failure |
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 🔀 Pull Request & Git Diff Intelligence
|
|
201
|
+
|
|
202
|
+
Fathom extends beyond isolated file scanning with **PR-aware Git Diff Intelligence**. Instead of inspecting modified files in a vacuum, Fathom evaluates changes against the complete repository context:
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
Git Diff
|
|
206
|
+
↓
|
|
207
|
+
RepositoryContext
|
|
208
|
+
↓
|
|
209
|
+
Affected files
|
|
210
|
+
↓
|
|
211
|
+
Existing analyzers/rules
|
|
212
|
+
↓
|
|
213
|
+
Finding comparison
|
|
214
|
+
↓
|
|
215
|
+
PR report
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### How It Works:
|
|
219
|
+
1. **Safe Git Operations**: Invokes Git strictly through `child_process.execFile` in read-only mode (`git rev-parse`, `git diff`, `git show`, `git merge-base`). Never modifies working tree, never checks out branches, never executes repository scripts.
|
|
220
|
+
2. **Whole-Repository Shadow Context**: Reconstructs base file versions for changed files using in-memory/temp shadow buffers, keeping untouched files referenced directly on disk. Runs all 26 rules across full architectural relationships.
|
|
221
|
+
3. **Three-Way Finding Categorization**:
|
|
222
|
+
- **New Findings**: Issues introduced by added or modified lines in the pull request.
|
|
223
|
+
- **Touched Findings**: Pre-existing issues within files touched by the diff.
|
|
224
|
+
- **Resolved Findings**: Issues previously present that were eliminated by the PR.
|
|
225
|
+
4. **Health & Category Impact**: Computes overall health score delta (`91 → 84 (-7 points)`) and per-category scoring shifts (Security, Quality, Testing, etc.).
|
|
226
|
+
5. **Git Resilience**: Gracefully handles detached HEAD states, shallow clones (providing actionable fetch guidance), merge commits, and binary files.
|
|
227
|
+
|
|
228
|
+
Example terminal output:
|
|
229
|
+
```text
|
|
230
|
+
FATHOM PR ANALYSIS
|
|
231
|
+
────────────────────────────────────────────────────────
|
|
232
|
+
|
|
233
|
+
Changed:
|
|
234
|
+
8 files
|
|
235
|
+
+312 lines
|
|
236
|
+
-87 lines
|
|
237
|
+
|
|
238
|
+
Health:
|
|
239
|
+
91 → 84
|
|
240
|
+
-7 points
|
|
241
|
+
|
|
242
|
+
NEW FINDINGS
|
|
243
|
+
🔴 SEC-002
|
|
244
|
+
Potential secret detected
|
|
245
|
+
|
|
246
|
+
🟠 QUAL-004
|
|
247
|
+
Empty catch block
|
|
248
|
+
|
|
249
|
+
RESOLVED
|
|
250
|
+
✓ TEST-004
|
|
251
|
+
|
|
252
|
+
CATEGORY IMPACT
|
|
253
|
+
Security -12
|
|
254
|
+
Quality -4
|
|
255
|
+
Testing +3
|
|
256
|
+
|
|
257
|
+
VERDICT
|
|
258
|
+
⚠ Changes introduce 2 findings
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 📉 Baseline & Regression Tracking
|
|
264
|
+
|
|
265
|
+
Fathom supports deterministic repository baselines to detect regressions over time or during CI/CD checks:
|
|
266
|
+
|
|
267
|
+
1. **Create a baseline**:
|
|
268
|
+
```bash
|
|
269
|
+
fathom --baseline
|
|
270
|
+
```
|
|
271
|
+
Analyzes the repository and saves `.fathom/baseline.json` containing only scores, metrics, rule IDs, and safe evidence — never secret values or repository source code.
|
|
272
|
+
|
|
273
|
+
2. **Compare current analysis**:
|
|
274
|
+
```bash
|
|
275
|
+
fathom --compare
|
|
276
|
+
```
|
|
277
|
+
Detects:
|
|
278
|
+
- Overall health score change (e.g. `91 → 84 (-7)`)
|
|
279
|
+
- Category score changes
|
|
280
|
+
- Newly introduced findings (`+`)
|
|
281
|
+
- Resolved findings (`-`)
|
|
282
|
+
- Unchanged & modified findings
|
|
283
|
+
- Regression verdict (`REGRESSION: YES / NO`)
|
|
284
|
+
|
|
285
|
+
3. **Export reports**:
|
|
286
|
+
- `fathom --compare --json`: Attaches regression comparison data to the JSON output.
|
|
287
|
+
- `fathom --compare --html report.html`: Generates an interactive visual report with dedicated regression breakdown.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 🏛️ Architecture Intelligence
|
|
292
|
+
|
|
293
|
+
Fathom includes a lightweight in-memory architecture graph analyzer that inspects import/export topologies without executing project code:
|
|
294
|
+
|
|
295
|
+
- **Static Import Parsing**: Scans ESM, CommonJS, dynamic imports, and Python modules.
|
|
296
|
+
- **Path Alias Resolution**: Honors `tsconfig.json` / `jsconfig.json` `compilerOptions.paths` and `baseUrl`.
|
|
297
|
+
- **Circular Dependency Detection (`ARCH-002`)**: Uses Tarjan's SCC algorithm to detect directed import loops.
|
|
298
|
+
- **Layer Boundary Violations (`ARCH-003`)**: Detects backend code referencing UI components, or client code referencing server-only primitives (`child_process`, `fs`, `net`, etc.).
|
|
299
|
+
- **Deep Coupling & Sizing (`ARCH-004`, `ARCH-005`)**: Flags excessive fan-out imports and large monolithic files requiring decomposition.
|
|
300
|
+
- **Orphaned File Detection (`ARCH-006`)**: Identifies dead, unreferenced source modules.
|
|
301
|
+
- **CLI View**: Run `fathom --architecture` for a visual tree of layers and graph warnings.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 🤖 GitHub Action Integration
|
|
306
|
+
|
|
307
|
+
You can run Fathom directly in your GitHub Actions workflows with zero extra configuration:
|
|
308
|
+
|
|
309
|
+
```yaml
|
|
310
|
+
name: Repository Intelligence
|
|
311
|
+
|
|
312
|
+
on:
|
|
313
|
+
push:
|
|
314
|
+
branches: [main]
|
|
315
|
+
pull_request:
|
|
316
|
+
branches: [main]
|
|
317
|
+
|
|
318
|
+
jobs:
|
|
319
|
+
fathom:
|
|
320
|
+
name: Repository Health Check
|
|
321
|
+
runs-on: ubuntu-latest
|
|
322
|
+
steps:
|
|
323
|
+
- name: Checkout Code
|
|
324
|
+
uses: actions/checkout@v4
|
|
325
|
+
|
|
326
|
+
- name: Run Fathom
|
|
327
|
+
uses: Ash-Technologia/Fathom@main
|
|
328
|
+
with:
|
|
329
|
+
fail-under: '80'
|
|
330
|
+
html: 'fathom-report.html'
|
|
331
|
+
sarif: 'fathom.sarif'
|
|
332
|
+
|
|
333
|
+
- name: Upload HTML Report
|
|
334
|
+
uses: actions/upload-artifact@v4
|
|
335
|
+
if: always()
|
|
336
|
+
with:
|
|
337
|
+
name: fathom-report
|
|
338
|
+
path: fathom-report.html
|
|
339
|
+
|
|
340
|
+
- name: Upload SARIF to GitHub Code Scanning
|
|
341
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
342
|
+
if: always()
|
|
343
|
+
with:
|
|
344
|
+
sarif_file: fathom.sarif
|
|
345
|
+
category: fathom
|
|
346
|
+
|
|
347
|
+
fathom-pr:
|
|
348
|
+
name: PR Intelligence & Step Summary
|
|
349
|
+
if: github.event_name == 'pull_request'
|
|
350
|
+
runs-on: ubuntu-latest
|
|
351
|
+
permissions:
|
|
352
|
+
contents: read
|
|
353
|
+
pull-requests: write # Required only if pr-comment: 'true'
|
|
354
|
+
steps:
|
|
355
|
+
- name: Checkout Code
|
|
356
|
+
uses: actions/checkout@v4
|
|
357
|
+
with:
|
|
358
|
+
fetch-depth: 0 # Full history needed for base ref diff
|
|
359
|
+
|
|
360
|
+
- name: Run Fathom PR Intelligence
|
|
361
|
+
uses: Ash-Technologia/Fathom@main
|
|
362
|
+
with:
|
|
363
|
+
diff: 'true' # Automatically resolves github.base_ref
|
|
364
|
+
pr-comment: 'true'
|
|
365
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### GitHub Actions Step Summary & PR Comments
|
|
369
|
+
|
|
370
|
+
When running in GitHub Actions:
|
|
371
|
+
- **Automatic Step Summary**: If running under a `pull_request` event or when `--diff` is analyzed, Fathom automatically generates and writes a concise Markdown summary to `$GITHUB_STEP_SUMMARY`.
|
|
372
|
+
- **PR Commenting**: Passing `--pr-comment` posts the concise PR health and findings table directly as a review comment on the pull request.
|
|
373
|
+
- **Offline / Local Execution**: When executed locally, Fathom runs completely offline without needing GitHub credentials or network connectivity. Tokens are never logged or exposed.
|
|
374
|
+
- **Custom Summary File**: Output Markdown directly to any file via `fathom --diff [ref] --summary pr-summary.md`.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## 🛡️ GitHub Code Scanning & SARIF 2.1.0 Integration
|
|
379
|
+
|
|
380
|
+
Fathom natively exports findings in standard **SARIF 2.1.0** (Static Analysis Results Interchange Format) format, which integrates seamlessly into GitHub Code Scanning:
|
|
381
|
+
|
|
382
|
+
```
|
|
383
|
+
Fathom
|
|
384
|
+
↓
|
|
385
|
+
SARIF (fathom --sarif -o fathom.sarif)
|
|
386
|
+
↓
|
|
387
|
+
GitHub Code Scanning (github/codeql-action/upload-sarif)
|
|
388
|
+
↓
|
|
389
|
+
Security & Quality Alerts in GitHub Security tab & PRs
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Standalone GitHub Actions Workflow
|
|
393
|
+
|
|
394
|
+
To run Fathom via npm/npx and upload results directly to GitHub Code Scanning:
|
|
395
|
+
|
|
396
|
+
```yaml
|
|
397
|
+
name: Security & Health Scanning
|
|
398
|
+
|
|
399
|
+
on:
|
|
400
|
+
push:
|
|
401
|
+
branches: [main]
|
|
402
|
+
pull_request:
|
|
403
|
+
branches: [main]
|
|
404
|
+
|
|
405
|
+
jobs:
|
|
406
|
+
fathom-scan:
|
|
407
|
+
name: Fathom SARIF Analysis
|
|
408
|
+
runs-on: ubuntu-latest
|
|
409
|
+
permissions:
|
|
410
|
+
security-events: write
|
|
411
|
+
contents: read
|
|
412
|
+
steps:
|
|
413
|
+
- name: Checkout Code
|
|
414
|
+
uses: actions/checkout@v4
|
|
415
|
+
|
|
416
|
+
- name: Set up Node.js
|
|
417
|
+
uses: actions/setup-node@v4
|
|
418
|
+
with:
|
|
419
|
+
node-version: 20
|
|
420
|
+
|
|
421
|
+
- name: Run Fathom SARIF Analysis
|
|
422
|
+
run: npx @ash-technologia/fathom . --sarif -o fathom.sarif
|
|
423
|
+
|
|
424
|
+
- name: Upload SARIF to GitHub Code Scanning
|
|
425
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
426
|
+
if: always()
|
|
427
|
+
with:
|
|
428
|
+
sarif_file: fathom.sarif
|
|
429
|
+
category: fathom
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## 🔍 Analyzers & Rules (26 Core Rules)
|
|
435
|
+
|
|
436
|
+
Fathom evaluates repositories across **9 isolated analyzers**:
|
|
437
|
+
|
|
438
|
+
| Rule ID | Category | Title | Severity |
|
|
439
|
+
|:---|:---|:---|:---:|
|
|
440
|
+
| `PROJ-001` | Project | Ecosystem detection (Node.js, Python, Go, Rust, Java, PHP) | `info` |
|
|
441
|
+
| `PROJ-002` | Project | Framework detection (React, Next.js, Vue, Angular, Express, FastAPI, etc.) | `info` |
|
|
442
|
+
| `PROJ-003` | Project | Package manager detection (npm, pnpm, yarn, poetry, cargo, etc.) | `info` |
|
|
443
|
+
| `PROJ-004` | Project | Repository size & file count heuristics | `info` |
|
|
444
|
+
| `GIT-001` | Git | Git repository initialized check | `medium` |
|
|
445
|
+
| `GIT-002` | Git | `.gitignore` existence | `medium` |
|
|
446
|
+
| `GIT-003` | Git | Generated directory ignore checks (`node_modules`, `dist`, `target`, etc.) | `medium` |
|
|
447
|
+
| `GIT-004` | Git | Detection of large files committed (>10 MB) | `high` |
|
|
448
|
+
| `GIT-005` | Git | Uncommitted changes status (informational, does not penalize) | `info` |
|
|
449
|
+
| `GIT-006` | Git | Empty repository (no commits) check | `low` |
|
|
450
|
+
| `SEC-001` | Security | `.env` not ignored by Git | `high` |
|
|
451
|
+
| `SEC-002` | Security | Potential credentials/secrets in source code (AWS keys, tokens, etc.) | `high` |
|
|
452
|
+
| `SEC-003` | Security | Private key files present (`id_rsa`, `.pem`, `.key`) | `critical` |
|
|
453
|
+
| `SEC-004` | Security | Tracked credential/config files (`secrets.json`, etc.) | `high` |
|
|
454
|
+
| `SEC-005` | Security | Credentials embedded in connection URLs | `high` |
|
|
455
|
+
| `DEP-001` | Dependencies | Manifest detection (`package.json`, `Cargo.toml`, etc.) | `info` |
|
|
456
|
+
| `DEP-002` | Dependencies | Lockfile detection (`package-lock.json`, `pnpm-lock.yaml`, etc.) | `info` |
|
|
457
|
+
| `DEP-003` | Dependencies | Missing lockfile when manifest is present | `medium` |
|
|
458
|
+
| `DEP-004` | Dependencies | Package manager / lockfile mismatch | `low` |
|
|
459
|
+
| `DEP-005` | Dependencies | Total dependencies declared | `info` |
|
|
460
|
+
| `DEP-006` | Dependencies | Suspicious dependency configuration (wildcards, git URLs, duplicate declarations) | `medium` |
|
|
461
|
+
| `DEP-007` | Dependencies | Known security vulnerabilities detected in dependencies (online) | `high` |
|
|
462
|
+
| `DEP-008` | Dependencies | Duplicate versions of the same package installed | `low` |
|
|
463
|
+
| `DEP-009` | Dependencies | Outdated major/minor dependencies detected (online) | `low` |
|
|
464
|
+
| `DEP-010` | Dependencies | Unused production dependency declared in manifest | `low` |
|
|
465
|
+
| `QUAL-001` | Quality | TODO comment count | `low` |
|
|
466
|
+
| `QUAL-002` | Quality | FIXME comment count | `medium` |
|
|
467
|
+
| `QUAL-003` | Quality | Debug/console statements left in code (`console.log`, `debugger`, etc.) | `low` |
|
|
468
|
+
| `QUAL-004` | Quality | Empty catch blocks | `medium` |
|
|
469
|
+
| `QUAL-005` | Quality | Extremely large source files (>500 lines) | `low` |
|
|
470
|
+
| `QUAL-006` | Quality | Deep directory nesting (>6 levels) | `low` |
|
|
471
|
+
| `TEST-001` | Testing | Standard test directory detection | `low` |
|
|
472
|
+
| `TEST-002` | Testing | Test files detection | `medium` |
|
|
473
|
+
| `TEST-003` | Testing | Test scripts in package manifest | `medium` |
|
|
474
|
+
| `TEST-004` | Testing | Test-to-source file ratio heuristic | `medium` |
|
|
475
|
+
| `DOC-001` | Documentation | `README.md` exists | `medium` |
|
|
476
|
+
| `DOC-002` | Documentation | Installation instructions present in README | `low` |
|
|
477
|
+
| `DOC-003` | Documentation | Usage instructions present in README | `low` |
|
|
478
|
+
| `DOC-004` | Documentation | `LICENSE` exists | `medium` |
|
|
479
|
+
| `DOC-005` | Documentation | `CONTRIBUTING.md` exists | `low` |
|
|
480
|
+
| `DOC-006` | Documentation | `SECURITY.md` exists | `low` |
|
|
481
|
+
| `DOC-007` | Documentation | Project description present in README | `low` |
|
|
482
|
+
| `CI-001` | CI/CD | GitHub Actions workflows detected | `info` |
|
|
483
|
+
| `CI-002` | CI/CD | CI/CD configuration presence | `medium` |
|
|
484
|
+
| `CI-003` | CI/CD | Test execution detected in CI | `medium` |
|
|
485
|
+
| `CI-004` | CI/CD | Build step detected in CI | `low` |
|
|
486
|
+
| `ARCH-001` | Architecture | Project layout & structure observations | `info` |
|
|
487
|
+
| `ARCH-002` | Architecture | Circular import dependencies detected | `high` |
|
|
488
|
+
| `ARCH-003` | Architecture | Suspicious cross-layer import or boundary violation | `high` |
|
|
489
|
+
| `ARCH-004` | Architecture | Deep fan-out coupling to internal modules | `low` |
|
|
490
|
+
| `ARCH-005` | Architecture | Large monolithic module decomposition indicator | `low` |
|
|
491
|
+
| `ARCH-006` | Architecture | Orphaned source file unreferenced across repository | `info` |
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## 📈 Scoring System
|
|
496
|
+
|
|
497
|
+
Fathom calculates individual 0–100 scores for each category based on deductions from detected findings:
|
|
498
|
+
|
|
499
|
+
| Category | Weight |
|
|
500
|
+
|:---|:---:|
|
|
501
|
+
| **Security** | 20% |
|
|
502
|
+
| **Git** | 15% |
|
|
503
|
+
| **Project Structure** | 15% |
|
|
504
|
+
| **Testing** | 15% |
|
|
505
|
+
| **Dependencies** | 10% |
|
|
506
|
+
| **Documentation** | 10% |
|
|
507
|
+
| **Code Quality** | 10% |
|
|
508
|
+
| **CI/CD** | 5% |
|
|
509
|
+
|
|
510
|
+
### Score Bands
|
|
511
|
+
|
|
512
|
+
- **90–100**: Excellent
|
|
513
|
+
- **75–89**: Healthy
|
|
514
|
+
- **60–74**: Fair
|
|
515
|
+
- **40–59**: Needs Attention
|
|
516
|
+
- **0–39**: Critical
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## ⚙️ Configuration & Repository Targeting
|
|
521
|
+
|
|
522
|
+
### 1. `.fathomignore`
|
|
523
|
+
|
|
524
|
+
Create a `.fathomignore` file in the root of your repository to specify repository-specific exclusion patterns using familiar gitignore-style syntax:
|
|
525
|
+
|
|
526
|
+
```text
|
|
527
|
+
# Exclude code generation and vendor directories
|
|
528
|
+
generated/
|
|
529
|
+
vendor/
|
|
530
|
+
legacy/
|
|
531
|
+
|
|
532
|
+
# Exclude generated artifacts
|
|
533
|
+
*.generated.ts
|
|
534
|
+
*.min.js
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
- Comments starting with `#` and blank lines are ignored.
|
|
538
|
+
- Trailing slashes automatically match directories and all nested contents.
|
|
539
|
+
- Patterns are merged deterministically with `.fathom.json` and built-in ignore lists.
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
### 2. `.fathom.json`
|
|
544
|
+
|
|
545
|
+
Customize rules, thresholds, and quality gates with a `.fathom.json` configuration file:
|
|
546
|
+
|
|
547
|
+
```json
|
|
548
|
+
{
|
|
549
|
+
"version": 1,
|
|
550
|
+
"ignore": [
|
|
551
|
+
"fixtures/**"
|
|
552
|
+
],
|
|
553
|
+
"rules": {
|
|
554
|
+
"QUAL-001": "warning",
|
|
555
|
+
"QUAL-005": "off"
|
|
556
|
+
},
|
|
557
|
+
"failUnder": 75
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
#### Rule States:
|
|
562
|
+
- `"off"`: Disables the rule completely.
|
|
563
|
+
- `"warning"`: Enables the rule at warning severity.
|
|
564
|
+
- `"error"`: Enables the rule at error severity (triggers CI failure if violated).
|
|
565
|
+
|
|
566
|
+
#### Security Safeguards:
|
|
567
|
+
To prevent unintentional security vulnerabilities, Fathom **does not allow configuration to silently disable critical security checks** (e.g. `SEC-001` through `SEC-005`).
|
|
568
|
+
Disabling a security rule requires explicit authorization:
|
|
569
|
+
```json
|
|
570
|
+
{
|
|
571
|
+
"version": 1,
|
|
572
|
+
"rules": {
|
|
573
|
+
"SEC-002": {
|
|
574
|
+
"enabled": false,
|
|
575
|
+
"reason": "Handled upstream by pre-commit secrets hook"
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
```
|
|
580
|
+
Or with global opt-in:
|
|
581
|
+
```json
|
|
582
|
+
{
|
|
583
|
+
"version": 1,
|
|
584
|
+
"allowDisableSecurity": true,
|
|
585
|
+
"rules": {
|
|
586
|
+
"SEC-003": "off"
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
```
|
|
590
|
+
If disabled, Fathom explicitly logs a warning to stderr during analysis.
|
|
591
|
+
|
|
592
|
+
#### Configuration Precedence:
|
|
593
|
+
```text
|
|
594
|
+
CLI Arguments (e.g. --fail-under 80, --ci, explicit flags)
|
|
595
|
+
↓
|
|
596
|
+
.fathom.json Configuration
|
|
597
|
+
↓
|
|
598
|
+
.fathomignore Patterns
|
|
599
|
+
↓
|
|
600
|
+
Built-in Defaults
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## 🏗️ Architecture Intelligence (`--architecture`)
|
|
606
|
+
|
|
607
|
+
Fathom builds an in-memory structural graph without running any code:
|
|
608
|
+
- **Zero Runtime Execution**: Parses import/export relationships purely via AST text regex scanners; supports ESM, CommonJS, dynamic imports, and Python modules.
|
|
609
|
+
- **Path Alias Resolution**: Automatically resolves module aliases defined in `tsconfig.json` or `jsconfig.json`.
|
|
610
|
+
- **Cycle Detection**: Uses Tarjan's Strongly Connected Components (SCC) algorithm to detect directed import loops (`ARCH-002`).
|
|
611
|
+
- **Boundary Violations (`ARCH-003`)**: Flags suspicious cross-layer imports (e.g., backend importing React components or client importing `fs`/`child_process`).
|
|
612
|
+
- **Deep Coupling (`ARCH-004`) & Monolithic Modules (`ARCH-005`)**: Flags high fan-out files and oversized monolithic units.
|
|
613
|
+
- **Orphan Detection (`ARCH-006`)**: Identifies unreachable source files with confident heuristic filtering.
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
## 📦 Dependency Intelligence (`--deps`, `--deps --online`)
|
|
618
|
+
|
|
619
|
+
Fathom provides deep dependency insights without acting as a package manager or mutating repositories:
|
|
620
|
+
- **Offline-by-Default Safe Analysis (`fathom --deps`)**:
|
|
621
|
+
- Direct vs transitive dependency counting across multi-package projects.
|
|
622
|
+
- Multi-lockfile support: npm `package-lock.json` (v1, v2, v3), `yarn.lock` (line-by-line), and `pnpm-lock.yaml`.
|
|
623
|
+
- Duplicate dependency version detection (`DEP-008`).
|
|
624
|
+
- Suspicious dependency configurations (`DEP-006`: wildcards, git URLs, duplicate dev/prod declarations).
|
|
625
|
+
- High-confidence unused dependency detection (`DEP-010`) cross-checked against static import graphs.
|
|
626
|
+
- **Opt-in Online Intelligence (`fathom --deps --online`)**:
|
|
627
|
+
- Batch queries to OSV API (Open Source Vulnerabilities) (`DEP-007`) with strict 3s timeouts.
|
|
628
|
+
- Npm registry queries for outdated package detection (`DEP-009`).
|
|
629
|
+
- Completely silent offline fallback when network is unavailable.
|
|
630
|
+
- Zero repository code transmission or token leakage.
|
|
631
|
+
|
|
632
|
+
## 🔌 Plugin Architecture
|
|
633
|
+
|
|
634
|
+
Fathom features a stable, sandboxed plugin system enabling developers to extend Fathom with custom rules and analyzers without modifying core engine code:
|
|
635
|
+
|
|
636
|
+
```text
|
|
637
|
+
Fathom Core
|
|
638
|
+
↓
|
|
639
|
+
Plugin Registry
|
|
640
|
+
├── @fathom/plugin-react (Built-in)
|
|
641
|
+
├── @fathom/plugin-docker
|
|
642
|
+
└── Community Plugins
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
### Stable Plugin API:
|
|
646
|
+
- `PluginManifest`: Defines package name, semver version, description, author, and declared rules.
|
|
647
|
+
- `PluginRule`: Extends Fathom rules with `recommendation`, `confidence`, `autoFixable`, and reference URLs.
|
|
648
|
+
- `PluginAnalyzer`: Custom analyzer contract (`id`, `name`, `category`, `description`, `analyze(context: PluginContext)`).
|
|
649
|
+
- `PluginContext`: Read-only, sandboxed context enforcing path traversal protections, bounded file reads (1MB limit), and structured finding creation.
|
|
650
|
+
- `PluginRegistry`: Lifecycle manager, schema validator, and error boundary wrapper.
|
|
651
|
+
|
|
652
|
+
### Example Internal Plugin: `@fathom/plugin-react`
|
|
653
|
+
Built into Fathom as a reference implementation:
|
|
654
|
+
- `REACT-001` (Security / medium): `dangerouslySetInnerHTML` usage without sanitization.
|
|
655
|
+
- `REACT-002` (Quality / low): Array index used as key or missing key in list render.
|
|
656
|
+
- `REACT-003` (Quality / medium): Direct React state mutation (`this.state.x = ...`).
|
|
657
|
+
|
|
658
|
+
### Enabling Plugins via `.fathom.json`:
|
|
659
|
+
```json
|
|
660
|
+
{
|
|
661
|
+
"version": 1,
|
|
662
|
+
"plugins": [
|
|
663
|
+
"@fathom/plugin-react"
|
|
664
|
+
],
|
|
665
|
+
"rules": {
|
|
666
|
+
"REACT-001": "warning"
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
---
|
|
672
|
+
|
|
673
|
+
## 💻 Interactive Developer Dashboard (HTML)
|
|
674
|
+
|
|
675
|
+
Generate a polished, standalone, interactive single-file dashboard for any repository:
|
|
676
|
+
|
|
677
|
+
```bash
|
|
678
|
+
fathom --html report.html
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
Or compare against a baseline and generate an interactive regression report:
|
|
682
|
+
|
|
683
|
+
```bash
|
|
684
|
+
fathom --compare --html report.html
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
### Dashboard Features:
|
|
688
|
+
- **100% Self-Contained**: Zero external CDNs, fonts, tracking scripts, or network calls. Opens instantly and safely in any browser offline or in air-gapped CI/CD environments.
|
|
689
|
+
- **12 Comprehensive Sections**:
|
|
690
|
+
1. **Overall Health Hero**: Health score, color-coded status badge, and repository metadata tags.
|
|
691
|
+
2. **Category Health Breakdown**: Visual progress bars and weighted contributions for each health dimension.
|
|
692
|
+
3. **Severity Distribution**: Proportional distribution bar across Critical, High, Medium, Low, and Info findings.
|
|
693
|
+
4. **Top Actionable Priorities**: Callout cards highlighting high-confidence vulnerabilities and issues requiring immediate attention.
|
|
694
|
+
5. **Regression & Baseline Banner**: Real-time diff metrics highlighting score regressions and newly introduced findings.
|
|
695
|
+
6. **Architecture Overview**: Graph metrics, detected layers, and circular dependency cycle warnings.
|
|
696
|
+
7. **Dependency Summary**: Direct vs transitive counts, duplicate versions, and lockfile status.
|
|
697
|
+
8. **Testing Maturity**: Test-to-source ratio, detected test directories, and test script presence.
|
|
698
|
+
9. **Git Hygiene**: Uncommitted working tree state, large binary files, and `.gitignore` status.
|
|
699
|
+
10. **Documentation Matrix**: Readiness checklist for README, LICENSE, CONTRIBUTING, and SECURITY policy.
|
|
700
|
+
11. **CI/CD Automation**: GitHub Actions workflow health and automation status.
|
|
701
|
+
12. **Interactive Finding Explorer**: Real-time text search, severity filter toggles, category dropdown, multi-attribute sorting (severity, rule ID, file, confidence), and collapsible syntax-highlighted code evidence viewers.
|
|
702
|
+
- **Deterministic & XSS-Safe**: HTML output is deterministic byte-for-byte with strict entity escaping.
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
## 🛡️ Security Model
|
|
707
|
+
|
|
708
|
+
Fathom treats target repositories as **untrusted input**:
|
|
709
|
+
- ❌ Never executes repository code or binaries
|
|
710
|
+
- ❌ Never installs dependencies or runs build commands
|
|
711
|
+
- ❌ Never transmits code or data over the network
|
|
712
|
+
- ❌ Never leaks or logs detected secret values (only filenames and line numbers)
|
|
713
|
+
- ✅ Only performs strictly bounded, read-only file inspections
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
## 🤝 Contributing
|
|
718
|
+
|
|
719
|
+
Contributions are welcome! Please check out [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on how to add rules, analyzers, or test fixtures.
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
## 📄 License
|
|
724
|
+
|
|
725
|
+
MIT © [Fathom Contributors](LICENSE)
|