@great-arrow/cli 0.1.52 → 0.1.53

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/dist/index.js +59 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -9402,7 +9402,7 @@ function isNodeError(value) {
9402
9402
 
9403
9403
  // src/lib/version.ts
9404
9404
  var CLI_PACKAGE_NAME = "@great-arrow/cli";
9405
- var CLI_VERSION = "0.1.52";
9405
+ var CLI_VERSION = "0.1.53";
9406
9406
  var GAD_INSTALL_VERSION = "2026.08.08";
9407
9407
  var GAD_INSTALL_MIN_VERSION = "2026.06.22";
9408
9408
  var GAD_INSTALL_HEADER = "X-GAD-Install-Version";
@@ -10678,6 +10678,42 @@ function parseMcpPayload(result) {
10678
10678
  }
10679
10679
  }
10680
10680
 
10681
+ // ../../src/lib/observability/scrub-pii.ts
10682
+ var EMAIL_RE = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
10683
+ var SSN_RE = /\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g;
10684
+ var CREDIT_CARD_RE = /\b\d(?:[ -]?\d){12,18}\b/g;
10685
+ var PHONE_RE = /(?:\+?\b1[-.\s]?)?(?:\([2-9]\d{2}\)\s?|\b[2-9]\d{2}[-.\s]?)\d{3}[-.\s]?\d{4}\b/g;
10686
+ function luhnValid(candidate) {
10687
+ const digits2 = candidate.replace(/\D/g, "");
10688
+ if (digits2.length < 13 || digits2.length > 19) return false;
10689
+ let sum = 0;
10690
+ let double = false;
10691
+ for (let i = digits2.length - 1; i >= 0; i--) {
10692
+ let n = digits2.charCodeAt(i) - 48;
10693
+ if (double) {
10694
+ n *= 2;
10695
+ if (n > 9) n -= 9;
10696
+ }
10697
+ sum += n;
10698
+ double = !double;
10699
+ }
10700
+ return sum % 10 === 0;
10701
+ }
10702
+ var SECRET_TOKEN_RE = /\b(?:gad_[A-Za-z0-9_-]{20,}|sk-[A-Za-z0-9-]{20,}|Bearer\s+[A-Za-z0-9._~+/=-]{8,})\b/gi;
10703
+ var SENSITIVE_QUERY_VALUE_RE = /((?:^|[?&])(?:code|token|access_token|refresh_token|id_token|api_key|apikey|api_secret|apisecret|key|secret|client_secret|password|state)=)[^&#\s]+/gi;
10704
+ function scrubPiiFromText(s) {
10705
+ return s.replace(EMAIL_RE, "[redacted-email]").replace(
10706
+ CREDIT_CARD_RE,
10707
+ (m) => luhnValid(m) ? "[redacted-credit-card]" : m
10708
+ ).replace(SSN_RE, "[redacted-ssn]").replace(PHONE_RE, "[redacted-phone]");
10709
+ }
10710
+ function scrubTelemetryText(s) {
10711
+ return scrubPiiFromText(s).replace(SENSITIVE_QUERY_VALUE_RE, "$1[redacted]").replace(
10712
+ SECRET_TOKEN_RE,
10713
+ (match) => match.toLowerCase().startsWith("bearer ") ? "Bearer [redacted]" : "[redacted-secret]"
10714
+ );
10715
+ }
10716
+
10681
10717
  // src/lib/telemetry.ts
10682
10718
  var MAX_EVENTS_PER_PROCESS = 20;
10683
10719
  var MAX_STRING = 240;
@@ -10685,12 +10721,14 @@ var sent = 0;
10685
10721
  function enabled() {
10686
10722
  if (process.env.GAD_TELEMETRY === "0" || process.env.GAD_TELEMETRY === "false")
10687
10723
  return false;
10688
- return process.env.GAD_TELEMETRY === "1" || process.env.GAD_TELEMETRY === "true";
10724
+ if (process.env.GAD_TELEMETRY === "1" || process.env.GAD_TELEMETRY === "true")
10725
+ return true;
10726
+ return void 0;
10689
10727
  }
10690
10728
  function redact(value, depth = 0) {
10691
10729
  if (depth > 3) return "[redacted]";
10692
10730
  if (typeof value === "string") {
10693
- const scrubbed = value.replace(/Bearer\s+\S+/gi, "Bearer [redacted]").replace(
10731
+ const scrubbed = scrubTelemetryText(value).replace(/Bearer\s+\S+/gi, "Bearer [redacted]").replace(
10694
10732
  /(token|secret|password|authorization)[=:]\s*[^\s,]+/gi,
10695
10733
  "$1=[redacted]"
10696
10734
  );
@@ -10709,7 +10747,9 @@ function redact(value, depth = 0) {
10709
10747
  }
10710
10748
  async function captureCliEvent(input) {
10711
10749
  if (sent >= MAX_EVENTS_PER_PROCESS) return;
10712
- if (!enabled()) {
10750
+ const envConsent = enabled();
10751
+ if (envConsent === false) return;
10752
+ if (envConsent === void 0) {
10713
10753
  try {
10714
10754
  const config = await loadConfig();
10715
10755
  if (config.telemetry_enabled !== true) return;
@@ -10717,28 +10757,33 @@ async function captureCliEvent(input) {
10717
10757
  return;
10718
10758
  }
10719
10759
  }
10760
+ if (sent >= MAX_EVENTS_PER_PROCESS) return;
10720
10761
  sent++;
10721
10762
  const error = input.error instanceof Error ? { name: input.error.name, message: input.error.message } : input.error;
10722
10763
  const payload = {
10723
10764
  platform: "cli",
10724
10765
  event: input.name,
10725
10766
  level: input.error ? "error" : "info",
10726
- message: error && typeof error === "object" && "message" in error ? String(error.message) : input.name,
10767
+ message: error && typeof error === "object" && "message" in error ? redact(String(error.message)) : redact(input.name),
10727
10768
  version: process.env.GAD_CLI_VERSION,
10728
10769
  code: input.context?.code,
10729
10770
  context: redact(input.context ?? {}),
10730
10771
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
10731
10772
  };
10732
10773
  try {
10733
- await fetch(`${input.apiUrl.replace(/\/$/, "")}/api/telemetry`, {
10734
- method: "POST",
10735
- headers: {
10736
- "content-type": "application/json",
10737
- ...input.token ? { authorization: `Bearer ${input.token}` } : {}
10738
- },
10739
- body: JSON.stringify(payload),
10740
- signal: AbortSignal.timeout(1500)
10741
- });
10774
+ const response = await fetch(
10775
+ `${input.apiUrl.replace(/\/$/, "")}/api/telemetry`,
10776
+ {
10777
+ method: "POST",
10778
+ headers: {
10779
+ "content-type": "application/json"
10780
+ },
10781
+ body: JSON.stringify(redact(payload)),
10782
+ signal: AbortSignal.timeout(1500)
10783
+ }
10784
+ );
10785
+ if (!response.ok)
10786
+ debugSwallow("telemetry.send", new Error(`HTTP ${response.status}`));
10742
10787
  } catch (err) {
10743
10788
  debugSwallow("telemetry.send", err);
10744
10789
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@great-arrow/cli",
3
- "version": "0.1.52",
3
+ "version": "0.1.53",
4
4
  "description": "GreatArrow.ai CLI tool",
5
5
  "type": "module",
6
6
  "bin": {