fullcourtdefense-cli 1.7.0 → 1.7.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.
@@ -470,7 +470,7 @@ function sanitizeAgentFileForUpload(finding) {
470
470
  excerpt: finding.excerpt,
471
471
  };
472
472
  }
473
- async function upload(servers, host, clientCoverage, apiUrl, apiKey, connectorName, extras) {
473
+ async function upload(servers, host, clientCoverage, apiUrl, auth, connectorName, extras) {
474
474
  const payload = {
475
475
  connectorName: connectorName || `Desktop MCP · ${host.hostname}`,
476
476
  host,
@@ -505,10 +505,23 @@ async function upload(servers, host, clientCoverage, apiUrl, apiKey, connectorNa
505
505
  tools: s.tools,
506
506
  })),
507
507
  };
508
- const resp = await fetch(`${apiUrl.replace(/\/$/, '')}/api/cicd/discovery/mcp`, {
508
+ // Prefer the org API key path; otherwise fall back to the Shield-key endpoint so
509
+ // `discover --upload` works straight from `login` credentials with no org key.
510
+ const base = apiUrl.replace(/\/$/, '');
511
+ const useShieldKey = !auth.apiKey && !!(auth.shieldId && auth.shieldKey);
512
+ const url = useShieldKey ? `${base}/api/cli/discovery` : `${base}/api/cicd/discovery/mcp`;
513
+ const headers = { 'Content-Type': 'application/json' };
514
+ if (useShieldKey) {
515
+ headers['x-shield-id'] = auth.shieldId;
516
+ headers['x-shield-key'] = auth.shieldKey;
517
+ }
518
+ else {
519
+ headers['X-API-Key'] = auth.apiKey;
520
+ }
521
+ const resp = await fetch(url, {
509
522
  method: 'POST',
510
- headers: { 'Content-Type': 'application/json', 'X-API-Key': apiKey },
511
- body: JSON.stringify(payload),
523
+ headers,
524
+ body: JSON.stringify(useShieldKey ? { ...payload, shieldId: auth.shieldId } : payload),
512
525
  });
513
526
  const data = await resp.json().catch(() => ({}));
514
527
  if (!resp.ok || data.success === false) {
@@ -651,18 +664,20 @@ async function discoverCommand(args, config) {
651
664
  if (args.upload !== 'true')
652
665
  return;
653
666
  const creds = (0, config_1.resolveCliCredentials)(config, { apiKey: args.apiKey, apiUrl: args.apiUrl });
654
- if (!creds.apiKey) {
667
+ // Either an org API key OR an enrolled Shield key (from `login`) is enough.
668
+ const hasShieldCreds = !!(creds.shieldId && creds.shieldKey);
669
+ if (!creds.apiKey && !hasShieldCreds) {
655
670
  if (!silent) {
656
- console.error(`\n${COLOR.red}--upload requires an API key.${COLOR.reset} Run \`fullcourtdefense setup\` first.`);
671
+ console.error(`\n${COLOR.red}--upload needs credentials.${COLOR.reset} Run \`fullcourtdefense login --token <fleet-token>\` (or \`fullcourtdefense setup\`) first.`);
657
672
  }
658
673
  process.exit(1);
659
674
  }
660
- await upload(found, host, clientCoverage, creds.apiUrl, creds.apiKey, args.connectorName, uploadExtras);
675
+ await upload(found, host, clientCoverage, creds.apiUrl, { apiKey: creds.apiKey, shieldId: creds.shieldId, shieldKey: creds.shieldKey }, args.connectorName, uploadExtras);
661
676
  }
662
677
  if (silent) {
663
678
  if (args.upload === 'true') {
664
679
  const creds = (0, config_1.resolveCliCredentials)(config, { apiKey: args.apiKey, apiUrl: args.apiUrl });
665
- if (!creds.apiKey)
680
+ if (!creds.apiKey && !(creds.shieldId && creds.shieldKey))
666
681
  process.exit(1);
667
682
  if (!runMcp && !secrets && !agentFiles && !posture)
668
683
  return;
@@ -12,12 +12,14 @@ const restartNotice_1 = require("./restartNotice");
12
12
  * hooks for built-in Cursor actions, optional self-heal and fleet upload.
13
13
  */
14
14
  async function installAllCommand(args, config) {
15
+ // A Shield id/key (from `login` or `setup`) is all that's needed — the org API
16
+ // key is optional, so the zero-paste `login` → `install-all` flow works without one.
15
17
  const creds = (0, config_1.requireCliSetup)(config, {
16
18
  apiKey: args.apiKey,
17
19
  shieldId: args.shieldId,
18
20
  shieldKey: args.shieldKey,
19
21
  apiUrl: args.apiUrl,
20
- }, { requireOrganizationId: false });
22
+ }, { requireOrganizationId: false, requireApiKey: false });
21
23
  const gatewayArgs = {
22
24
  ...args,
23
25
  ...creds,
@@ -51,7 +53,10 @@ async function installAllCommand(args, config) {
51
53
  intervalMinutes: args.intervalMinutes || '60',
52
54
  }, config);
53
55
  }
54
- if (args.discover === 'true' || args.upload === 'true') {
56
+ // Run discovery + upload by default so the AI Fleet "Devices & MCP" view is
57
+ // populated on first install — no extra command, no org API key (uploads via
58
+ // the enrolled Shield key). Opt out with `--discover false`.
59
+ if (args.discover !== 'false') {
55
60
  console.log('\n\x1b[1mUploading desktop posture to AI Fleet…\x1b[0m');
56
61
  const discoverArgs = {
57
62
  surface: 'all',
@@ -59,7 +64,6 @@ async function installAllCommand(args, config) {
59
64
  apiKey: creds.apiKey,
60
65
  apiUrl: creds.apiUrl,
61
66
  userEmail: args.developerName,
62
- silent: args.upload === 'true' && args.discover !== 'true' ? 'true' : undefined,
63
67
  };
64
68
  await (0, discover_1.discoverCommand)(discoverArgs, config);
65
69
  }
package/dist/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "1.7.0"
2
+ "version": "1.7.1"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fullcourtdefense-cli",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "Full Court Defense CLI — security scanning for AI agents from your terminal",
5
5
  "main": "dist/index.js",
6
6
  "bin": {