@log-drop/web 1.0.0-alpha2 → 1.0.0-alpha4

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/README.md CHANGED
@@ -13,7 +13,6 @@ import { LogDrop } from "@log-drop/web";
13
13
 
14
14
  LogDrop.init({
15
15
  appId: "your-app-id",
16
- apiKey: "your-api-key",
17
16
  release: "1.0.0",
18
17
  });
19
18
  ```
@@ -25,7 +24,7 @@ Load a pinned stable SDK version from the LogDrop CDN:
25
24
  ```html
26
25
  <script src="https://cdn.logdrop.io/PUBLIC_FILES/logdrop-web-sdk/release/1.0.0/logdrop.min.js"></script>
27
26
  <script>
28
- LogDrop.init({ appId: "your-app-id", apiKey: "your-api-key" });
27
+ LogDrop.init({ appId: "your-app-id" });
29
28
  </script>
30
29
  ```
31
30
 
@@ -36,7 +35,6 @@ Copy the exported `logdrop-sw.js` file to the website's own public directory, th
36
35
  ```js
37
36
  LogDrop.init({
38
37
  appId: "your-app-id",
39
- apiKey: "your-api-key",
40
38
  serviceWorkerUrl: "/logdrop-sw.js",
41
39
  serviceWorkerScope: "/",
42
40
  });
package/dist/index.cjs CHANGED
@@ -38,7 +38,7 @@ LogDropConstants.DEFAULT_BASE_URL = "https://server.logdrop.io";
38
38
  LogDropConstants.DEFAULT_WEB_SECRET_KEY = "xuM9w0BAQEFx";
39
39
  LogDropConstants.FILE_EXPORT_INTERVAL_MS = 3e5;
40
40
  LogDropConstants.DEVICE_INFO_INTERVAL_MS = 1e4;
41
- LogDropConstants.SDK_VERSION = true ? "1.0.0-alpha2" : "1.0.0";
41
+ LogDropConstants.SDK_VERSION = true ? "1.0.0-alpha4" : "1.0.0";
42
42
  LogDropConstants.STORAGE_CHECK_INTERVAL_MS = 12e4;
43
43
  LogDropConstants.MAX_LOCAL_STORAGE_SIZE = 5242880;
44
44
  LogDropConstants.DATABASE_MAX_STORAGE_LIMIT = 16e6;
@@ -540,6 +540,168 @@ var NetworkInstrumentation = class {
540
540
  }
541
541
  };
542
542
 
