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