projscan 3.0.8 → 3.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.
Files changed (67) hide show
  1. package/PRIVACY.md +14 -0
  2. package/README.md +71 -70
  3. package/TELEMETRY.md +100 -0
  4. package/dist/analyzers/securityCheck.d.ts +4 -1
  5. package/dist/analyzers/securityCheck.js +5 -1
  6. package/dist/analyzers/securityCheck.js.map +1 -1
  7. package/dist/cli/_shared.js +44 -0
  8. package/dist/cli/_shared.js.map +1 -1
  9. package/dist/cli/commands/feedback.js +3 -1
  10. package/dist/cli/commands/feedback.js.map +1 -1
  11. package/dist/cli/commands/init.js +33 -1
  12. package/dist/cli/commands/init.js.map +1 -1
  13. package/dist/cli/commands/privacyCheck.d.ts +1 -0
  14. package/dist/cli/commands/privacyCheck.js +66 -0
  15. package/dist/cli/commands/privacyCheck.js.map +1 -0
  16. package/dist/cli/commands/telemetry.d.ts +1 -0
  17. package/dist/cli/commands/telemetry.js +131 -0
  18. package/dist/cli/commands/telemetry.js.map +1 -0
  19. package/dist/cli/index.js +4 -0
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/core/adoption.d.ts +1 -1
  22. package/dist/core/adoption.js +7 -0
  23. package/dist/core/adoption.js.map +1 -1
  24. package/dist/core/auditRunner.js +4 -0
  25. package/dist/core/auditRunner.js.map +1 -1
  26. package/dist/core/embeddings.js +3 -0
  27. package/dist/core/embeddings.js.map +1 -1
  28. package/dist/core/issueEngine.d.ts +5 -1
  29. package/dist/core/issueEngine.js +16 -3
  30. package/dist/core/issueEngine.js.map +1 -1
  31. package/dist/core/preflight.js +28 -7
  32. package/dist/core/preflight.js.map +1 -1
  33. package/dist/core/privacy.d.ts +59 -0
  34. package/dist/core/privacy.js +129 -0
  35. package/dist/core/privacy.js.map +1 -0
  36. package/dist/core/repositoryScanner.d.ts +2 -0
  37. package/dist/core/repositoryScanner.js +88 -5
  38. package/dist/core/repositoryScanner.js.map +1 -1
  39. package/dist/core/sessionResources.js +7 -7
  40. package/dist/core/sessionResources.js.map +1 -1
  41. package/dist/core/start.js +42 -1
  42. package/dist/core/start.js.map +1 -1
  43. package/dist/core/telemetry.d.ts +114 -0
  44. package/dist/core/telemetry.js +451 -0
  45. package/dist/core/telemetry.js.map +1 -0
  46. package/dist/core/upgradePreview.js +10 -4
  47. package/dist/core/upgradePreview.js.map +1 -1
  48. package/dist/core/watcher.js +2 -4
  49. package/dist/core/watcher.js.map +1 -1
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.js +1 -0
  52. package/dist/index.js.map +1 -1
  53. package/dist/mcp/server.js +5 -2
  54. package/dist/mcp/server.js.map +1 -1
  55. package/dist/projscan-sbom.cdx.json +6 -6
  56. package/dist/tool-manifest.json +2 -2
  57. package/dist/types.d.ts +50 -0
  58. package/dist/utils/changedFiles.js +5 -4
  59. package/dist/utils/changedFiles.js.map +1 -1
  60. package/dist/utils/config.js +15 -0
  61. package/dist/utils/config.js.map +1 -1
  62. package/dist/utils/fileWalker.js +1 -1
  63. package/dist/utils/fileWalker.js.map +1 -1
  64. package/dist/utils/formatSupport.d.ts +6 -0
  65. package/dist/utils/formatSupport.js +6 -0
  66. package/dist/utils/formatSupport.js.map +1 -1
  67. package/package.json +4 -2
