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.
- package/index.js +34 -11
- 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.
|
|
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
|
-
//
|
|
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
|
|
665
|
-
|
|
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
|
-
:
|
|
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
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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",
|