proof-of-commitment 1.26.0 → 1.28.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 +34 -11
  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.26.0
3
+ * proof-of-commitment CLI v1.28.0
4
4
  * Scores npm/PyPI/Cargo/Go packages on behavioral commitment signals.
5
5
  * Usage: npx proof-of-commitment [packages...] [options]
6
6
  */
@@ -649,7 +649,7 @@ function printTable(results, { totalScanned, totalCritical, lockfile } = {}) {
649
649
  * intent. Copy adapts to context: degradation alerts (CRITICAL) vs baseline
650
650
  * lock-in (healthy). Quick lookups (<3 packages) still skip the prompt.
651
651
  */
652
- async function inlineSignup(results) {
652
+ async function inlineSignup(results, opts = {}) {
653
653
  // Only prompt in interactive TTY when no key saved
654
654
  if (!process.stdin.isTTY || !process.stdout.isTTY) return;
655
655
  const hasKey = !!process.env.COMMIT_API_KEY || _cachedHasKey;
@@ -657,20 +657,36 @@ async function inlineSignup(results) {
657
657
  const critPkgs = results.filter(r => hasCritical(r.riskFlags));
658
658
  const lowScorePkgs = results.filter(r => typeof r.score === 'number' && r.score < 60);
659
659
  const hasFindings = critPkgs.length >= 1 || lowScorePkgs.length >= 2;
660
- // Gate: show prompt when there's something worth monitoring.
660
+ // engagementSignal: true when the backend returned an `_cta` field, which
661
+ // means this IP has scored ≥ AUDIT_SOFT_CTA_AT (5) packages today.
662
+ // That's a server-confirmed engagement signal independent of local result
663
+ // shape — the user is approaching the daily wall (15) and will hit it
664
+ // soon. Pre-this fix, single-package healthy scans at counts 5–14 saw
665
+ // only a dim URL: the strongest in-terminal conversion moment dropped to
666
+ // a copy-paste task. With engagementSignal=true we bypass the findings
667
+ // gate so the inline email→key prompt fires at the moment of warmest
668
+ // engagement. Closes the leak found 2026-06-10 dogfooding /api/keys/stats:
669
+ // 4 IPs hit AUDIT_SOFT_CTA_AT in 7d, 0 organic signups.
670
+ const engagementSignal = !!opts.engagementSignal;
671
+ // Gate: show prompt when there's something worth monitoring OR the user
672
+ // has demonstrated repeat-use engagement today (server _cta signal).
661
673
  // Old gate (results.length < 3) blocked the most common entry point:
662
674
  // `npx proof-of-commitment axios` after reading about an attack.
663
675
  // A single CRITICAL result IS the high-intent moment — don't skip it.
664
- // For healthy single-package checks with no findings, still skip.
665
- if (results.length < 3 && !hasFindings) return;
676
+ // For healthy single-package checks with no findings AND no engagement
677
+ // signal, still skip.
678
+ if (results.length < 3 && !hasFindings && !engagementSignal) return;
666
679
 
667
680
  // Copy adapts to context. Findings → degradation framing.
668
681
  // Healthy → baseline-lock framing (still real value: alert me if any score drops).
682
+ // engagementSignal without findings → soft-CTA wall-approach framing.
669
683
  const heading = hasFindings
670
684
  ? (results.length === 1
671
685
  ? ' 🔔 Monitor this package. Get alerted if it gets worse.'
672
686
  : ' 🔔 Lock in this audit. Get alerted if these packages get worse.')
673
- : ' 🔔 Lock in this baseline. Get alerted if any of these packages degrade.';
687
+ : engagementSignal
688
+ ? ' 🔔 Past the free anonymous quota on this network — lift it to 200/day.'
689
+ : ' 🔔 Lock in this baseline. Get alerted if any of these packages degrade.';
674
690
 
675
691
  console.log(clr(c.dim, ' ─────────────────────────────────────────────'));
676
692
  console.log(clr(c.bold, heading));
@@ -696,10 +712,17 @@ async function inlineSignup(results) {
696
712
  process.stdout.write(clr(c.dim, ' Creating key...'));
697
713
 
698
714
  try {
715
+ // Funnel attribution: 'cli-soft-cta' for engagement-signal path,
716
+ // 'cli' for findings-driven inline prompts. Lets api_keys.source
717
+ // measure 2026-06-10 engagementSignal gate-bypass lift separately
718
+ // from baseline inline-CLI signups. Backend VALID_SOURCES gains
719
+ // 'cli-soft-cta' in this same commit; older worker versions drop
720
+ // unknown sources to 'web' (safe degradation, no error).
721
+ const source = engagementSignal && !hasFindings ? 'cli-soft-cta' : 'cli';
699
722
  const res = await fetch('https://poc-backend.amdal-dev.workers.dev/api/keys/create', {
700
723
  method: 'POST',
701
724
  headers: { 'Content-Type': 'application/json' },
702
- body: JSON.stringify({ email, source: 'cli' }),
725
+ body: JSON.stringify({ email, source }),
703
726
  });
704
727
 
705
728
  const data = await res.json();
@@ -734,7 +757,7 @@ async function inlineSignup(results) {
734
757
 
735
758
  function printHelp() {
736
759
  console.log(`
737
- ${clr(c.bold, 'proof-of-commitment')} v1.24.0 — supply chain risk scorer
760
+ ${clr(c.bold, 'proof-of-commitment')} v1.28.0 — supply chain risk scorer
738
761
 
739
762
  ${clr(c.bold, 'Usage:')}
740
763
  npx proof-of-commitment Auto-detect manifest in current dir
@@ -846,7 +869,7 @@ ${clr(c.bold, 'Score dimensions (npm/PyPI/Cargo):')} longevity · download momen
846
869
  ${clr(c.bold, 'Score dimensions (Go):')} longevity · release consistency · maintainer depth · GitHub backing · stars
847
870
 
848
871
  ${clr(c.bold, 'MCP:')} https://poc-backend.amdal-dev.workers.dev/mcp — connect from Claude Desktop / Cursor / Cline.
849
- Free tier: 100 queries/IP/UTC day. Power users: API key for 200/day. ${clr(c.dim, '(Authorization: Bearer sk_commit_…)')}
872
+ Anonymous: 15 queries/IP/UTC day. Free API key (instant, no card): 200/day. ${clr(c.dim, '(Authorization: Bearer sk_commit_…)')}
850
873
 
851
874
  ${clr(c.bold, 'Web:')} ${WEB}
852
875
  `);
@@ -2635,7 +2658,7 @@ async function main() {
2635
2658
  const criticalTotal = allResults.filter(r => hasCritical(r.riskFlags)).length;
2636
2659
  printTable(displayed, { totalScanned: allResults.length, totalCritical: criticalTotal, lockfile: true });
2637
2660
  if (apiCta) console.log(clr(c.dim + c.cyan, `\n ${apiCta}`));
2638
- await inlineSignup(displayed);
2661
+ await inlineSignup(displayed, { engagementSignal: !!apiCta });
2639
2662
  if (shouldFail(allResults, failOn)) {
2640
2663
  console.error(clr(c.red + c.bold, `\n✗ --fail-on=${failOn} threshold met. Exit 1.`));
2641
2664
  process.exit(1);
@@ -2676,7 +2699,7 @@ async function main() {
2676
2699
 
2677
2700
  printTable(allResults);
2678
2701
  if (apiCta) console.log(clr(c.dim + c.cyan, `\n ${apiCta}`));
2679
- await inlineSignup(allResults);
2702
+ await inlineSignup(allResults, { engagementSignal: !!apiCta });
2680
2703
  if (shouldFail(allResults, failOn)) {
2681
2704
  console.error(clr(c.red + c.bold, `✗ --fail-on=${failOn} threshold met. Exit 1.`));
2682
2705
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proof-of-commitment",
3
- "version": "1.26.0",
3
+ "version": "1.28.0",
4
4
  "mcpName": "io.github.piiiico/proof-of-commitment",
5
5
  "description": "Supply chain security risk scorer for npm, PyPI, Cargo, and Go packages — behavioral signals that can't be faked",
6
6
  "type": "module",