proof-of-commitment 1.12.1 → 1.13.1

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 (2) hide show
  1. package/index.js +77 -4
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * proof-of-commitment CLI v1.12.1
3
+ * proof-of-commitment CLI v1.13.1
4
4
  * Scores npm/PyPI/Cargo/Go packages on behavioral commitment signals.
5
5
  * Usage: npx proof-of-commitment [packages...] [options]
6
6
  */
@@ -198,24 +198,95 @@ function printTable(results, { totalScanned, totalCritical, lockfile } = {}) {
198
198
  }
199
199
 
200
200
  // Contextual upsell — show when findings make monitoring relevant
201
+ // In TTY mode, inlineSignup() handles the upsell interactively — skip static text
201
202
  if (effectiveCritical > 0) {
202
- // Check for API key synchronously via env (fast path)
203
203
  const hasKey = !!process.env.COMMIT_API_KEY || _cachedHasKey;
204
204
  if (hasKey) {
205
205
  console.log(clr(c.dim, `\n 📊 Monitor ${effectiveCritical === 1 ? 'this package' : 'these packages'}: `) +
206
206
  clr(c.cyan, `poc watch ${results.find(r => hasCritical(r.riskFlags))?.name || results[0]?.name}`));
207
- } else {
207
+ } else if (!process.stdin.isTTY || !process.stdout.isTTY) {
208
+ // Non-TTY (CI, piped): show static URL since interactive prompt won't work
208
209
  console.log(clr(c.dim, `\n 📊 Monitor ${effectiveCritical === 1 ? 'this' : 'these ' + effectiveCritical} CRITICAL ${effectiveCritical === 1 ? 'package' : 'packages'} — get alerted when scores change.`));
209
210
  console.log(clr(c.dim, ' Get a free API key: ') + clr(c.cyan, 'https://getcommit.dev/get-started?utm_source=cli'));
210
211
  console.log(clr(c.dim, ' Then run: ') + clr(c.cyan, 'poc login'));
211
212
  }
213
+ // else: TTY mode — inlineSignup() will prompt interactively after printTable
214
+ }
215
+ console.log();
216
+ }
217
+
218
+ /**
219
+ * Inline signup: after CRITICAL findings, offer one-step email→key flow.
220
+ * Collapses 6-step funnel (visit site → email → check inbox → copy key → login → watch)
221
+ * into a single CLI prompt.
222
+ */
223
+ async function inlineSignup(results) {
224
+ // Only prompt in interactive TTY when CRITICAL packages found and no key saved
225
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return;
226
+ const hasKey = !!process.env.COMMIT_API_KEY || _cachedHasKey;
227
+ if (hasKey) return;
228
+ const critPkgs = results.filter(r => hasCritical(r.riskFlags));
229
+ if (critPkgs.length === 0) return;
230
+
231
+ console.log(clr(c.dim, ' ─────────────────────────────────────────────'));
232
+ console.log(clr(c.bold, ' 🔔 Get alerts when these scores change?'));
233
+ console.log(clr(c.dim, ' Free API key — no credit card, 10 seconds.\n'));
234
+
235
+ const { createInterface } = await import('readline');
236
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
237
+
238
+ const email = await new Promise(resolve => {
239
+ rl.question(clr(c.dim, ' Your email (Enter to skip): '), answer => {
240
+ rl.close();
241
+ resolve(answer.trim());
242
+ });
243
+ });
244
+
245
+ if (!email) return;
246
+
247
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
248
+ console.log(clr(c.red, ' Invalid email. Skipped.'));
249
+ return;
212
250
  }
251
+
252
+ process.stdout.write(clr(c.dim, ' Creating key...'));
253
+
254
+ try {
255
+ const res = await fetch('https://poc-backend.amdal-dev.workers.dev/api/keys/create', {
256
+ method: 'POST',
257
+ headers: { 'Content-Type': 'application/json' },
258
+ body: JSON.stringify({ email, source: 'cli' }),
259
+ });
260
+
261
+ const data = await res.json();
262
+
263
+ if (data.key) {
264
+ await writeApiKey(data.key);
265
+ _cachedHasKey = true;
266
+ console.log(clr(c.green, ' ✓ Saved to ~/.commit/config'));
267
+ console.log(clr(c.dim, ` Backup sent to ${email}`));
268
+ console.log();
269
+ console.log(clr(c.bold, ' Next steps:'));
270
+ console.log(clr(c.dim, ' • ') + clr(c.cyan, 'poc status') + clr(c.dim, ' — check your account'));
271
+ if (critPkgs.length > 0) {
272
+ console.log(clr(c.dim, ' • ') + clr(c.cyan, `poc watch ${critPkgs[0].name}`) + clr(c.dim, ' — start monitoring (Pro)'));
273
+ }
274
+ console.log(clr(c.dim, ' • ') + clr(c.cyan, 'poc init') + clr(c.dim, ' — add CI gate to this project'));
275
+ } else if (data.message) {
276
+ console.log(clr(c.green, ` ✓ ${data.message}`));
277
+ } else {
278
+ console.log(clr(c.red, ` Failed: ${JSON.stringify(data)}`));
279
+ }
280
+ } catch (err) {
281
+ console.log(clr(c.red, ` Error: ${err.message}`));
282
+ }
283
+
213
284
  console.log();
214
285
  }
215
286
 
216
287
  function printHelp() {
217
288
  console.log(`
218
- ${clr(c.bold, 'proof-of-commitment')} v1.12.1 — supply chain risk scorer
289
+ ${clr(c.bold, 'proof-of-commitment')} v1.13.1 — supply chain risk scorer
219
290
 
220
291
  ${clr(c.bold, 'Usage:')}
221
292
  npx proof-of-commitment Auto-detect manifest in current dir
@@ -1667,6 +1738,7 @@ async function main() {
1667
1738
  const displayed = allResults.slice(0, MAX_DISPLAY);
1668
1739
  const criticalTotal = allResults.filter(r => hasCritical(r.riskFlags)).length;
1669
1740
  printTable(displayed, { totalScanned: allResults.length, totalCritical: criticalTotal, lockfile: true });
1741
+ await inlineSignup(displayed);
1670
1742
  if (shouldFail(allResults, failOn)) {
1671
1743
  console.error(clr(c.red + c.bold, `\n✗ --fail-on=${failOn} threshold met. Exit 1.`));
1672
1744
  process.exit(1);
@@ -1697,6 +1769,7 @@ async function main() {
1697
1769
  }
1698
1770
 
1699
1771
  printTable(allResults);
1772
+ await inlineSignup(allResults);
1700
1773
  if (shouldFail(allResults, failOn)) {
1701
1774
  console.error(clr(c.red + c.bold, `✗ --fail-on=${failOn} threshold met. Exit 1.`));
1702
1775
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proof-of-commitment",
3
- "version": "1.12.1",
3
+ "version": "1.13.1",
4
4
  "description": "Supply chain risk scorer for npm, PyPI, Cargo, and Go packages — behavioral signals that can't be faked",
5
5
  "type": "module",
6
6
  "bin": {