543
+ // src/instrumentation/httpCapturePolicy.js
544
+ var ALWAYS_MASKED_HEADERS = /* @__PURE__ */ new Set([
545
+ "authorization",
546
+ "proxy-authorization",
547
+ "x-auth-token",
548
+ "x-api-key",
549
+ "x-session-token",
550
+ "cookie",
551
+ "set-cookie"
552
+ ]);
553
+ var MASK = "***";
554
+ var MAX_PATTERN_LENGTH = 500;
555
+ var DANGEROUS_PATTERN = /(a\+)\+|\(\.\*\)\+|\(\.\+\)\+/;
556
+ function normalizeHost(value) {
557
+ const host = String(value ?? "").trim().replace(/\.+$/, "").toLowerCase();
558
+ if (!host || /[/:?#@]/.test(host) || host.length > 253) return null;
559
+ return host;
560
+ }
561
+ function normalizePath(value) {
562
+ const trimmed = String(value ?? "").trim();
563
+ if (!trimmed) return "/";
564
+ const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
565
+ return withSlash.length > 1 ? withSlash.replace(/\/+$/, "") : withSlash;
566
+ }
567
+ function domainMatches(host, ruleHost) {
568
+ return host === ruleHost || host.endsWith(`.${ruleHost}`);
569
+ }
570
+ function pathMatches(path, rulePath, matchType) {
571
+ if (matchType === "EXACT") return path === rulePath;
572
+ if (matchType === "PREFIX") return rulePath === "/" || path === rulePath || path.startsWith(`${rulePath}/`);
573
+ return false;
574
+ }
575
+ function parseUrl(url) {
576
+ try {
577
+ const parsed = new URL(String(url ?? ""));
578
+ const host = normalizeHost(parsed.hostname);
579
+ return host ? { host, path: normalizePath(parsed.pathname) } : null;
580
+ } catch {
581
+ return null;
582
+ }
583
+ }
584
+ function compileSensitivePatterns(filters) {
585
+ const patterns = [];
586
+ for (const filter of Array.isArray(filters) ? filters : []) {
587
+ const source = String(filter ?? "");
588
+ if (!source || source.length > MAX_PATTERN_LENGTH) continue;
589
+ const parts = source.match(/^\/(.+)\/([gimsuy]*)$/);
590
+ const body = parts ? parts[1] : source;
591
+ if (DANGEROUS_PATTERN.test(body)) continue;
592
+ let flags = parts ? parts[2] : "";
593
+ if (!flags.includes("g")) flags += "g";
594
+ if (!flags.includes("i")) flags += "i";
595
+ try {
596
+ patterns.push(new RegExp(body, flags));
597
+ } catch {
598
+ }
599
+ }
600
+ return patterns;
601
+ }
602
+ function hashString(text) {
603
+ let hash = 2166136261;
604
+ for (let i = 0; i < text.length; i++) {
605
+ hash ^= text.charCodeAt(i);
606
+ hash = Math.imul(hash, 16777619);
607
+ }
608
+ return (hash >>> 0).toString(16);
609
+ }
610
+ function buildHttpCapturePolicy(config) {
611
+ const policy = {
612
+ domainBlacklist: (config?.httpDomainBlackList ?? []).map(normalizeHost).filter(Boolean),
613
+ pathBlacklist: Array.isArray(config?.httpPathBlackList) ? config.httpPathBlackList : [],
614
+ captureConfig: config?.httpPayloadCaptureConfig ?? null,
615
+ sensitivePatterns: compileSensitivePatterns(config?.sensitiveInfoFilter)
616
+ };
617
+ policy.fingerprint = hashString(JSON.stringify([
618
+ policy.domainBlacklist,
619
+ policy.pathBlacklist,
620
+ policy.captureConfig,
621
+ policy.sensitivePatterns.map((pattern) => `${pattern.source}/${pattern.flags}`)
622
+ ]));
623
+ return policy;
624
+ }
625
+ function shouldIgnoreHttpUrl(url, policy) {
626
+ const target = parseUrl(url);
627
+ if (!target || !policy) return false;
628
+ if (policy.domainBlacklist.some((domain) => domainMatches(target.host, domain))) return true;
629
+ return policy.pathBlacklist.some((rule) => {
630
+ const ruleHost = normalizeHost(rule?.host);
631
+ if (!ruleHost || !domainMatches(target.host, ruleHost)) return false;
632
+ return pathMatches(target.path, normalizePath(rule.path), rule.matchType);
633
+ });
634
+ }
635
+ function resolveDisabledPayloadFields(url, captureConfig) {
636
+ const disabled = {
637
+ requestHeaders: captureConfig?.disableRequestHeaders === true,
638
+ requestBody: captureConfig?.disableRequestBody === true,
639
+ responseHeaders: captureConfig?.disableResponseHeaders === true,
640
+ responseBody: captureConfig?.disableResponseBody === true
641
+ };
642
+ const target = parseUrl(url);
643
+ if (!captureConfig || !target) return disabled;
644
+ for (const rule of captureConfig.rules ?? []) {
645
+ const ruleHost = normalizeHost(rule?.host);
646
+ if (!ruleHost || !domainMatches(target.host, ruleHost)) continue;
647
+ if (rule.path && String(rule.path).trim() && !pathMatches(target.path, normalizePath(rule.path), rule.matchType)) {
648
+ continue;
649
+ }
650
+ disabled.requestHeaders || (disabled.requestHeaders = rule.disableRequestHeaders === true);
651
+ disabled.requestBody || (disabled.requestBody = rule.disableRequestBody === true);
652
+ disabled.responseHeaders || (disabled.responseHeaders = rule.disableResponseHeaders === true);
653
+ disabled.responseBody || (disabled.responseBody = rule.disableResponseBody === true);
654
+ }
655
+ return disabled;
656
+ }
657
+ function maskSensitive(text, patterns) {
658
+ if (typeof text !== "string" || !patterns?.length) return text;
659
+ let output = text;
660
+ for (const regex of patterns) {
661
+ regex.lastIndex = 0;
662
+ output = output.replace(regex, (...args) => {
663
+ const groups = args.slice(1, -2).filter((group) => typeof group === "string" || group === void 0);
664
+ const present = groups.filter((group) => group !== void 0 && group !== "");
665
+ if (present.length === 3) return `${groups[0]}${MASK}${groups[2]}`;
666
+ if (present.length === 2) return `${groups[0]}${MASK}`;
667
+ return MASK;
668
+ });
669
+ }
670
+ return output;
671
+ }
672
+ function maskStructured(value, patterns) {
673
+ if (value == null || !patterns.length) return value;
674
+ if (typeof value === "string") return maskSensitive(value, patterns);
675
+ try {
676
+ return JSON.parse(maskSensitive(JSON.stringify(value), patterns));
677
+ } catch {
678
+ return value;
679
+ }
680
+ }
681
+ function maskCredentialHeaders(headers) {
682
+ if (!headers || typeof headers !== "object") return {};
683
+ const out = {};
684
+ for (const [key, value] of Object.entries(headers)) {
685
+ out[key] = ALWAYS_MASKED_HEADERS.has(String(key).toLowerCase()) ? MASK : value;
686
+ }
687
+ return out;
688
+ }
689
+ function applyHttpCapturePolicy(payload, policy) {
690
+ if (!payload) return null;
691
+ const effective = policy ?? buildHttpCapturePolicy(null);
692
+ if (shouldIgnoreHttpUrl(payload.url, effective)) return null;
693
+ const disabled = resolveDisabledPayloadFields(payload.url, effective.captureConfig);
694
+ const patterns = effective.sensitivePatterns;
695
+ return {
696
+ ...payload,
697
+ url: maskSensitive(String(payload.url ?? ""), patterns),
698
+ requestHeaders: disabled.requestHeaders ? {} : maskStructured(maskCredentialHeaders(payload.requestHeaders), patterns),
699
+ requestBody: disabled.requestBody ? null : maskStructured(payload.requestBody ?? null, patterns),
700
+ responseHeaders: disabled.responseHeaders ? {} : maskStructured(maskCredentialHeaders(payload.responseHeaders), patterns),
701
+ responseBody: disabled.responseBody ? null : maskStructured(payload.responseBody ?? null, patterns)
702
+ };
703
+ }
704
+
543
705
  // src/push/pushModule.js
544
706
  function hasWindow2() {
545
707
  return typeof window !== "undefined";
@@ -569,7 +731,7 @@ var PushModule = class {
569
731
  * serviceWorkerRegistration?: ServiceWorkerRegistration | null,
570
732
  * isPushEnabled?: boolean,
571
733
  * onRemoteMessageReceived?: ((payload: any) => void) | null,
572
- * apiKey?: string,
734
+ * appId?: string,
573
735
  * apiBase?: string,
574
736
  * deviceId?: string,
575
737
  * getSessionToken?: (() => string | null) | null,
@@ -587,7 +749,7 @@ var PushModule = class {
587
749
  this.serviceWorkerRegistration = cfg.serviceWorkerRegistration ?? null;
588
750
  this.isPushEnabled = cfg.isPushEnabled !== false;
589
751
  this.onRemoteMessageReceived = typeof cfg.onRemoteMessageReceived === "function" ? cfg.onRemoteMessageReceived : null;
590
- this.apiKey = cfg.apiKey ?? null;
752
+ this.appId = cfg.appId ?? null;
591
753
  this.apiBase = cfg.apiBase ?? "";
592
754
  this.deviceId = cfg.deviceId ?? null;
593
755
  this.getSessionToken = typeof cfg.getSessionToken === "function" ? cfg.getSessionToken : null;
@@ -909,7 +1071,7 @@ var PushModule = class {
909
1071
  config: {
910
1072
  vapidPublicKey: this.vapidPublicKey,
911
1073
  apiBase: this.apiBase,
912
- apiKey: this.apiKey,
1074
+ appId: this.appId,
913
1075
  sessionToken: this.getSessionToken ? this.getSessionToken() : null,
914
1076
  deviceUuid: this.deviceId
915
1077
  }
@@ -1725,6 +1887,105 @@ function decodeWebPushConfig(buf) {
1725
1887
  }
1726
1888
  return result;
1727
1889
  }
1890
+ var HTTP_PATH_MATCH_TYPES = ["EXACT", "PREFIX"];
1891
+ function decodeHttpPathMatchType(value) {
1892
+ return HTTP_PATH_MATCH_TYPES[value] ?? null;
1893
+ }
1894
+ function decodeHttpPathBlacklistRule(buf) {
1895
+ const r = new ProtoReader(buf);
1896
+ const result = { host: "", path: "", matchType: "EXACT" };
1897
+ while (r.hasMore()) {
1898
+ const tag = r.readTag();
1899
+ switch (tag.fieldNumber) {
1900
+ case 1:
1901
+ result.host = r.readString();
1902
+ break;
1903
+ case 2:
1904
+ result.path = r.readString();
1905
+ break;
1906
+ case 3:
1907
+ result.matchType = decodeHttpPathMatchType(r.readVarint());
1908
+ break;
1909
+ default:
1910
+ r.skip(tag.wireType);
1911
+ }
1912
+ }
1913
+ return result;
1914
+ }
1915
+ function decodeHttpPayloadCaptureRule(buf) {
1916
+ const r = new ProtoReader(buf);
1917
+ const result = {
1918
+ host: "",
1919
+ path: null,
1920
+ matchType: "EXACT",
1921
+ disableRequestHeaders: false,
1922
+ disableRequestBody: false,
1923
+ disableResponseHeaders: false,
1924
+ disableResponseBody: false
1925
+ };
1926
+ while (r.hasMore()) {
1927
+ const tag = r.readTag();
1928
+ switch (tag.fieldNumber) {
1929
+ case 1:
1930
+ result.host = r.readString();
1931
+ break;
1932
+ case 2:
1933
+ result.path = r.readString();
1934
+ break;
1935
+ case 3:
1936
+ result.matchType = decodeHttpPathMatchType(r.readVarint());
1937
+ break;
1938
+ case 4:
1939
+ result.disableRequestHeaders = r.readBool();
1940
+ break;
1941
+ case 5:
1942
+ result.disableRequestBody = r.readBool();
1943
+ break;
1944
+ case 6:
1945
+ result.disableResponseHeaders = r.readBool();
1946
+ break;
1947
+ case 7:
1948
+ result.disableResponseBody = r.readBool();
1949
+ break;
1950
+ default:
1951
+ r.skip(tag.wireType);
1952
+ }
1953
+ }
1954
+ return result;
1955
+ }
1956
+ function decodeHttpPayloadCaptureConfig(buf) {
1957
+ const r = new ProtoReader(buf);
1958
+ const result = {
1959
+ disableRequestHeaders: false,
1960
+ disableRequestBody: false,
1961
+ disableResponseHeaders: false,
1962
+ disableResponseBody: false,
1963
+ rules: []
1964
+ };
1965
+ while (r.hasMore()) {
1966
+ const tag = r.readTag();
1967
+ switch (tag.fieldNumber) {
1968
+ case 1:
1969
+ result.disableRequestHeaders = r.readBool();
1970
+ break;
1971
+ case 2:
1972
+ result.disableRequestBody = r.readBool();
1973
+ break;
1974
+ case 3:
1975
+ result.disableResponseHeaders = r.readBool();
1976
+ break;
1977
+ case 4:
1978
+ result.disableResponseBody = r.readBool();
1979
+ break;
1980
+ case 5:
1981
+ result.rules.push(decodeHttpPayloadCaptureRule(r.readBytes()));
1982
+ break;
1983
+ default:
1984
+ r.skip(tag.wireType);
1985
+ }
1986
+ }
1987
+ return result;
1988
+ }
1728
1989
  function decodeSdkRiskConfig(buf) {
1729
1990
  const r = new ProtoReader(buf);
1730
1991
  const result = {
@@ -1761,6 +2022,8 @@ function decodeConfigResponse(buf) {
1761
2022
  isCrashTrackingEnabled: false,
1762
2023
  isEventTrackingEnabled: false,
1763
2024
  httpDomainBlackList: [],
2025
+ httpPathBlackList: [],
2026
+ httpPayloadCaptureConfig: null,
1764
2027
  sensitiveInfoFilter: [],
1765
2028
  sslPinning: null,
1766
2029
  accessToken: "",
@@ -1821,6 +2084,12 @@ function decodeConfigResponse(buf) {
1821
2084
  case 15:
1822
2085
  result.isEventTrackingEnabled = r.readBool();
1823
2086
  break;
2087
+ case 16:
2088
+ result.httpPathBlackList.push(decodeHttpPathBlacklistRule(r.readBytes()));
2089
+ break;
2090
+ case 17:
2091
+ result.httpPayloadCaptureConfig = decodeHttpPayloadCaptureConfig(r.readBytes());
2092
+ break;
1824
2093
  case 18:
1825
2094
  result.webPushConfig = decodeWebPushConfig(r.readBytes());
1826
2095
  break;
@@ -1990,7 +2259,7 @@ var EventModule = class {
1990
2259
  * getSessionId: () => string,
1991
2260
  * getUserUuid: () => string|null,
1992
2261
  * release: string|undefined,
1993
- * apiKey: string,
2262
+ * appId: string,
1994
2263
  * apiBase: string,
1995
2264
  * isEventTrackingEnabled: boolean,
1996
2265
  * isFirstVisit: boolean,
@@ -2007,7 +2276,7 @@ var EventModule = class {
2007
2276
  this._logEvent = typeof cfg.logEvent === "function" ? cfg.logEvent : null;
2008
2277
  this._getSessionToken = typeof cfg.getSessionToken === "function" ? cfg.getSessionToken : null;
2009
2278
  this._release = cfg.release ?? void 0;
2010
- this._apiKey = cfg.apiKey ?? "";
2279
+ this._appId = cfg.appId ?? "";
2011
2280
  this._apiBase = cfg.apiBase ?? "";
2012
2281
  this._isEventTrackingEnabled = cfg.isEventTrackingEnabled === true;
2013
2282
  this._isFirstVisit = cfg.isFirstVisit === true;
@@ -2311,7 +2580,7 @@ var EventModule = class {
2311
2580
  headers: {
2312
2581
  "Content-Type": "application/x-protobuf",
2313
2582
  "Accept": "application/x-protobuf",
2314
- "x-api-key": this._apiKey,
2583
+ "x-api-key": this._appId,
2315
2584
  "x-session-token": sessionToken
2316
2585
  },
2317
2586
  body: new Blob([protoBytes], { type: "application/x-protobuf" })
@@ -3504,6 +3773,7 @@ var LogDropClient = class {
3504
3773
  };
3505
3774
  this._activeIpReputationAction = this._loadStoredIpReputationAction();
3506
3775
  this._ipReputationExpiryTimer = null;
3776
+ this._httpCapturePolicy = null;
3507
3777
  this._loadCachedServerConfig();
3508
3778
  this._user = this._loadPersistedExternalUser();
3509
3779
  this._errorHandlersInstalled = false;
@@ -4060,9 +4330,9 @@ var LogDropClient = class {
4060
4330
  const fetchFn = hasWindow5() ? window.fetch : typeof fetch !== "undefined" ? fetch : null;
4061
4331
  if (typeof fetchFn !== "function") return false;
4062
4332
  const osInfo = this._getOsInfo();
4063
- const last = this._lastSentUserUpdate?.apiKey === config.apiKey ? this._lastSentUserUpdate : null;
4333
+ const last = this._lastSentUserUpdate?.appId === config.appId ? this._lastSentUserUpdate : null;
4064
4334
  const runtime = {
4065
- apiKey: config.apiKey,
4335
+ appId: config.appId,
4066
4336
  userUuid: task.userUuid,
4067
4337
  osName: osInfo.osName,
4068
4338
  osVersion: osInfo.osVersion,
@@ -4092,7 +4362,7 @@ var LogDropClient = class {
4092
4362
  const headers = {
4093
4363
  "content-type": "application/x-protobuf",
4094
4364
  "accept": "application/x-protobuf",
4095
- "x-api-key": config.apiKey
4365
+ "x-api-key": config.appId
4096
4366
  };
4097
4367
  let usedSignatureAuth = false;
4098
4368
  if (sessionToken) {
@@ -4330,6 +4600,7 @@ var LogDropClient = class {
4330
4600
  if (typeof parsed.data.isSDKDisabled === "boolean") {
4331
4601
  this._serverConfig.isSDKDisabled = parsed.data.isSDKDisabled;
4332
4602
  }
4603
+ this._httpCapturePolicy = buildHttpCapturePolicy(parsed.data);
4333
4604
  }
4334
4605
  }
4335
4606
  } catch {
@@ -4351,6 +4622,9 @@ var LogDropClient = class {
4351
4622
  if (typeof data.isHttpLoggingEnabled === "boolean") {
4352
4623
  this._serverConfig.isHttpLoggingEnabled = data.isHttpLoggingEnabled;
4353
4624
  }
4625
+ if ("httpDomainBlackList" in data || "httpPayloadCaptureConfig" in data || "sensitiveInfoFilter" in data) {
4626
+ this._httpCapturePolicy = buildHttpCapturePolicy(data);
4627
+ }
4354
4628
  if (typeof data.isCrashTrackingEnabled === "boolean" && this._crashTrackingOverride === null) {
4355
4629
  this._serverConfig.isCrashTrackingEnabled = data.isCrashTrackingEnabled;
4356
4630
  }
@@ -4410,7 +4684,7 @@ var LogDropClient = class {
4410
4684
  onEvent: (eventName, payload) => {
4411
4685
  if (eventName !== "network_activity") return;
4412
4686
  if (!this._serverConfig.isHttpLoggingEnabled || !this._config?.network?.enabled) return;
4413
- this._enqueue(LogLevel.NETWORK_ACTIVITY, payload, new LogFlow("NetworkActivity", payload.uuid));
4687
+ this._recordNetworkActivity(payload);
4414
4688
  },
4415
4689
  getBaseHref,
4416
4690
  excludeUrls: this._config.network.excludeUrls,
@@ -4429,6 +4703,31 @@ var LogDropClient = class {
4429
4703
  });
4430
4704
  this._net.install();
4431
4705
  }
4706
+ _recordNetworkActivity(payload) {
4707
+ const recorded = applyHttpCapturePolicy(payload, this._httpCapturePolicy);
4708
+ if (!recorded) return;
4709
+ this._enqueue(LogLevel.NETWORK_ACTIVITY, recorded, new LogFlow("NetworkActivity", recorded.uuid));
4710
+ }
4711
+ // Logs captured before the init response, or under rules that have changed
4712
+ // since, are filtered again with the current policy before upload; logs
4713
+ // stored under the same rules are sent as they are. Returns null when the
4714
+ // log must be dropped.
4715
+ _applyHttpCapturePolicyToStoredLog(log) {
4716
+ const policy = this._httpCapturePolicy;
4717
+ if (!policy || log.level === LogLevel.DEVICEINFO) return log.message;
4718
+ if (log.httpPolicyFingerprint === policy.fingerprint) return log.message;
4719
+ if (log.level !== LogLevel.NETWORK_ACTIVITY) {
4720
+ return maskSensitive(log.message, policy.sensitivePatterns);
4721
+ }
4722
+ let parsed;
4723
+ try {
4724
+ parsed = JSON.parse(log.message);
4725
+ } catch {
4726
+ return maskSensitive(log.message, policy.sensitivePatterns);
4727
+ }
4728
+ const recorded = applyHttpCapturePolicy(parsed, policy);
4729
+ return recorded ? safeStringify(recorded) : null;
4730
+ }
4432
4731
  _uninstallNetworkInstrumentation() {
4433
4732
  if (this._net) {
4434
4733
  this._net.uninstall();
@@ -4643,9 +4942,8 @@ var LogDropClient = class {
4643
4942
  this._warnInternal("[LogDrop] SDK is disabled by server configuration");
4644
4943
  return;
4645
4944
  }
4646
- if (!config || !config.appId) throw new Error("LogDrop.init requires config.appId");
4647
- const apiKey = String(config.apiKey || "").trim();
4648
- if (!apiKey) throw new Error("LogDrop.init requires config.apiKey");
4945
+ const appId = String(config?.appId || "").trim();
4946
+ if (!appId) throw new Error("LogDrop.init requires config.appId");
4649
4947
  const defaultWebSecretKey = config.webSecretKey == null ? LogDropConstants.DEFAULT_WEB_SECRET_KEY : config.webSecretKey;
4650
4948
  const webSecretKey = String(defaultWebSecretKey || "").trim() || null;
4651
4949
  const baseUrl = normalizeBaseUrl(config.baseUrl);
@@ -4672,8 +4970,7 @@ var LogDropClient = class {
4672
4970
  ]
4673
4971
  };
4674
4972
  this._config = {
4675
- appId: String(config.appId),
4676
- apiKey,
4973
+ appId,
4677
4974
  webSecretKey,
4678
4975
  baseUrl,
4679
4976
  endpoint,
@@ -4716,7 +5013,7 @@ var LogDropClient = class {
4716
5013
  isPushEnabled: true,
4717
5014
  // default; overridden by server config in _applyServerConfig
4718
5015
  onRemoteMessageReceived: this._config.onRemoteMessageReceived,
4719
- apiKey: this._config.apiKey,
5016
+ appId: this._config.appId,
4720
5017
  apiBase: this._config.baseUrl,
4721
5018
  deviceId: this._deviceId,
4722
5019
  getSessionToken: () => this._getAccessToken(),
@@ -4750,7 +5047,7 @@ var LogDropClient = class {
4750
5047
  // Mirror every successfully sent event into the log stream at EVENT level.
4751
5048
  logEvent: (eventLog) => this._enqueue(LogLevel.EVENT, eventLog),
4752
5049
  release: this._config.release,
4753
- apiKey: this._config.apiKey,
5050
+ appId: this._config.appId,
4754
5051
  apiBase: this._config.baseUrl,
4755
5052
  isEventTrackingEnabled: this._serverConfig.isEventTrackingEnabled,
4756
5053
  isFirstVisit: this._isNewDevice,
@@ -5046,6 +5343,13 @@ var LogDropClient = class {
5046
5343
  // IMPORTANT: if message object convert => JSON string
5047
5344
  message: typeof message === "string" ? message : safeStringify(message)
5048
5345
  };
5346
+ const policy = this._httpCapturePolicy;
5347
+ if (policy && level !== LogLevel.DEVICEINFO) {
5348
+ if (level !== LogLevel.NETWORK_ACTIVITY) {
5349
+ entry.message = maskSensitive(entry.message, policy.sensitivePatterns);
5350
+ }
5351
+ entry.httpPolicyFingerprint = policy.fingerprint;
5352
+ }
5049
5353
  if (tag) {
5050
5354
  entry.tag = tag;
5051
5355
  }
@@ -5131,6 +5435,7 @@ var LogDropClient = class {
5131
5435
  message: entry.message
5132
5436
  };
5133
5437
  if (entry.tag) logRecord.tag = entry.tag;
5438
+ if (entry.httpPolicyFingerprint) logRecord.httpPolicyFingerprint = entry.httpPolicyFingerprint;
5134
5439
  if (logFlow && logFlow instanceof LogFlow) {
5135
5440
  logRecord.flowId = logFlow.id;
5136
5441
  logRecord.flowName = logFlow.name;
@@ -5432,11 +5737,16 @@ var LogDropClient = class {
5432
5737
  for (const [sessionId, logs] of Object.entries(sessionGroups)) {
5433
5738
  const sessionLogs = [];
5434
5739
  for (const log of logs) {
5740
+ const message = this._applyHttpCapturePolicyToStoredLog(log);
5741
+ if (message === null) {
5742
+ chunk.droppedLogIds.push(log.id);
5743
+ continue;
5744
+ }
5435
5745
  const logEntry = {
5436
5746
  id: log.id,
5437
5747
  ts: log.ts,
5438
5748
  level: log.level,
5439
- message: log.message,
5749
+ message,
5440
5750
  flowId: log.flowId,
5441
5751
  flowName: log.flowName,
5442
5752
  flowAttributes: log.flowAttributes
@@ -5509,7 +5819,7 @@ var LogDropClient = class {
5509
5819
  headers: {
5510
5820
  "content-type": "application/x-protobuf",
5511
5821
  "accept": "application/x-protobuf",
5512
- "x-api-key": this._config.apiKey,
5822
+ "x-api-key": this._config.appId,
5513
5823
  "x-session-token": sessionToken
5514
5824
  },
5515
5825
  body: new Blob([protoBytes], { type: "application/x-protobuf" })
@@ -5555,7 +5865,7 @@ var LogDropClient = class {
5555
5865
  headers: {
5556
5866
  "content-type": "application/x-protobuf",
5557
5867
  "accept": "application/x-protobuf",
5558
- "x-api-key": this._config.apiKey,
5868
+ "x-api-key": this._config.appId,
5559
5869
  "x-session-token": sessionToken
5560
5870
  },
5561
5871
  body: new Blob([protoBytes], { type: "application/x-protobuf" })
@@ -5654,7 +5964,8 @@ var LogDropClient = class {
5654
5964
  if (!this._dbPromise) return false;
5655
5965
  this._fileFlushInProgress = true;
5656
5966
  try {
5657
- const allLogs = await this._readAllLogs();
5967
+ const storedLogs = await this._readAllLogs();
5968
+ const allLogs = this._httpCapturePolicy ? storedLogs : storedLogs.filter((log) => log.level !== LogLevel.NETWORK_ACTIVITY);
5658
5969
  if (this._isInternalLoggingEnabled()) {
5659
5970
  this._logInternal(`[LogDrop DEBUG] _flushLogs called. DB log count: ${allLogs.length}`);
5660
5971
  }
@@ -5780,7 +6091,7 @@ var LogDropClient = class {
5780
6091
  const headers = {
5781
6092
  "content-type": "application/x-protobuf",
5782
6093
  "accept": "application/x-protobuf",
5783
- "x-api-key": this._config.apiKey
6094
+ "x-api-key": this._config.appId
5784
6095
  };
5785
6096
  const sessionToken = this._getAccessToken();
5786
6097
  const refreshToken = this._getRefreshToken();