package/PRIVACY.md CHANGED
@@ -8,8 +8,12 @@ projscan is part of the Baseframe Labs family of products (https://www.baseframe
8
8
 
9
9
  By default, projscan runs on your machine and reads files in the repository where you run it. It does not upload source code, dependency data, scan results, telemetry, or usage analytics to a projscan service.
10
10
 
11
+ Inside a Git repository, projscan uses Git's own visible-file boundary by default: tracked files plus untracked files that are not excluded by `.gitignore`, `.git/info/exclude`, or global Git excludes. Files hidden by Git ignore rules are not scanned unless you explicitly opt in with `--include-ignored` or `scan.includeIgnored: true`. Non-Git folders fall back to projscan's built-in local noise ignores.
12
+
11
13
  projscan may write local files when you ask it to, such as `.projscan-cache/`, `.projscan-feedback.json`, baselines, handoff files, generated policies, generated GitHub Actions, or reports.
12
14
 
15
+ Run `projscan privacy-check` to see the current telemetry status, offline status, scan root, ignore boundary, ignored-file count, `.env` content-scanning status, plugin execution status, local write surfaces, report-export sensitivity, and network-capable endpoints.
16
+
13
17
  ## Commands that can involve network access
14
18
 
15
19
  Some workflows can involve network access because they call external tooling or package managers:
@@ -18,14 +22,24 @@ Some workflows can involve network access because they call external tooling or
18
22
  - `projscan audit` shells out to npm audit behavior for the current project
19
23
  - commands or modes that explicitly ask for registry checks may contact the configured package registry
20
24
  - semantic search can download an optional local embedding model when the optional `@xenova/transformers` peer is installed and the user opts into semantic mode
25
+
26
+ Set `PROJSCAN_OFFLINE=1`, pass `--offline`, or set `scan.offline: true` to block projscan's known network-capable features: telemetry sending, `projscan audit`, registry checks, and optional semantic model loading. This does not prevent npm or npx from contacting the registry before projscan starts.
21
27
  - local analyzer or reporter plugins can do anything their code does; only enable plugins you trust
22
28
 
23
29
  ## Environment variables and secrets
24
30
 
25
31
  projscan may pass `process.env` to child processes such as Git or npm so those tools work normally. projscan does not intentionally inspect `.env` values, API keys, session tokens, or private credentials for telemetry or product analytics.
26
32
 
33
+ `.env*` files are path-only by default. If a `.env` file is tracked by Git, projscan can flag that filename as risky, but it does not read the `.env` file contents for secret-pattern detection unless you explicitly opt in with `--scan-env-values` or `scan.scanEnvValues: true`.
34
+
27
35
  Security analyzers may flag committed secret-looking strings in repository files. Those findings stay in local output unless you choose to copy, save, or publish them.
28
36
 
37
+ ## Optional telemetry
38
+
39
+ Telemetry is off by default. Users can opt in with `projscan telemetry enable` or through the interactive `projscan init team` prompt. When enabled, projscan sends only anonymous product-health events: command category, success/failure, duration bucket, version/platform, setup booleans, repeat-use buckets, and optional feedback buckets. It does not send source code, file paths, repository names, branch names, package names, usernames, email addresses, raw findings, secrets, environment values, or scan reports.
40
+
41
+ See `TELEMETRY.md` for the full allowlist, controls, endpoint, and environment variables.
42
+
29
43
  ## Feedback artifacts
30
44
 
31
45
  `projscan feedback` creates local JSON evidence about reviewer usefulness, minutes saved, prevented bad edits, false positives, owner clarity, next-command clarity, and repeat PR use. Treat that artifact as team data. Do not commit it if it contains private PR URLs, reviewer handles, or internal notes you do not want public.
package/README.md CHANGED
@@ -9,9 +9,9 @@
9
9
 
10
10
  **Agent-first code intelligence.** An MCP server that lets AI coding agents (Claude Code, Codex, Cursor, Gemini, Windsurf, Cline, Continue, Zed — any MCP-aware client) query your codebase — with a CLI for humans and a local plugin layer for team-specific policy and reporting.
11
11
 
12
- [AI Agent Quick Start](#ai-agent-integration-mcp) · [CLI Quick Start](#quick-start) · [Commands](#commands) · [Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/GUIDE.md) · [Roadmap](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/ROADMAP.md)
12
+ [AI Agent Quick Start](#ai-agent-integration-mcp) · [CLI Quick Start](#quick-start) · [Commands](#commands) · [Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/GUIDE.md) · [Roadmap](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/ROADMAP.md)
13
13
 
14
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/projscan-reporter-plugin.png" alt="projscan reporter plugin running in a macOS-style terminal window with a team health summary" width="700">
14
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/projscan-reporter-plugin.png" alt="projscan reporter plugin running in a macOS-style terminal window with a team health summary" width="700">
15
15
 
16
16
  </div>
17
17
 
@@ -27,13 +27,13 @@ For teams, projscan turns that context into a repeatable PR habit. `projscan ini
27
27
 
28
28
  The local plugin platform lets teams add project-specific findings and render `doctor`, `analyze`, and `ci` in their own voice without changing the scan pipeline. Humans get the same information through the CLI.
29
29
 
30
- **Everything is offline-first. Zero network calls. No API keys.**
30
+ **Everything is local-first. No source upload. No API keys. `.gitignore` is respected by default. `.env` values are path-only unless explicitly enabled. Anonymous product telemetry is off by default and only runs after explicit opt-in.**
31
31
 
32
32
  ```bash
33
33
  npx projscan
34
34
  ```
35
35
 
36
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/projscan-reporter-plugin.gif" alt="projscan doctor rendered through a local reporter plugin in a macOS-style terminal window" width="700">
36
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/projscan-reporter-plugin.gif" alt="projscan doctor rendered through a local reporter plugin in a macOS-style terminal window" width="700">
37
37
 
38
38
  Run `projscan doctor` for a focused health check:
39
39
 
@@ -41,7 +41,7 @@ Run `projscan doctor` for a focused health check:
41
41
  npx projscan doctor
42
42
  ```
43
43
 
44
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/npx%20projscan%20doctor.gif" alt="npx projscan doctor" width="700">
44
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/npx%20projscan%20doctor.gif" alt="npx projscan doctor" width="700">
45
45
 
46
46
  ## Install
47
47
 
@@ -57,59 +57,45 @@ npx projscan
57
57
 
58
58
  ## Quick Start
59
59
 
60
- Run inside any repository:
60
+ Run this path first inside a repository:
61
61
 
62
62
  ```bash
63
- projscan # Full project analysis
64
- projscan start # First-60-seconds workflow orientation
65
- projscan first-run # First-run setup diagnostics for CLI + MCP
66
- projscan init mcp --client all # Ready-to-paste MCP client configs
67
- projscan mcp doctor --client codex # Verify MCP setup and paste config
68
- projscan init policy --team security # Team policy starter .projscanrc.json
69
- projscan init team --team security # Policy + PR workflow + CODEOWNERS + baseline + first-PR checklist
70
- projscan init github-action # PR workflow with validated evidence comments + block enforcement
71
- projscan recipes # Agent workflow recipes, including team bootstrap + PR automation
72
- projscan workplan --mode bug_hunt # Prioritized agent execution plan
73
- projscan bug-hunt --format json # Bug-hunt fix queue with verification commands
74
- projscan agent-brief --intent bug_hunt # Compact next-agent context packet
75
- projscan quality-scorecard --format json # Dimensioned quality view
76
- projscan release-train --format json # Product readiness plan
77
- projscan evidence-pack --website-prompt # Approval packet with product evidence
78
- projscan evidence-pack --pr-comment # PR comment with trust calibration + First Fix
79
- projscan feedback init --output .projscan-feedback.json # Create reviewer feedback evidence
80
- projscan dogfood --repo ../api --repo ../web --format json # Multi-repo adoption proof loop
81
- projscan trial --repo ../api --repo ../web --feedback .projscan-feedback.json --format json # Adoption-readiness report
82
- projscan regression-plan --level full # Risk-based verification matrix
83
- projscan handoff # Concise next-agent handoff
84
- projscan handoff --write docs/agent-handoff.md # Persist next-agent handoff artifact
85
- projscan preflight --format json # Agent safety gate with supply-chain evidence
86
- projscan doctor # Health check, including security and supply-chain risks
87
- projscan hotspots # Rank files by risk (churn × complexity × issues × ownership)
88
- projscan semantic-graph --format json # Stable v3 file/function/package/symbol graph
89
- projscan dataflow --format json # Focused direct, propagated, and bridge dataflow risks
90
- projscan search <query> # BM25-ranked search (content + symbols + path)
91
- projscan file <path> # Drill into a file - purpose, risk, ownership, issues
92
- projscan fix # Auto-fix detected issues
93
- projscan ci # CI health gate (exits 1 on low score)
94
- projscan ci --changed-only # Gate only on this PR's diff
95
- projscan ci --format sarif # SARIF 2.1.0 for GitHub Code Scanning
96
- projscan outdated # Declared-vs-installed drift (offline)
97
- projscan audit # npm audit, normalized + SARIF-ready
98
- projscan upgrade <pkg> # Preview upgrade impact (local CHANGELOG + importers)
99
- projscan coverage # Coverage × hotspots - scariest untested files
100
- projscan diff # Compare health + hotspot trends against a baseline
101
- projscan diagram # Architecture visualization
102
- projscan structure # Directory tree
103
- projscan mcp # Run as an MCP server for AI coding agents
104
- projscan plugin list # Discover local analyzer/reporter plugins
105
- projscan plugin init --kind analyzer --name policy
106
- projscan plugin test .projscan-plugins/policy.projscan-plugin.json
107
- PROJSCAN_PLUGINS_PREVIEW=1 projscan doctor --reporter team-radar
63
+ projscan privacy-check # Show exactly what can be read, written, or contacted
64
+ projscan start # First-60-seconds workflow orientation
65
+ projscan preflight --format json # Proceed/caution/block safety gate
66
+ projscan evidence-pack --pr-comment # Reviewer-ready PR evidence
67
+ ```
68
+
69
+ For MCP clients:
70
+
71
+ ```bash
72
+ projscan first-run
73
+ projscan init mcp --client all
74
+ projscan mcp doctor --client codex
75
+ projscan mcp
76
+ ```
77
+
78
+ For team rollout after the first local run is trusted:
79
+
80
+ ```bash
81
+ projscan init team --team security
82
+ projscan telemetry explain
83
+ projscan feedback init --output .projscan-feedback.json
84
+ projscan dogfood --repo ../api --repo ../web --repo ../worker --feedback .projscan-feedback.json --format json
85
+ projscan trial --repo ../api --repo ../web --repo ../worker --feedback .projscan-feedback.json --format json
108
86
  ```
109
87
 
110
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/npx%20projscan%20--help.gif" alt="npx projscan --help" width="700">
88
+ For maintainers changing trust-sensitive behavior:
111
89
 
112
- For a comprehensive walkthrough, see the **[Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/GUIDE.md)**.
90
+ ```bash
91
+ npm run test:trust-smoke
92
+ ```
93
+
94
+ The full command catalog is below. Most users should start with the four-command path above instead of scanning the catalog.
95
+
96
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/npx%20projscan%20--help.gif" alt="npx projscan --help" width="700">
97
+
98
+ For a comprehensive walkthrough, see the **[Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/GUIDE.md)**.
113
99
 
114
100
  ## Commands
115
101
 
@@ -132,6 +118,8 @@ For a comprehensive walkthrough, see the **[Full Guide](https://github.com/abhiy
132
118
  | `projscan evidence-pack` | Assemble approval evidence from planning, bug-hunt, workplan, preflight, trust calibration, First Fix, owner routing, and baseline trend memory |
133
119
  | `projscan trial` | Produce one adoption-readiness report from onboarding, dogfood, feedback, trust signals, and website proof |
134
120
  | `projscan feedback` | Capture measured reviewer feedback: minutes saved, prevented bad edits, false positives, and repeat PR use |
121
+ | `projscan privacy-check` | Verify the local trust boundary: telemetry, offline mode, scan root, .gitignore handling, ignored-file count, .env content scanning, and network-capable endpoints |
122
+ | `projscan telemetry` | Explicit default-off telemetry controls: status, enable, disable, and explain |
135
123
  | `projscan dogfood` | Evaluate 1+ real repos for PR-comment readiness, repeat-use readiness, MCP readiness, and reviewer feedback prompts |
136
124
  | `projscan regression-plan` | Build a smoke, focused, or full regression matrix from product risk signals |
137
125
  | `projscan handoff` | Concise next-agent handoff from the current workplan |
@@ -173,31 +161,31 @@ projscan --help
173
161
  <details>
174
162
  <summary><strong>projscan structure</strong> - Directory tree with file counts</summary>
175
163
 
176
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/npx%20projscan%20structure.gif" alt="npx projscan structure" width="700">
164
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/npx%20projscan%20structure.gif" alt="npx projscan structure" width="700">
177
165
  </details>
178
166
 
179
167
  <details>
180
168
  <summary><strong>projscan diagram</strong> - Architecture visualization</summary>
181
169
 
182
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/npx%20projscan%20diagram.gif" alt="npx projscan diagram" width="700">
170
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/npx%20projscan%20diagram.gif" alt="npx projscan diagram" width="700">
183
171
  </details>
184
172
 
185
173
  <details>
186
174
  <summary><strong>projscan dependencies</strong> - Dependency analysis</summary>
187
175
 
188
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/npx%20projscan%20dependencies.gif" alt="npx projscan dependencies" width="700">
176
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/npx%20projscan%20dependencies.gif" alt="npx projscan dependencies" width="700">
189
177
  </details>
190
178
 
191
179
  <details>
192
180
  <summary><strong>projscan explain</strong> - File explanation</summary>
193
181
 
194
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/npx%20projscan%20explain.gif" alt="npx projscan explain" width="700">
182
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/npx%20projscan%20explain.gif" alt="npx projscan explain" width="700">
195
183
  </details>
196
184
 
197
185
  <details>
198
186
  <summary><strong>projscan badge</strong> - Health badge generation</summary>
199
187
 
200
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/npx%20projscan%20badge.gif" alt="npx projscan badge" width="700">
188
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/npx%20projscan%20badge.gif" alt="npx projscan badge" width="700">
201
189
  </details>
202
190
 
203
191
  ### Output Formats
@@ -219,7 +207,7 @@ Run `projscan help` for the generated command-by-command support matrix.
219
207
 
220
208
  projscan can load local plugins from `.projscan-plugins/` when `PROJSCAN_PLUGINS_PREVIEW=1` is set. The environment flag is kept for explicit local-code opt-in. Analyzer plugins emit normal projscan issues; reporter plugins render supported CLI commands with team-specific output.
221
209
 
222
- **2.0 upgrade notes:** migrating from 1.x or authoring plugins? Start with the [2.0 Migration Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/2.0-MIGRATION.md), then use [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/PLUGIN-AUTHORING.md), the [Plugin Gallery](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/PLUGIN-GALLERY.md), and the [manifest schema](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/plugin.schema.json) as the stable contract.
210
+ **2.0 upgrade notes:** migrating from 1.x or authoring plugins? Start with the [2.0 Migration Guide](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/2.0-MIGRATION.md), then use [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/PLUGIN-AUTHORING.md), the [Plugin Gallery](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/PLUGIN-GALLERY.md), and the [manifest schema](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/plugin.schema.json) as the stable contract.
223
211
 
224
212
  ```bash
225
213
  projscan plugin list
@@ -228,9 +216,9 @@ PROJSCAN_PLUGINS_PREVIEW=1 projscan doctor --reporter team-radar
228
216
  PROJSCAN_PLUGINS_PREVIEW=1 projscan ci --reporter team-radar --min-score 80
229
217
  ```
230
218
 
231
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/projscan-reporter-plugin.gif" alt="projscan local reporter plugin rendering a team health report" width="700">
219
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/projscan-reporter-plugin.gif" alt="projscan local reporter plugin rendering a team health report" width="700">
232
220
 
233
- Reporter plugins are intentionally CLI-only. MCP tools keep returning structured JSON-compatible payloads so agents can reason over stable data, while humans can get a polished local report for their team. Custom presentation, team-branded summaries, and white-label reports belong in reporter plugins rather than new core HTML theming flags. See [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/PLUGIN-AUTHORING.md) for manifest shape, `render(context)`, validation, and the trust model.
221
+ Reporter plugins are intentionally CLI-only. MCP tools keep returning structured JSON-compatible payloads so agents can reason over stable data, while humans can get a polished local report for their team. Custom presentation, team-branded summaries, and white-label reports belong in reporter plugins rather than new core HTML theming flags. See [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/PLUGIN-AUTHORING.md) for manifest shape, `render(context)`, validation, and the trust model.
234
222
 
235
223
  ### Options
236
224
 
@@ -238,6 +226,9 @@ Reporter plugins are intentionally CLI-only. MCP tools keep returning structured
238
226
  |------|-------------|
239
227
  | `--format <type>` | Output format: console, json, markdown, sarif, html (command-dependent) |
240
228
  | `--config <path>` | Path to a `.projscanrc` config file |
229
+ | `--include-ignored` | Explicitly include files hidden by Git ignore rules |
230
+ | `--scan-env-values` | Explicitly read `.env*` contents during secret checks |
231
+ | `--offline` | Block projscan network-capable features for this run |
241
232
  | `--changed-only` | Scope to files changed vs base ref (ci/analyze/doctor) |
242
233
  | `--base-ref <ref>` | Git base ref for `--changed-only` (default: origin/main) |
243
234
  | `--reporter <name>` | Render `doctor`, `analyze`, or `ci` with a local reporter plugin |
@@ -361,10 +352,10 @@ projscan reads your source code so it can be useful; it does not send your sourc
361
352
 
362
353
  ### What projscan does NOT do
363
354
 
364
- - **Send your source code off-machine.** Zero network calls in any code path projscan owns. File contents stay local; AST analysis runs in-process.
355
+ - **Send your source code off-machine.** File contents stay local; AST analysis runs in-process. The only projscan-owned network path is explicit opt-in telemetry, and those events are anonymous product-health buckets, not code or scan results.
365
356
  - **Read environment variables for secrets.** `process.env` is forwarded to child processes (`git`, `npm`) so they can find their `PATH` — we never inspect `.env` values, API keys, or session tokens.
366
357
  - **Execute command-line arguments as code.** Core CLI and MCP arguments are parsed as data, and projscan does not compose shell strings from user input. Local plugins are the explicit trust boundary: when `PROJSCAN_PLUGINS_PREVIEW=1` is set, projscan imports local modules declared in `.projscan-plugins/*.projscan-plugin.json` and runs their `check` / `render` exports.
367
- - **Phone home with telemetry.** The opt-in JSONL telemetry shipped in 0.11 was removed entirely in 0.12. Future telemetry, if any, will be remote-sink-with-dashboard and explicitly opt-in.
358
+ - **Phone home silently.** Telemetry is off by default. If you explicitly opt in with `projscan telemetry enable` or the interactive `projscan init team` prompt, projscan sends only anonymous product-health events; it never sends source code, file paths, repo names, branch names, package names, usernames, raw findings, or secrets. See [TELEMETRY.md](TELEMETRY.md).
368
359
  - **Modify your repo without an explicit command.** `projscan fix` is the only command that writes to source files, and only when invoked. The cache directory `.projscan-cache/` is local-only and gitignored.
369
360
 
370
361
  ### What projscan DOES do, and what it costs
@@ -375,6 +366,7 @@ projscan reads your source code so it can be useful; it does not send your sourc
375
366
  | Spawn `git` | `hotspots`, `pr-diff`, `review`, `diff` | git itself may fetch if you run `git fetch` separately; **projscan never invokes `git fetch`** | `env: process.env` is passed so `git` can find its config |
376
367
  | Spawn `npm audit` | `audit` only | yes — by `npm`, not by projscan | runs against your local lockfile |
377
368
  | Scan supply-chain IOCs | `doctor`, `preflight`, release validation | no | checks manifests, lockfiles, hidden editor hooks, and suspicious install-time payloads against bundled indicators |
369
+ | Anonymous telemetry | only after `projscan telemetry enable` or accepting the `projscan init team` prompt | yes — projscan-owned, default off | sends product-health buckets only; see [TELEMETRY.md](TELEMETRY.md) |
378
370
  | Load local plugins | only with `PROJSCAN_PLUGINS_PREVIEW=1` | no | imports local JS modules declared in `.projscan-plugins/`; only enable plugins you trust |
379
371
  | Load wasm grammars | first parse of a non-JS file | no | served from `dist/grammars/` inside the package; no fetch |
380
372
  | Build embeddings | semantic search opt-in only | yes — by `@xenova/transformers`, on first use | model cached locally after first download; remove the peer dep to remove this code path entirely |
@@ -391,7 +383,7 @@ If you read projscan's [Socket report](https://socket.dev/npm/package/projscan),
391
383
  ### Audit it yourself
392
384
 
393
385
  - **Source is open** at [github.com/abhiyoheswaran1/projscan](https://github.com/abhiyoheswaran1/projscan). The npm tarball matches the `dist/` produced by `npm run build` at the matching tag.
394
- - **Public API surface is locked** by `scripts/check-stability.mjs`, which runs in CI on every PR and fails on any rename or removal of an MCP tool, CLI command, or exit code. See [`docs/STABILITY.md`](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/STABILITY.md).
386
+ - **Public API surface is locked** by `scripts/check-stability.mjs`, which runs in CI on every PR and fails on any rename or removal of an MCP tool, CLI command, or exit code. See [`docs/STABILITY.md`](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/STABILITY.md).
395
387
  - **Run it offline:** `npm install -g projscan` followed by anything except `audit` and `--mode semantic` works without network.
396
388
  - **Drop privilege further:** in CI, run projscan in a sandbox that disallows network egress; everything except `audit` will pass.
397
389
 
@@ -442,7 +434,7 @@ projscan ci --changed-only # Gate only on this PR's diff
442
434
  projscan ci --format sarif > projscan.sarif # SARIF for Code Scanning
443
435
  ```
444
436
 
445
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/npx%20projscan%20ci%20--min-score%2070.gif" alt="npx projscan ci --min-score 70" width="700">
437
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/npx%20projscan%20ci%20--min-score%2070.gif" alt="npx projscan ci --min-score 70" width="700">
446
438
 
447
439
  ### GitHub Action (recommended)
448
440
 
@@ -490,6 +482,11 @@ Drop a `.projscanrc.json` at your repo root to set defaults - CLI flags always w
490
482
  "minScore": 80,
491
483
  "baseRef": "origin/main",
492
484
  "ignore": ["**/fixtures/**", "**/generated/**"],
485
+ "scan": {
486
+ "includeIgnored": false,
487
+ "scanEnvValues": false,
488
+ "offline": false
489
+ },
493
490
  "disableRules": ["missing-editorconfig", "large-*"],
494
491
  "severityOverrides": {
495
492
  "missing-prettier": "info"
@@ -506,12 +503,15 @@ Fields:
506
503
  - `minScore` - default `ci` threshold (0–100)
507
504
  - `baseRef` - default base ref for `--changed-only`
508
505
  - `ignore` - extra glob patterns added to the built-in ignore list
506
+ - `scan.includeIgnored` - opt into scanning files hidden by Git ignore rules
507
+ - `scan.scanEnvValues` - opt into reading `.env*` contents during secret checks
508
+ - `scan.offline` - block projscan network-capable features by default
509
509
  - `disableRules` - silence rules by id; supports wildcard `prefix-*`
510
510
  - `severityOverrides` - remap a rule's severity (`info` / `warning` / `error`)
511
511
  - `hotspots.limit` / `hotspots.since` - defaults for the `hotspots` command
512
512
  - `monorepo.importPolicy` - cross-package import allow/deny rules in monorepos *(0.14+)*
513
513
 
514
- See [`docs/GUIDE.md` → Configuration](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/GUIDE.md#configuration-projscanrc) for the full reference (field types, validation behavior, embedding config in `package.json`, monorepo `importPolicy` semantics).
514
+ See [`docs/GUIDE.md` → Configuration](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/GUIDE.md#configuration-projscanrc) for the full reference (field types, validation behavior, embedding config in `package.json`, monorepo `importPolicy` semantics).
515
515
 
516
516
  ## Tracking Health Over Time
517
517
 
@@ -524,7 +524,7 @@ projscan diff # Compare against baseline
524
524
  projscan diff --format markdown # Markdown diff for PRs
525
525
  ```
526
526
 
527
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/npx%20projscan%20diff%20--save-baseline.gif" alt="npx projscan diff --save-baseline" width="700">
527
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/npx%20projscan%20diff%20--save-baseline.gif" alt="npx projscan diff --save-baseline" width="700">
528
528
 
529
529
  ## Hotspots - Where to Fix First
530
530
 
@@ -613,7 +613,7 @@ Coverage is also automatically joined into `projscan hotspots` when one of those
613
613
 
614
614
  **This is the primary way to use projscan.** `projscan mcp` starts an [MCP](https://modelcontextprotocol.io) server over stdio so AI coding agents can query your codebase with real structural accuracy - not regex, not grep.
615
615
 
616
- <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.0.8/docs/projscan-agent-demo.gif" alt="projscan answering two agent questions: what breaks if I rename buildCodeGraph (impact analysis with definitions, direct callers, transitive reach), and where should I fix first (ranked hotspots with cyclomatic complexity)" width="700">
616
+ <img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v3.1.0/docs/projscan-agent-demo.gif" alt="projscan answering two agent questions: what breaks if I rename buildCodeGraph (impact analysis with definitions, direct callers, transitive reach), and where should I fix first (ranked hotspots with cyclomatic complexity)" width="700">
617
617
 
618
618
  Two questions an agent asks; structural answers in milliseconds. *"What breaks if I rename `buildCodeGraph`?"* → 31 direct callers, 97 files reachable. *"Where should I fix first?"* → ranked hotspots with AST cyclomatic complexity, churn, and ownership signals.
619
619
 
@@ -810,7 +810,7 @@ Capability is advertised under `experimental.fileChanged` on `initialize` so cli
810
810
  - **`projscan_apply_fix`** *(1.6)* - mechanically execute the safe fix templates. Default is dry-run; pass `confirm: true` to write. Atomic writes, per-apply rollback record at `.projscan-cache/rollbacks/<id>.json`. Reverse with `action: "rollback", rollback_id: ...`. Six templates supported at this release: `unused-dependency-*`, `missing-test-framework`, `missing-eslint`, `missing-prettier`, `missing-editorconfig`, `missing-readme`.
811
811
  - **`projscan_taint`** *(1.6)* - source-to-sink reachability over the per-function call graph. Built-in defaults cover common JS / Python sources (`process.env`, `req.body`, etc.) and sinks (`exec`, `eval`, `db.query`, etc.). Project-specific names go in `.projscanrc.json` `taint`. `projscan_review` automatically diffs taint flows between base and head and **blocks any PR that introduces a new flow**. In 3.0.2, review surfaces hardened `newDataflowRisks`, compact `graphEvidence`, and graph-readiness gates for safer handoff.
812
812
 
813
- Analyzer plugins can optionally read graph/dataflow context through `check(rootPath, files, context)` while staying on manifest schema v1. The packaged `graph-context` example shows `context.getSemanticGraph()` and `context.getDataflow()` in a real analyzer. For analyzer and reporter plugin authoring, manifest validation, `--reporter <name>`, and the trust model, see [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.0.8/docs/PLUGIN-AUTHORING.md).
813
+ Analyzer plugins can optionally read graph/dataflow context through `check(rootPath, files, context)` while staying on manifest schema v1. The packaged `graph-context` example shows `context.getSemanticGraph()` and `context.getDataflow()` in a real analyzer. For analyzer and reporter plugin authoring, manifest validation, `--reporter <name>`, and the trust model, see [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v3.1.0/docs/PLUGIN-AUTHORING.md).
814
814
 
815
815
  ### Context-window budgeting
816
816
 
@@ -887,10 +887,11 @@ Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) before
887
887
  - Disclaimer: [DISCLAIMER.md](DISCLAIMER.md)
888
888
  - Security policy: [SECURITY.md](SECURITY.md)
889
889
  - Privacy notice: [PRIVACY.md](PRIVACY.md)
890
+ - Telemetry policy: [TELEMETRY.md](TELEMETRY.md)
890
891
  - Trademark and brand policy: [TRADEMARKS.md](TRADEMARKS.md)
891
892
  - Third-party notices: [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md)
892
893
 
893
- projscan is free and open source. The CLI and MCP server are local-first and do not upload source code, scan results, telemetry, or usage analytics to a projscan service.
894
+ projscan is free and open source. The CLI and MCP server are local-first and do not upload source code or scan results to a projscan service. Anonymous product telemetry is default-off and only runs after explicit opt-in.
894
895
 
895
896
  <p align="center">
896
897
  <a href="https://www.baseframelabs.com" target="_blank" rel="noopener" title="Part of Baseframe Labs">
package/TELEMETRY.md ADDED
@@ -0,0 +1,100 @@
1
+ # projscan telemetry
2
+
3
+ projscan telemetry is **off by default**. The CLI and MCP server do not send usage data unless a user explicitly opts in with `projscan telemetry enable` or accepts the prompt shown by `projscan init team` in an interactive terminal.
4
+
5
+ ## Controls
6
+
7
+ ```bash
8
+ projscan telemetry status
9
+ projscan telemetry explain
10
+ projscan telemetry enable
11
+ projscan telemetry disable
12
+ ```
13
+
14
+ `projscan telemetry disable` turns telemetry off, clears the local queue, and removes the anonymous id.
15
+
16
+ ## What is collected when enabled
17
+
18
+ Only anonymous product-health events are collected:
19
+
20
+ - command category and command name, such as `doctor`, `review`, `preflight`, or `dogfood`
21
+ - success or failure
22
+ - duration bucket, not exact command timing
23
+ - projscan version
24
+ - Node major version and operating-system platform
25
+ - whether CI, MCP setup, GitHub PR automation, or team bootstrap appears configured
26
+ - repeat-use buckets, such as run-count and active-day ranges
27
+ - optional feedback buckets from `projscan feedback add`, such as minutes-saved range, useful yes/no, prevented-bad-edit yes/no, and whether a false positive was reported
28
+
29
+ ## What is never collected
30
+
31
+ projscan telemetry does **not** collect:
32
+
33
+ - source code
34
+ - file paths
35
+ - repository names
36
+ - branch names
37
+ - package names
38
+ - usernames or email addresses
39
+ - raw findings or scan output
40
+ - secrets or environment variable values
41
+
42
+ The implementation builds events from a fixed allowlist. It does not serialize scan reports, command arguments, file lists, dependency names, or analyzer findings.
43
+
44
+ ## Storage and sending
45
+
46
+ Opt-in state is stored in the user config directory, or in `PROJSCAN_TELEMETRY_HOME` when set. Events are queued locally as JSONL and sent best-effort to:
47
+
48
+ ```text
49
+ https://www.baseframelabs.com/api/projscan/telemetry
50
+ ```
51
+
52
+ The endpoint can be overridden with `PROJSCAN_TELEMETRY_ENDPOINT`. Set `PROJSCAN_TELEMETRY_DISABLED=1` to force telemetry off in CI or managed environments. Set `PROJSCAN_TELEMETRY_NO_NETWORK=1` to keep enabled telemetry queued locally without sending network requests. Set `PROJSCAN_OFFLINE=1` or pass `--offline` to skip telemetry recording and sending for the run as part of projscan's broader no-network guard.
53
+
54
+ ## Endpoint payload
55
+
56
+ The client posts JSON with this shape:
57
+
58
+ ```json
59
+ {
60
+ "schemaVersion": 1,
61
+ "events": [
62
+ {
63
+ "schemaVersion": 1,
64
+ "eventId": "evt_<random-uuid>",
65
+ "eventType": "command_run",
66
+ "anonymousId": "psn_<random-uuid>",
67
+ "occurredAt": "2026-06-01T00:00:00.000Z",
68
+ "commandCategory": "doctor",
69
+ "commandName": "doctor",
70
+ "status": "success",
71
+ "durationBucket": "1-5s",
72
+ "version": "3.0.9",
73
+ "nodeMajor": 22,
74
+ "platform": "darwin",
75
+ "ci": false,
76
+ "setup": {
77
+ "githubActionConfigured": false,
78
+ "mcpConfigured": false,
79
+ "teamInitConfigured": false
80
+ },
81
+ "repeatUse": {
82
+ "runCountBucket": "2-5",
83
+ "activeDaysBucket": "1"
84
+ }
85
+ }
86
+ ]
87
+ }
88
+ ```
89
+
90
+ Feedback events use `eventType: "feedback_outcome"` and add a `feedback` object containing only buckets or booleans.
91
+
92
+ ## Why this exists
93
+
94
+ Public download counts and stars do not show whether projscan actually helps engineers. Opt-in telemetry answers product-health questions such as whether teams finish setup, connect MCP, generate PR evidence, keep using projscan on later PRs, and report false positives. Outcome value still comes from explicit reviewer feedback:
95
+
96
+ ```bash
97
+ projscan feedback add --minutes-saved 12 --prevented-bad-edit true --false-positive-rule owner:vague
98
+ ```
99
+
100
+ Telemetry can show repeat use. Feedback explains whether that use was valuable.
@@ -1,2 +1,5 @@
1
1
  import type { FileEntry, Issue } from '../types.js';
2
- export declare function check(rootPath: string, files: FileEntry[]): Promise<Issue[]>;
2
+ export interface SecurityCheckOptions {
3
+ scanEnvValues?: boolean;
4
+ }
5
+ export declare function check(rootPath: string, files: FileEntry[], options?: SecurityCheckOptions): Promise<Issue[]>;
@@ -23,7 +23,10 @@ const SECRET_PATTERNS = [
23
23
  pattern: /(?:password|secret|api_key|apikey|token|auth)\s*[=:]\s*['"][^'"]{8,}['"]/i,
24
24
  },
25
25
  ];
26
- export async function check(rootPath, files) {
26
+ function isEnvLikeFile(relativePath) {
27
+ return path.basename(relativePath).startsWith('.env');
28
+ }
29
+ export async function check(rootPath, files, options = {}) {
27
30
  const issues = [];
28
31
  // Detection 1: Sensitive .env files
29
32
  for (const file of files) {
@@ -63,6 +66,7 @@ export async function check(rootPath, files) {
63
66
  }
64
67
  // Detection 3: Hardcoded secrets in file contents
65
68
  const filesToScan = files.filter((f) => f.sizeBytes <= MAX_FILE_SIZE &&
69
+ (options.scanEnvValues === true || !isEnvLikeFile(f.relativePath)) &&
66
70
  (SCANNABLE_EXTENSIONS.has(f.extension) ||
67
71
  path.basename(f.relativePath).startsWith('.env')));
68
72
  // 1.9+ — was Promise.all unbounded; on a 50K-file repo that opens
@@ -1 +1 @@
1
- {"version":3,"file":"securityCheck.js","sourceRoot":"","sources":["../../src/analyzers/securityCheck.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"securityCheck.js","sourceRoot":"","sources":["../../src/analyzers/securityCheck.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,8 @@ import { explainFile as explainProjectFile } from '../core/fileInspector.js';
8
8
  import { setLogLevel } from '../utils/logger.js';
9
9
  import { showBanner, showCompactBanner } from '../utils/banner.js';
10
10
  import { loadConfig } from '../utils/config.js';
11
+ import { recordCommandTelemetry } from '../core/telemetry.js';
12
+ import { enableOfflineMode } from '../core/privacy.js';
11
13
  import { getChangedFiles } from '../utils/changedFiles.js';
12
14
  import { OUTPUT_FORMATS, formatList, getCommandFormatSupport } from '../utils/formatSupport.js';
13
15
  import { resolveReporterPlugin, renderReporterPlugin, } from '../core/plugins.js';
@@ -20,8 +22,44 @@ program
20
22
  .version(pkg.version)
21
23
  .option('--format <type>', `output format: ${formatList()} (command-dependent)`, 'console')
22
24
  .option('--config <path>', 'path to .projscanrc config file')
25
+ .option('--include-ignored', 'explicitly include files ignored by .gitignore')
26
+ .option('--scan-env-values', 'explicitly read .env* file contents during secret checks')
27
+ .option('--offline', 'block all projscan network-capable features for this run')
23
28
  .option('--verbose', 'enable verbose output')
24
29
  .option('--quiet', 'suppress non-essential output');
30
+ let activeTelemetryRun = null;
31
+ program.hook('preAction', (_thisCommand, actionCommand) => {
32
+ const opts = program.opts();
33
+ if (opts.offline)
34
+ enableOfflineMode();
35
+ if (opts.includeIgnored)
36
+ process.env.PROJSCAN_INCLUDE_IGNORED = '1';
37
+ if (opts.scanEnvValues)
38
+ process.env.PROJSCAN_SCAN_ENV_VALUES = '1';
39
+ activeTelemetryRun = { commandName: commandPath(actionCommand), startedAt: Date.now() };
40
+ });
41
+ program.hook('postAction', async (_thisCommand, actionCommand) => {
42
+ const run = activeTelemetryRun ?? { commandName: commandPath(actionCommand), startedAt: Date.now() };
43
+ activeTelemetryRun = null;
44
+ await recordCommandTelemetry({
45
+ commandName: run.commandName,
46
+ status: 'success',
47
+ durationMs: Date.now() - run.startedAt,
48
+ rootPath: getRootPath(),
49
+ version: pkg.version,
50
+ }).catch(() => undefined);
51
+ });
52
+ function commandPath(actionCommand) {
53
+ const parts = [];
54
+ let current = actionCommand;
55
+ while (current && current.name() !== 'projscan') {
56
+ const name = current.name();
57
+ if (name)
58
+ parts.unshift(name);
59
+ current = current.parent ?? null;
60
+ }
61
+ return parts.join(' ') || actionCommand.name() || 'unknown';
62
+ }
25
63
  export function getFormat() {
26
64
  const opts = program.opts();
27
65
  const f = opts.format;
@@ -52,6 +90,12 @@ export async function loadProjectConfig() {
52
90
  const explicit = typeof opts.config === 'string' ? opts.config : undefined;
53
91
  try {
54
92
  const { config, source } = await loadConfig(getRootPath(), explicit);
93
+ if (config.scan?.offline)
94
+ enableOfflineMode();
95
+ if (config.scan?.includeIgnored)
96
+ process.env.PROJSCAN_INCLUDE_IGNORED = '1';
97
+ if (config.scan?.scanEnvValues)
98
+ process.env.PROJSCAN_SCAN_ENV_VALUES = '1';
55
99
  if (source && !opts.quiet && getFormat() === 'console') {
56
100
  console.error(chalk.dim(` [config: ${path.relative(getRootPath(), source) || source}]`));
57
101
  }