codeproof 1.1.0 → 1.1.2

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/Readme.md ADDED
@@ -0,0 +1,130 @@
1
+ CodeProof CLI
2
+ =============
3
+
4
+ CodeProof is a security-focused CLI that scans your codebase, blocks risky commits, and reports findings to a server-backed dashboard.
5
+
6
+ Features
7
+ --------
8
+ - Run security scans on staged or full files.
9
+ - Enforce commit safety with configurable rules.
10
+ - Generate local reports and optionally sync them to the server.
11
+ - Usage tracking with monthly limits (free tier default 20 runs).
12
+
13
+ Installation
14
+ ------------
15
+ Use npx (recommended):
16
+
17
+ ```bash
18
+ npx codeproof init
19
+ ```
20
+
21
+ Or install globally:
22
+
23
+ ```bash
24
+ npm install -g codeproof
25
+ codeproof init
26
+ ```
27
+
28
+ Quick Start
29
+ -----------
30
+ 1. Initialize in a Git repo:
31
+
32
+ ```bash
33
+ codeproof init
34
+ ```
35
+
36
+ 2. Run a scan:
37
+
38
+ ```bash
39
+ codeproof run
40
+ ```
41
+
42
+ 3. View reports in the dashboard (requires server):
43
+
44
+ ```bash
45
+ codeproof report@dashboard
46
+ ```
47
+
48
+ Commands
49
+ --------
50
+ - init: Initialize CodeProof in the current Git repo.
51
+ - run: Run a security scan based on your config.
52
+ - report@dashboard: Send latest report and show dashboard link.
53
+ - move-secret: Move high-risk secrets to .env safely.
54
+ - ignore: Temporarily disable commit enforcement.
55
+ - apply: Re-enable commit enforcement.
56
+ - whoami: Show the local clientId.
57
+ - help: Show CLI help.
58
+
59
+ Configuration
60
+ -------------
61
+ CodeProof uses codeproof.config.json at the repo root.
62
+
63
+ Example:
64
+
65
+ ```json
66
+ {
67
+ "projectId": "<uuid>",
68
+ "projectType": "Node",
69
+ "scanMode": "staged",
70
+ "enforcement": "enabled",
71
+ "features": {
72
+ "reporting": true,
73
+ "integration": true,
74
+ "aiEscalation": false,
75
+ "secretRemediation": false
76
+ },
77
+ "integration": {
78
+ "enabled": true,
79
+ "endpointUrl": "http://127.0.0.1:4000/api/reports"
80
+ }
81
+ }
82
+ ```
83
+
84
+ Usage Limits (Server-Enforced)
85
+ ------------------------------
86
+ CodeProof enforces monthly run limits on the server.
87
+
88
+ - Default plan: free
89
+ - Default monthly limit: 20
90
+ - The CLI checks usage before each run
91
+ - If the server is unreachable, the CLI fails closed and stops the run
92
+
93
+ API Base Override
94
+ -----------------
95
+ By default the CLI uses http://127.0.0.1:4000/api for usage checks.
96
+ Override with:
97
+
98
+ ```bash
99
+ set CODEPROOF_API_BASE=http://your-server:4000/api
100
+ ```
101
+
102
+ move-secret Command
103
+ -------------------
104
+ Safely moves high-risk secrets to .env with backups:
105
+
106
+ ```bash
107
+ codeproof move-secret --yes
108
+ ```
109
+
110
+ Server Setup (Required for Dashboard)
111
+ -------------------------------------
112
+ This CLI expects the CodeProof server to be running for:
113
+
114
+ - Usage enforcement
115
+ - Report ingestion
116
+ - Dashboard views
117
+
118
+ If you only want local scanning, disable integration in your config.
119
+
120
+ Dashboard
121
+ ---------
122
+ The Next.js dashboard displays:
123
+
124
+ - Project and report metrics
125
+ - Analytics charts
126
+ - Usage and limit graphs
127
+
128
+ License
129
+ -------
130
+ Proprietary. All rights reserved.
package/commands/help.js CHANGED
@@ -7,21 +7,17 @@ import { formatBlock } from "../ui/formatting.js";
7
7
  const HELP_TEXT = `Usage: codeproof <command>
8
8
 
9
9
  Commands:
10
- init Initialize CodeProof in a Git repository
11
- run Run CodeProof checks
12
- report@dashboard Send latest report and show dashboard link
13
- move-secret Move high-risk secrets to .env
14
- ignore Temporarily disable commit enforcement
15
- apply Re-enable commit enforcement
16
- whoami Show the local CodeProof client ID
17
- help Show this help menu
18
- -h, --help Show this help menu
10
+ codeproof init Initialize CodeProof in a Git repository
11
+ codeproof run Run CodeProof checks
12
+ codeproof report@dashboard Send latest report and show dashboard link
13
+ codeproof move-secret Move high-risk secrets to .env
14
+ codeproof ignore Temporarily disable commit enforcement
15
+ codeproof apply Re-enable commit enforcement
16
+ codeproof whoami Show the local CodeProof client ID
17
+ codeproof help Show this help menu
18
+ codeproof -h, --help Show this help menu
19
+
19
20
 
20
- Examples:
21
- codeproof init
22
- codeproof run
23
- codeproof move-secret --yes
24
- codeproof help
25
21
  `;
