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.
- package/index.js +77 -4
- 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.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.
|
|
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);
|