fullcourtdefense-cli 1.26.6 → 1.26.7

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.
@@ -90,6 +90,15 @@ export interface FetchBundleInput {
90
90
  ttlMs?: number;
91
91
  /** Force a network refresh regardless of cache freshness. */
92
92
  force?: boolean;
93
+ /**
94
+ * Fetch timeout override (ms). Default is the tight hot-path budget
95
+ * (REFRESH_TIMEOUT_MS = 1.5s) — a hook must never stall a command on a slow
96
+ * control plane. Diagnostic callers (doctor --health, deep self-test) pass a
97
+ * generous value instead: a bundle answer at 3s is a healthy backend, not a
98
+ * "no live bundle" failure. The 2h workday simulation surfaced this — ~1 in
99
+ * 6 health checkpoints false-alarmed on p95 latency spikes.
100
+ */
101
+ timeoutMs?: number;
93
102
  /**
94
103
  * Hot-path caller (hook / MCP gateway): when the cached mode is monitor or
95
104
  * shadow, accept a STALE cache without a synchronous refresh — the resident
@@ -130,6 +139,7 @@ export declare function validateShieldCredentials(input: {
130
139
  apiUrl: string;
131
140
  shieldId: string;
132
141
  shieldKey?: string;
142
+ timeoutMs?: number;
133
143
  }): Promise<CredentialValidationResult>;
134
144
  /**
135
145
  * Drop every cached runtime bundle at enrollment time.
@@ -258,7 +258,7 @@ async function getRuntimeBundle(input) {
258
258
  params.set('machineName', input.machineName);
259
259
  if (input.machineId)
260
260
  params.set('machineId', input.machineId);
261
- const resp = await fetch(`${input.apiUrl}/api/cli/bundle?${params.toString()}`, { method: 'GET', headers, signal: AbortSignal.timeout(REFRESH_TIMEOUT_MS) });
261
+ const resp = await fetch(`${input.apiUrl}/api/cli/bundle?${params.toString()}`, { method: 'GET', headers, signal: AbortSignal.timeout(input.timeoutMs ?? REFRESH_TIMEOUT_MS) });
262
262
  // 304 Not Modified — cache is still valid; refresh its timestamp.
263
263
  // Re-assert the marker when the cache says suspended, but NEVER clear it
264
264
  // here: a 304 validates the version string, not the (locally editable)
@@ -359,10 +359,12 @@ async function validateShieldCredentials(input) {
359
359
  }
360
360
  try {
361
361
  const params = new URLSearchParams({ shieldId: input.shieldId });
362
+ // Diagnostic default (10s), not the hot-path 1.5s: onboarding/doctor would
363
+ // rather wait than misreport a slow-but-healthy backend as unreachable.
362
364
  const resp = await fetch(`${input.apiUrl}/api/cli/bundle?${params.toString()}`, {
363
365
  method: 'GET',
364
366
  headers: { 'Content-Type': 'application/json', 'x-shield-key': input.shieldKey },
365
- signal: AbortSignal.timeout(REFRESH_TIMEOUT_MS),
367
+ signal: AbortSignal.timeout(input.timeoutMs ?? 10_000),
366
368
  });
367
369
  if (resp.status === 401 || resp.status === 403) {
368
370
  (0, distress_1.reportDistress)('bundle', distress_1.DISTRESS.AUTH_BROKEN, `credential validation HTTP ${resp.status}`);
package/dist/selfTest.js CHANGED
@@ -91,6 +91,8 @@ async function runDeepSelfTest(input) {
91
91
  machineId: input.machineId,
92
92
  force: true,
93
93
  ttlMs: 0,
94
+ // Diagnostic call — a 3s answer is a healthy backend, not a failure.
95
+ timeoutMs: 10_000,
94
96
  });
95
97
  add({
96
98
  id: 'bundle_auth',
package/dist/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "1.26.6"
2
+ "version": "1.26.7"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fullcourtdefense-cli",
3
- "version": "1.26.6",
3
+ "version": "1.26.7",
4
4
  "description": "Full Court Defense CLI — security scanning for AI agents from your terminal",
5
5
  "main": "dist/index.js",
6
6
  "bin": {