26
22
 
27
23
  /**
package/commands/run.js CHANGED
@@ -13,6 +13,7 @@ import { sendReportToServer } from "../utils/apiClient.js";
13
13
  import { resolveFeatureFlags, isVerbose } from "../core/featureFlags.js";
14
14
  import { getClientId } from "../core/identity.js";
15
15
  import { getEnforcementState } from "../core/enforcement.js";
16
+ import { checkUsageOrThrow } from "../core/usageCheck.js";
16
17
  import {
17
18
  reportFeatureDisabled,
18
19
  warnExperimentalOnce,
@@ -67,6 +68,22 @@ export async function runCli({ args = [], cwd }) {
67
68
  process.exit(1);
68
69
  }
69
70
 
71
+ const clientId = getClientId();
72
+ try {
73
+ const usage = await checkUsageOrThrow({ clientId, config });
74
+ if (!usage.allowed) {
75
+ const limit = usage.limit ?? 20;
76
+ const used = usage.used ?? limit;
77
+ logError(`Free limit reached (${used}/${limit} runs/month).`);
78
+ logError("Upgrade to premium to continue.");
79
+ process.exit(1);
80
+ }
81
+ } catch (error) {
82
+ logError("Usage check failed. Unable to reach CodeProof server.");
83
+ logError(error?.message || "Usage enforcement failed.");
84
+ process.exit(1);
85
+ }
86
+
70
87
  const scanMode = String(config.scanMode).toLowerCase();
71
88
  let targets = [];
72
89
 
@@ -14,6 +14,7 @@ export async function runWhoAmI() {
14
14
  logInfo("");
15
15
  logInfo("Use this ID to log in at:");
16
16
  logInfo("http://localhost:3000/login");
17
+ logInfo("http://localhost:3000/login");
17
18
  logInfo("");
18
19
  logInfo(`Config: ${getGlobalConfigPath()}`);
19
20
  }
@@ -0,0 +1,98 @@
1
+ import http from "http";
2
+ import https from "https";
3
+
4
+ const DEFAULT_API_BASE = "http://127.0.0.1:4000/api";
5
+
6
+ function resolveApiBase(config) {
7
+ const envBase = typeof process.env.CODEPROOF_API_BASE === "string"
8
+ ? process.env.CODEPROOF_API_BASE.trim()
9
+ : "";
10
+ if (envBase) {
11
+ return envBase.replace(/\/+$/, "");
12
+ }
13
+
14
+ const endpoint = typeof config?.integration?.endpointUrl === "string"
15
+ ? config.integration.endpointUrl.trim()
16
+ : "";
17
+
18
+ if (endpoint) {
19
+ try {
20
+ const url = new URL(endpoint);
21
+ return `${url.origin}/api`;
22
+ } catch {
23
+ return DEFAULT_API_BASE;
24
+ }
25
+ }
26
+
27
+ return DEFAULT_API_BASE;
28
+ }
29
+
30
+ export async function checkUsageOrThrow({ clientId, config }) {
31
+ const apiBase = resolveApiBase(config);
32
+ const endpoint = `${apiBase}/usage/check-and-increment`;
33
+ const payload = JSON.stringify({ clientId });
34
+
35
+ return new Promise((resolve, reject) => {
36
+ try {
37
+ const url = new URL(endpoint);
38
+ const transport = url.protocol === "http:" ? http : https;
39
+ const portNumber = url.port
40
+ ? parseInt(url.port, 10)
41
+ : url.protocol === "http:"
42
+ ? 80
43
+ : 443;
44
+
45
+ const request = transport.request(
46
+ {
47
+ method: "POST",
48
+ hostname: url.hostname,
49
+ port: portNumber,
50
+ path: `${url.pathname}${url.search}`,
51
+ headers: {
52
+ "Content-Type": "application/json",
53
+ "Content-Length": Buffer.byteLength(payload),
54
+ },
55
+ timeout: 5000,
56
+ },
57
+ (res) => {
58
+ let body = "";
59
+ res.on("data", (chunk) => {
60
+ body += chunk;
61
+ });
62
+ res.on("end", () => {
63
+ if (res.statusCode !== 200) {
64
+ reject(new Error(`Usage check failed (${res.statusCode})`));
65
+ return;
66
+ }
67
+
68
+ try {
69
+ const data = body ? JSON.parse(body) : null;
70
+ if (!data || typeof data.allowed !== "boolean") {
71
+ reject(new Error("Invalid usage response"));
72
+ return;
73
+ }
74
+ resolve(data);
75
+ } catch (error) {
76
+ reject(new Error("Invalid usage response"));
77
+ }
78
+ });
79
+ res.resume();
80
+ }
81
+ );
82
+
83
+ request.on("timeout", () => {
84
+ request.destroy();
85
+ reject(new Error("Usage check timeout"));
86
+ });
87
+
88
+ request.on("error", (err) => {
89
+ reject(new Error(`Usage check error: ${err.message}`));
90
+ });
91
+
92
+ request.write(payload);
93
+ request.end();
94
+ } catch (error) {
95
+ reject(new Error("Usage check failed"));
96
+ }
97
+ });
98
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeproof",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "CodeProof CLI",
5
5
  "type": "module",
6
6
  "bin": {