@chainpatrol/sdk 1.10.0 → 1.11.0

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/dist/index.js CHANGED
@@ -1274,17 +1274,17 @@ var PolyDateFormatter = class {
1274
1274
  constructor(dt, intl, opts) {
1275
1275
  this.opts = opts;
1276
1276
  this.originalZone = void 0;
1277
- let z61 = void 0;
1277
+ let z64 = void 0;
1278
1278
  if (this.opts.timeZone) {
1279
1279
  this.dt = dt;
1280
1280
  } else if (dt.zone.type === "fixed") {
1281
1281
  const gmtOffset = -1 * (dt.offset / 60);
1282
1282
  const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`;
1283
1283
  if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) {
1284
- z61 = offsetZ;
1284
+ z64 = offsetZ;
1285
1285
  this.dt = dt;
1286
1286
  } else {
1287
- z61 = "UTC";
1287
+ z64 = "UTC";
1288
1288
  this.dt = dt.offset === 0 ? dt : dt.setZone("UTC").plus({ minutes: dt.offset });
1289
1289
  this.originalZone = dt.zone;
1290
1290
  }
@@ -1292,14 +1292,14 @@ var PolyDateFormatter = class {
1292
1292
  this.dt = dt;
1293
1293
  } else if (dt.zone.type === "iana") {
1294
1294
  this.dt = dt;
1295
- z61 = dt.zone.name;
1295
+ z64 = dt.zone.name;
1296
1296
  } else {
1297
- z61 = "UTC";
1297
+ z64 = "UTC";
1298
1298
  this.dt = dt.setZone("UTC").plus({ minutes: dt.offset });
1299
1299
  this.originalZone = dt.zone;
1300
1300
  }
1301
1301
  const intlOpts = __spreadValues({}, this.opts);
1302
- intlOpts.timeZone = intlOpts.timeZone || z61;
1302
+ intlOpts.timeZone = intlOpts.timeZone || z64;
1303
1303
  this.dtf = getCachedDTF(intl, intlOpts);
1304
1304
  }
1305
1305
  format() {
@@ -7033,6 +7033,22 @@ zod.z.object({
7033
7033
  zod.z.object({
7034
7034
  noteId: zod.z.number().int().positive()
7035
7035
  });
7036
+ var ASSET_TAGS = {
7037
+ ENFORCEMENT_EXHAUSTED: {
7038
+ label: "Enforcement Exhausted",
7039
+ description: "All available enforcement options have been pursued with the relevant providers. The asset remains active due to provider inaction.",
7040
+ colorScheme: "orange"
7041
+ }
7042
+ };
7043
+ var ASSET_TAG_KEYS = Object.keys(ASSET_TAGS);
7044
+ var assetTagKeySchema = zod.z.enum(ASSET_TAG_KEYS);
7045
+ zod.z.object({
7046
+ assetId: zod.z.number().int().positive()
7047
+ });
7048
+ zod.z.object({
7049
+ assetId: zod.z.number().int().positive(),
7050
+ tag: assetTagKeySchema
7051
+ });
7036
7052
  zod.z.object({
7037
7053
  slug: zod.z.string(),
7038
7054
  assetId: zod.z.number(),
@@ -7192,7 +7208,9 @@ var AssetType = {
7192
7208
  FIVE_HUNDRED_PX: "FIVE_HUNDRED_PX",
7193
7209
  LUMA: "LUMA",
7194
7210
  SMARTMONEYMATCH: "SMARTMONEYMATCH",
7195
- APK_GOLD: "APK_GOLD"
7211
+ APK_GOLD: "APK_GOLD",
7212
+ GLASSDOOR: "GLASSDOOR",
7213
+ PUMP_FUN: "PUMP_FUN"
7196
7214
  };
7197
7215
  var LivenessStatus = {
7198
7216
  UNKNOWN: "UNKNOWN",
@@ -7353,8 +7371,23 @@ zod.z.object({
7353
7371
  watchStatus: zod.z.nativeEnum(WatchStatus).optional().describe("The watch status of the asset.")
7354
7372
  }).describe("Check asset response body");
7355
7373
  var assetListInputSchema = zod.z.object({
7356
- /** The type of asset to retrieve. */
7357
- type: zod.z.nativeEnum(AssetType).describe("Asset type"),
7374
+ /**
7375
+ * The type of asset to retrieve. Omitting the key means every asset type,
7376
+ * which lets a bulk consumer sweep the whole blocklist with one cursor
7377
+ * instead of looping all 94 members of `AssetType`.
7378
+ *
7379
+ * An explicit `null` is rejected with a 400 rather than treated as "all
7380
+ * types". Only omission opts into the full sweep, so a client that sends
7381
+ * `type: null` from an uninitialised variable gets a clear error instead of
7382
+ * silently pulling every blocked asset.
7383
+ *
7384
+ * Not `.nullable()`: besides accepting that null, it renders in the
7385
+ * generated MCP tool manifest as a nested `anyOf` containing `{"not": {}}`,
7386
+ * which buries the enum hint telling a model which values are legal.
7387
+ */
7388
+ type: zod.z.nativeEnum(AssetType).optional().describe(
7389
+ "Asset type to retrieve. Omit the field entirely to retrieve assets of every type in a single paginated sweep; an explicit null is rejected."
7390
+ ),
7358
7391
  /** Optional status filter for the assets; defaults to `BLOCKED`. */
7359
7392
  status: zod.z.nativeEnum(AssetStatus).optional().default(AssetStatus.BLOCKED).describe("Status of the assets to retrieve"),
7360
7393
  /**
@@ -7382,7 +7415,8 @@ var assetListInputSchema = zod.z.object({
7382
7415
  }).describe(
7383
7416
  `List asset request body
7384
7417
 
7385
- Defaults to getting all the updates in the last 1 day.
7418
+ With no \`startDate\`, this returns every matching asset regardless of age \u2014 there
7419
+ is no implicit one-day window. Pass \`startDate\` to get a delta instead.
7386
7420
 
7387
7421
  You can also choose a \`startDate\` and \`endDate\` for the range of asset updates, most
7388
7422
  timestamp formats should work, we use [Luxon](https://moment.github.io/luxon/#/parsing)
@@ -7491,6 +7525,8 @@ var ThreatDetectionSourceKey = /* @__PURE__ */ ((ThreatDetectionSourceKey2) => {
7491
7525
  ThreatDetectionSourceKey2["TELEGRAM_CHANNELS_SEARCH_VETRIC"] = "telegram_channels_search_vetric";
7492
7526
  ThreatDetectionSourceKey2["TELEGRAM_USER_SEARCH_VETRIC"] = "telegram_user_search_vetric";
7493
7527
  ThreatDetectionSourceKey2["FACEBOOK_PAGE_SEARCH_VETRIC"] = "facebook_page_search_vetric";
7528
+ ThreatDetectionSourceKey2["FACEBOOK_USER_SEARCH_VETRIC"] = "facebook_user_search_vetric";
7529
+ ThreatDetectionSourceKey2["FACEBOOK_POST_SEARCH_VETRIC"] = "facebook_post_search_vetric";
7494
7530
  ThreatDetectionSourceKey2["INSTAGRAM_ACCOUNT_SEARCH_VETRIC"] = "instagram_account_search_vetric";
7495
7531
  ThreatDetectionSourceKey2["TWITTER_SEARCH_VETRIC"] = "twitter_search_vetric";
7496
7532
  ThreatDetectionSourceKey2["LINKEDIN_PEOPLE_SEARCH_VETRIC"] = "linkedin_people_search_vetric";
@@ -7530,14 +7566,17 @@ var ThreatDetectionSourceKey = /* @__PURE__ */ ((ThreatDetectionSourceKey2) => {
7530
7566
  ThreatDetectionSourceKey2["GROK_USER_SEARCH"] = "grok_user_search";
7531
7567
  ThreatDetectionSourceKey2["GOOGLE_LENS_IMAGE_SEARCH"] = "google_lens_image_search";
7532
7568
  ThreatDetectionSourceKey2["YANDEX_SEARCH"] = "yandex_search";
7569
+ ThreatDetectionSourceKey2["YANDEX_IMAGE_SEARCH"] = "yandex_image_search";
7533
7570
  ThreatDetectionSourceKey2["LINKEDIN_EMPLOYEE_DETECTION"] = "linkedin_employee_detection";
7534
7571
  ThreatDetectionSourceKey2["LINKEDIN_POST_SEARCH"] = "linkedin_post_search";
7535
7572
  ThreatDetectionSourceKey2["LINKEDIN_COMPANY_SEARCH"] = "linkedin_company_search";
7536
7573
  ThreatDetectionSourceKey2["BING_ADS_SEARCH"] = "bing_ads_search";
7537
7574
  ThreatDetectionSourceKey2["TIK_TOK_ADS_SEARCH"] = "tik_tok_ads_search";
7575
+ ThreatDetectionSourceKey2["ADLIBRARY_ADS_SEARCH"] = "adlibrary_ads_search";
7538
7576
  ThreatDetectionSourceKey2["DNSDB"] = "dnsdb";
7539
7577
  ThreatDetectionSourceKey2["DAILY_MOTION_SEARCH"] = "daily_motion_search";
7540
7578
  ThreatDetectionSourceKey2["WATCHLIST"] = "watchlist";
7579
+ ThreatDetectionSourceKey2["GITHUB_SEARCH"] = "github_search";
7541
7580
  return ThreatDetectionSourceKey2;
7542
7581
  })(ThreatDetectionSourceKey || {});
7543
7582
  var ThreatDetectionScope = /* @__PURE__ */ ((ThreatDetectionScope2) => {
@@ -7563,6 +7602,7 @@ var AssetScanEnrichmentType = /* @__PURE__ */ ((AssetScanEnrichmentType2) => {
7563
7602
  AssetScanEnrichmentType2["DNS"] = "dns";
7564
7603
  AssetScanEnrichmentType2["TLS"] = "tls";
7565
7604
  AssetScanEnrichmentType2["TCP"] = "tcp";
7605
+ AssetScanEnrichmentType2["HOSTNAME_FIRST_SEEN"] = "hostname_first_seen";
7566
7606
  AssetScanEnrichmentType2["TWITTER_POST"] = "post";
7567
7607
  AssetScanEnrichmentType2["TWITTER_PROFILE"] = "profile";
7568
7608
  AssetScanEnrichmentType2["TWITTER_FOLLOWERS"] = "twitter_followers";
@@ -7588,12 +7628,17 @@ var AssetScanEnrichmentType = /* @__PURE__ */ ((AssetScanEnrichmentType2) => {
7588
7628
  AssetScanEnrichmentType2["VIMEO_PROFILE"] = "vimeo_profile";
7589
7629
  AssetScanEnrichmentType2["STACKBLITZ_PAGE"] = "stackblitz_page";
7590
7630
  AssetScanEnrichmentType2["LEETCODE_PAGE"] = "leetcode_page";
7631
+ AssetScanEnrichmentType2["TUMBLR_BLOG"] = "tumblr_blog";
7632
+ AssetScanEnrichmentType2["TUMBLR_POST"] = "tumblr_post";
7633
+ AssetScanEnrichmentType2["TUMBLR_COMMUNITY"] = "tumblr_community";
7591
7634
  AssetScanEnrichmentType2["NPM_PACKAGE"] = "npm_package";
7592
7635
  AssetScanEnrichmentType2["PYPI_PACKAGE"] = "pypi_package";
7593
7636
  AssetScanEnrichmentType2["RUST_PACKAGE"] = "rust_package";
7594
7637
  AssetScanEnrichmentType2["LINKEDIN_PROFILE"] = "linkedin_profile";
7638
+ AssetScanEnrichmentType2["PUMP_FUN_TOKEN"] = "pump_fun_token";
7595
7639
  AssetScanEnrichmentType2["META_AD"] = "meta_ad";
7596
7640
  AssetScanEnrichmentType2["GOOGLE_AD"] = "google_ad";
7641
+ AssetScanEnrichmentType2["ADLIBRARY_AD"] = "adlibrary_ad";
7597
7642
  AssetScanEnrichmentType2["CONTRACT_DEPLOYER"] = "contract_deployer";
7598
7643
  return AssetScanEnrichmentType2;
7599
7644
  })(AssetScanEnrichmentType || {});
@@ -7605,6 +7650,8 @@ var AssetScanEnrichmentSource = /* @__PURE__ */ ((AssetScanEnrichmentSource2) =>
7605
7650
  AssetScanEnrichmentSource2["NETWORK"] = "node_js_network";
7606
7651
  AssetScanEnrichmentSource2["EXTENSION"] = "extension";
7607
7652
  AssetScanEnrichmentSource2["PLAYWRIGHT"] = "playwright";
7653
+ AssetScanEnrichmentSource2["CHAINPATROL_BROWSER"] = "chainpatrol_browser";
7654
+ AssetScanEnrichmentSource2["STEEL_BROWSER"] = "steel_browser";
7608
7655
  AssetScanEnrichmentSource2["X_API"] = "x_api";
7609
7656
  AssetScanEnrichmentSource2["SOCIALDATA_API"] = "socialdata_api";
7610
7657
  AssetScanEnrichmentSource2["NEYNAR_API"] = "neynar_api";
@@ -7623,12 +7670,16 @@ var AssetScanEnrichmentSource = /* @__PURE__ */ ((AssetScanEnrichmentSource2) =>
7623
7670
  AssetScanEnrichmentSource2["VIMEO_API"] = "vimeo_api";
7624
7671
  AssetScanEnrichmentSource2["STACKBLITZ_API"] = "stackblitz_api";
7625
7672
  AssetScanEnrichmentSource2["LEETCODE_API"] = "leetcode_api";
7673
+ AssetScanEnrichmentSource2["TUMBLR_API"] = "tumblr_api";
7626
7674
  AssetScanEnrichmentSource2["NPM_REGISTRY_API"] = "npm_registry_api";
7627
7675
  AssetScanEnrichmentSource2["PYPI_REGISTRY_API"] = "pypi_registry_api";
7628
7676
  AssetScanEnrichmentSource2["CRATES_IO_API"] = "crates_io_api";
7629
7677
  AssetScanEnrichmentSource2["APIFY_LINKEDIN_API"] = "apify_linkedin_api";
7678
+ AssetScanEnrichmentSource2["PUMP_FUN_API"] = "pump_fun_api";
7630
7679
  AssetScanEnrichmentSource2["META_ADS_LIBRARY"] = "meta_ads_library";
7680
+ AssetScanEnrichmentSource2["STEEL_META_ADS_LIBRARY"] = "steel_meta_ads_library";
7631
7681
  AssetScanEnrichmentSource2["GOOGLE_ADS_TRANSPARENCY_CENTER"] = "google_ads_transparency_center";
7682
+ AssetScanEnrichmentSource2["ADLIBRARY"] = "adlibrary";
7632
7683
  AssetScanEnrichmentSource2["ETHERSCAN_API"] = "etherscan_api";
7633
7684
  return AssetScanEnrichmentSource2;
7634
7685
  })(AssetScanEnrichmentSource || {});
@@ -7643,6 +7694,7 @@ var ASSET_SCAN_ENRICHMENT_TYPE_LABELS = {
7643
7694
  ["dns" /* DNS */]: "DNS Lookup",
7644
7695
  ["tls" /* TLS */]: "TLS Connection Info",
7645
7696
  ["tcp" /* TCP */]: "TCP Connection Info",
7697
+ ["hostname_first_seen" /* HOSTNAME_FIRST_SEEN */]: "Hostname First Seen",
7646
7698
  // Farcaster
7647
7699
  ["cast" /* FARCASTER_CAST */]: "Farcaster Cast",
7648
7700
  ["farcaster_profile" /* FARCASTER_PROFILE */]: "Farcaster Profile",
@@ -7681,6 +7733,10 @@ var ASSET_SCAN_ENRICHMENT_TYPE_LABELS = {
7681
7733
  ["stackblitz_page" /* STACKBLITZ_PAGE */]: "Stackblitz Page",
7682
7734
  // Leetcode
7683
7735
  ["leetcode_page" /* LEETCODE_PAGE */]: "Leetcode Page",
7736
+ // Tumblr
7737
+ ["tumblr_blog" /* TUMBLR_BLOG */]: "Tumblr Blog",
7738
+ ["tumblr_post" /* TUMBLR_POST */]: "Tumblr Post",
7739
+ ["tumblr_community" /* TUMBLR_COMMUNITY */]: "Tumblr Community",
7684
7740
  // NPM
7685
7741
  ["npm_package" /* NPM_PACKAGE */]: "NPM Package",
7686
7742
  // PyPI
@@ -7689,10 +7745,14 @@ var ASSET_SCAN_ENRICHMENT_TYPE_LABELS = {
7689
7745
  ["rust_package" /* RUST_PACKAGE */]: "Rust Package",
7690
7746
  // LinkedIn
7691
7747
  ["linkedin_profile" /* LINKEDIN_PROFILE */]: "LinkedIn Profile",
7748
+ // Pump.fun
7749
+ ["pump_fun_token" /* PUMP_FUN_TOKEN */]: "Pump.fun Token",
7692
7750
  // Meta Ads
7693
7751
  ["meta_ad" /* META_AD */]: "Meta Ad",
7694
7752
  // Google Ads
7695
7753
  ["google_ad" /* GOOGLE_AD */]: "Google Ad",
7754
+ // Cross-platform ad intelligence
7755
+ ["adlibrary_ad" /* ADLIBRARY_AD */]: "AdLibrary Ad",
7696
7756
  // Crypto / Onchain
7697
7757
  ["contract_deployer" /* CONTRACT_DEPLOYER */]: "Contract Deployer"
7698
7758
  };
@@ -7705,6 +7765,8 @@ var ASSET_SCAN_ENRICHMENT_SOURCE_LABELS = {
7705
7765
  ["node_js_network" /* NETWORK */]: "Network",
7706
7766
  ["extension" /* EXTENSION */]: "Browser Extension",
7707
7767
  ["playwright" /* PLAYWRIGHT */]: "Playwright",
7768
+ ["chainpatrol_browser" /* CHAINPATROL_BROWSER */]: "ChainPatrol Browser",
7769
+ ["steel_browser" /* STEEL_BROWSER */]: "Steel Browser",
7708
7770
  // Twitter
7709
7771
  ["x_api" /* X_API */]: "X API",
7710
7772
  ["socialdata_api" /* SOCIALDATA_API */]: "SocialData API",
@@ -7739,6 +7801,8 @@ var ASSET_SCAN_ENRICHMENT_SOURCE_LABELS = {
7739
7801
  ["stackblitz_api" /* STACKBLITZ_API */]: "Stackblitz API",
7740
7802
  // Leetcode
7741
7803
  ["leetcode_api" /* LEETCODE_API */]: "Leetcode API",
7804
+ // Tumblr
7805
+ ["tumblr_api" /* TUMBLR_API */]: "Tumblr API",
7742
7806
  // NPM
7743
7807
  ["npm_registry_api" /* NPM_REGISTRY_API */]: "NPM Registry API",
7744
7808
  // PyPI
@@ -7747,10 +7811,15 @@ var ASSET_SCAN_ENRICHMENT_SOURCE_LABELS = {
7747
7811
  ["crates_io_api" /* CRATES_IO_API */]: "Crates.io API",
7748
7812
  // LinkedIn
7749
7813
  ["apify_linkedin_api" /* APIFY_LINKEDIN_API */]: "Apify LinkedIn API",
7814
+ // Pump.fun
7815
+ ["pump_fun_api" /* PUMP_FUN_API */]: "Pump.fun API",
7750
7816
  // Meta Ads
7751
7817
  ["meta_ads_library" /* META_ADS_LIBRARY */]: "Meta Ads Library",
7818
+ ["steel_meta_ads_library" /* STEEL_META_ADS_LIBRARY */]: "Steel Meta Ads Library",
7752
7819
  // Google Ads
7753
7820
  ["google_ads_transparency_center" /* GOOGLE_ADS_TRANSPARENCY_CENTER */]: "Google Ads Transparency Center",
7821
+ // Cross-platform ad intelligence
7822
+ ["adlibrary" /* ADLIBRARY */]: "AdLibrary",
7754
7823
  // Crypto / Onchain
7755
7824
  ["etherscan_api" /* ETHERSCAN_API */]: "Etherscan"
7756
7825
  };
@@ -7758,7 +7827,8 @@ var ASSET_SCAN_ENRICHMENT_SOURCE_TO_TYPES = {
7758
7827
  // URL-related sources
7759
7828
  ["urlscan" /* URLSCAN */]: [
7760
7829
  "browser_capture" /* BROWSER_CAPTURE */,
7761
- "geolocation_and_ip" /* GEOLOCATION_AND_IP */
7830
+ "geolocation_and_ip" /* GEOLOCATION_AND_IP */,
7831
+ "hostname_first_seen" /* HOSTNAME_FIRST_SEEN */
7762
7832
  ],
7763
7833
  ["whois" /* WHOIS */]: ["ownership_and_registration" /* OWNERSHIP_AND_REGISTRATION */],
7764
7834
  ["rdap" /* RDAP */]: ["ownership_and_registration" /* OWNERSHIP_AND_REGISTRATION */],
@@ -7783,6 +7853,12 @@ var ASSET_SCAN_ENRICHMENT_SOURCE_TO_TYPES = {
7783
7853
  "bilibili_profile" /* BILIBILI_PROFILE */,
7784
7854
  "telegram_profile" /* TELEGRAM_PROFILE */
7785
7855
  ],
7856
+ // Only the generic page capture: the in-house browser does not (yet) run the
7857
+ // platform-specific scrapes PLAYWRIGHT does above.
7858
+ ["chainpatrol_browser" /* CHAINPATROL_BROWSER */]: [
7859
+ "browser_capture" /* BROWSER_CAPTURE */
7860
+ ],
7861
+ ["steel_browser" /* STEEL_BROWSER */]: ["browser_capture" /* BROWSER_CAPTURE */],
7786
7862
  // Twitter-related sources
7787
7863
  ["x_api" /* X_API */]: [
7788
7864
  "post" /* TWITTER_POST */,
@@ -7842,6 +7918,12 @@ var ASSET_SCAN_ENRICHMENT_SOURCE_TO_TYPES = {
7842
7918
  ["stackblitz_api" /* STACKBLITZ_API */]: ["stackblitz_page" /* STACKBLITZ_PAGE */],
7843
7919
  // Leetcode-related sources
7844
7920
  ["leetcode_api" /* LEETCODE_API */]: ["leetcode_page" /* LEETCODE_PAGE */],
7921
+ // Tumblr-related sources
7922
+ ["tumblr_api" /* TUMBLR_API */]: [
7923
+ "tumblr_blog" /* TUMBLR_BLOG */,
7924
+ "tumblr_post" /* TUMBLR_POST */,
7925
+ "tumblr_community" /* TUMBLR_COMMUNITY */
7926
+ ],
7845
7927
  // NPM-related sources
7846
7928
  ["npm_registry_api" /* NPM_REGISTRY_API */]: ["npm_package" /* NPM_PACKAGE */],
7847
7929
  // PyPI-related sources
@@ -7852,12 +7934,17 @@ var ASSET_SCAN_ENRICHMENT_SOURCE_TO_TYPES = {
7852
7934
  ["apify_linkedin_api" /* APIFY_LINKEDIN_API */]: [
7853
7935
  "linkedin_profile" /* LINKEDIN_PROFILE */
7854
7936
  ],
7937
+ // Pump.fun
7938
+ ["pump_fun_api" /* PUMP_FUN_API */]: ["pump_fun_token" /* PUMP_FUN_TOKEN */],
7855
7939
  // Meta Ads-related sources
7856
7940
  ["meta_ads_library" /* META_ADS_LIBRARY */]: ["meta_ad" /* META_AD */],
7941
+ ["steel_meta_ads_library" /* STEEL_META_ADS_LIBRARY */]: ["meta_ad" /* META_AD */],
7857
7942
  // Google Ads-related sources
7858
7943
  ["google_ads_transparency_center" /* GOOGLE_ADS_TRANSPARENCY_CENTER */]: [
7859
7944
  "google_ad" /* GOOGLE_AD */
7860
7945
  ],
7946
+ // Cross-platform ad intelligence sources
7947
+ ["adlibrary" /* ADLIBRARY */]: ["adlibrary_ad" /* ADLIBRARY_AD */],
7861
7948
  // Crypto / Onchain sources
7862
7949
  ["etherscan_api" /* ETHERSCAN_API */]: ["contract_deployer" /* CONTRACT_DEPLOYER */]
7863
7950
  };
@@ -8058,6 +8145,7 @@ function isDefinedAndNotNull(value) {
8058
8145
  // ../../internal/utils/src/promise.ts
8059
8146
  var promise_exports = {};
8060
8147
  __export(promise_exports, {
8148
+ allSettledWithConcurrency: () => allSettledWithConcurrency,
8061
8149
  isPromiseSettledResultFulfilled: () => isPromiseSettledResultFulfilled,
8062
8150
  isPromiseSettledResultRejected: () => isPromiseSettledResultRejected
8063
8151
  });
@@ -8067,6 +8155,27 @@ function isPromiseSettledResultFulfilled(result) {
8067
8155
  function isPromiseSettledResultRejected(result) {
8068
8156
  return result.status === "rejected";
8069
8157
  }
8158
+ function allSettledWithConcurrency(items, limit, fn5) {
8159
+ return __async(this, null, function* () {
8160
+ const results = new Array(items.length);
8161
+ let next = 0;
8162
+ const worker = () => __async(null, null, function* () {
8163
+ for (; ; ) {
8164
+ const index = next;
8165
+ next += 1;
8166
+ if (index >= items.length) return;
8167
+ try {
8168
+ results[index] = { status: "fulfilled", value: yield fn5(items[index], index) };
8169
+ } catch (reason) {
8170
+ results[index] = { status: "rejected", reason };
8171
+ }
8172
+ }
8173
+ });
8174
+ const workers = Math.max(1, Math.min(Math.floor(limit) || 1, items.length));
8175
+ yield Promise.all(Array.from({ length: workers }, worker));
8176
+ return results;
8177
+ });
8178
+ }
8070
8179
 
8071
8180
  // ../../internal/utils/src/url.ts
8072
8181
  var url_exports = {};
@@ -10821,6 +10930,7 @@ function buildSafePreviewUrl({
10821
10930
  var parse_exports = {};
10822
10931
  __export(parse_exports, {
10823
10932
  parseTerms: () => parseTerms,
10933
+ repairTermsString: () => repairTermsString,
10824
10934
  stringifyTerms: () => stringifyTerms
10825
10935
  });
10826
10936
  function parseTerms(terms, {
@@ -10847,6 +10957,31 @@ function parseTerms(terms, {
10847
10957
  function stringifyTerms(parsedTerms) {
10848
10958
  return parsedTerms.map((term) => term.type === "exact" ? `*${term.value}*` : term.value).join(", ");
10849
10959
  }
10960
+ function repairTermsString(terms) {
10961
+ if (!terms) return terms;
10962
+ const entries = terms.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
10963
+ if (entries.length === 0) return terms;
10964
+ const first = entries[0];
10965
+ const last = entries[entries.length - 1];
10966
+ const isWholeListWrap = entries.length > 1 && first.startsWith("*") && !first.endsWith("*") && last.endsWith("*") && !last.startsWith("*");
10967
+ const hasOneSidedAsterisk = entries.some(
10968
+ (entry) => entry.startsWith("*") !== entry.endsWith("*")
10969
+ );
10970
+ if (!isWholeListWrap && !hasOneSidedAsterisk) return terms;
10971
+ const seen = /* @__PURE__ */ new Set();
10972
+ const repaired = [];
10973
+ for (const entry of entries) {
10974
+ const inner = entry.replace(/^\*+|\*+$/g, "").trim();
10975
+ if (inner.length === 0) continue;
10976
+ const isExact = isWholeListWrap || entry.startsWith("*") && entry.endsWith("*") && entry.length > 2;
10977
+ const formatted = isExact ? `*${inner}*` : inner;
10978
+ const key = formatted.toLowerCase();
10979
+ if (seen.has(key)) continue;
10980
+ seen.add(key);
10981
+ repaired.push(formatted);
10982
+ }
10983
+ return repaired.join(", ");
10984
+ }
10850
10985
 
10851
10986
  // ../../internal/utils/src/brand-pattern.ts
10852
10987
  var brand_pattern_exports = {};
@@ -11492,6 +11627,44 @@ zod.z.object({
11492
11627
  })
11493
11628
  )
11494
11629
  });
11630
+ var DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
11631
+ var utcDateSchema = (endOfDay) => zod.z.preprocess((value) => {
11632
+ if (typeof value !== "string") {
11633
+ return value;
11634
+ }
11635
+ const parsed = DateTime.fromISO(value, { zone: "utc" });
11636
+ if (!parsed.isValid) {
11637
+ return new Date(Number.NaN);
11638
+ }
11639
+ return endOfDay && DATE_ONLY_PATTERN.test(value) ? parsed.endOf("day").toJSDate() : parsed.toJSDate();
11640
+ }, zod.z.coerce.date());
11641
+
11642
+ // ../../internal/validation/src/public/metrics/false-positive-rate.ts
11643
+ zod.z.object({
11644
+ slug: zod.z.string().min(1).describe("Organization slug"),
11645
+ startDate: utcDateSchema(false).optional().describe(
11646
+ "Only include assets blocked on or after this date. A date-only value (YYYY-MM-DD) starts at midnight UTC"
11647
+ ),
11648
+ endDate: utcDateSchema(true).optional().describe(
11649
+ "Only include assets blocked on or before this date. A date-only value (YYYY-MM-DD) covers the whole day in UTC; pass a full timestamp for a precise cut-off"
11650
+ ),
11651
+ brandIds: zod.z.array(zod.z.number().int().positive()).optional().describe("Only include assets belonging to these brands"),
11652
+ countryCodes: zod.z.array(zod.z.string().length(2)).optional().describe("Only include assets scanned from these ISO 3166-1 alpha-2 countries")
11653
+ });
11654
+ zod.z.object({
11655
+ byAssetType: zod.z.array(
11656
+ zod.z.object({
11657
+ assetType: zod.z.nativeEnum(AssetType).describe("Asset type that was blocked"),
11658
+ blocked: zod.z.number().describe("Assets of this type blocked within the date range"),
11659
+ falsePositives: zod.z.number().describe("Of those, how many are no longer blocked today"),
11660
+ falsePositiveRate: zod.z.number().nullable().describe(
11661
+ "falsePositives / blocked, 0-1. Null only when nothing was blocked, which cannot happen for a returned row"
11662
+ )
11663
+ })
11664
+ ).describe(
11665
+ "False positive rate, one entry per asset type blocked in the range, descending by number blocked. Asset types with no false positives are included with a rate of 0; asset types with no blocks at all in the range are omitted, since they have no rate to report. The denominator counts block events, not distinct assets, so an asset blocked twice in the range counts twice. Whether a block still stands is read as of now while the range bounds the block itself, so a recent range reads low. An asset's blocked status is global, so a block another organization's report caused to be reversed is counted here too"
11666
+ )
11667
+ });
11495
11668
  zod.z.object({
11496
11669
  slug: zod.z.string().min(1),
11497
11670
  startDate: zod.z.date(),
@@ -11506,8 +11679,8 @@ zod.z.object({
11506
11679
  endDate: zod.z.date()
11507
11680
  })
11508
11681
  });
11509
- var DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
11510
- var utcDateSchema = (endOfDay) => zod.z.preprocess((value) => {
11682
+ var DATE_ONLY_PATTERN2 = /^\d{4}-\d{2}-\d{2}$/;
11683
+ var utcDateSchema2 = (endOfDay) => zod.z.preprocess((value) => {
11511
11684
  if (typeof value !== "string") {
11512
11685
  return value;
11513
11686
  }
@@ -11515,7 +11688,7 @@ var utcDateSchema = (endOfDay) => zod.z.preprocess((value) => {
11515
11688
  if (!parsed.isValid) {
11516
11689
  return new Date(Number.NaN);
11517
11690
  }
11518
- return endOfDay && DATE_ONLY_PATTERN.test(value) ? parsed.endOf("day").toJSDate() : parsed.toJSDate();
11691
+ return endOfDay && DATE_ONLY_PATTERN2.test(value) ? parsed.endOf("day").toJSDate() : parsed.toJSDate();
11519
11692
  }, zod.z.coerce.date());
11520
11693
  var funnelCountsSchema = zod.z.object({
11521
11694
  blocked: zod.z.number().int().nonnegative().describe(
@@ -11524,10 +11697,10 @@ var funnelCountsSchema = zod.z.object({
11524
11697
  });
11525
11698
  zod.z.object({
11526
11699
  slug: zod.z.string().min(1).describe("Organization slug"),
11527
- startDate: utcDateSchema(false).describe(
11700
+ startDate: utcDateSchema2(false).describe(
11528
11701
  "Only include assets whose earliest report was created on or after this date. A date-only value (YYYY-MM-DD) starts at midnight UTC"
11529
11702
  ),
11530
- endDate: utcDateSchema(true).describe(
11703
+ endDate: utcDateSchema2(true).describe(
11531
11704
  "Only include assets whose earliest report was created on or before this date. A date-only value (YYYY-MM-DD) covers the whole day in UTC; pass a full timestamp for a precise cut-off"
11532
11705
  ),
11533
11706
  brandIds: zod.z.array(zod.z.number().int().positive()).optional().describe("Only include assets belonging to these brands")
@@ -11581,25 +11754,12 @@ zod.z.object({
11581
11754
  })
11582
11755
  )
11583
11756
  });
11584
- var DATE_ONLY_PATTERN2 = /^\d{4}-\d{2}-\d{2}$/;
11585
- var utcDateSchema2 = (endOfDay) => zod.z.preprocess((value) => {
11586
- if (typeof value !== "string") {
11587
- return value;
11588
- }
11589
- const parsed = DateTime.fromISO(value, { zone: "utc" });
11590
- if (!parsed.isValid) {
11591
- return new Date(Number.NaN);
11592
- }
11593
- return endOfDay && DATE_ONLY_PATTERN2.test(value) ? parsed.endOf("day").toJSDate() : parsed.toJSDate();
11594
- }, zod.z.coerce.date());
11595
-
11596
- // ../../internal/validation/src/public/metrics/takedown-success-rate.ts
11597
11757
  zod.z.object({
11598
11758
  slug: zod.z.string().min(1).describe("Organization slug"),
11599
- startDate: utcDateSchema2(false).optional().describe(
11759
+ startDate: utcDateSchema(false).optional().describe(
11600
11760
  "Only include takedowns first submitted to a provider on or after this date. A date-only value (YYYY-MM-DD) starts at midnight UTC"
11601
11761
  ),
11602
- endDate: utcDateSchema2(true).optional().describe(
11762
+ endDate: utcDateSchema(true).optional().describe(
11603
11763
  "Only include takedowns first submitted to a provider on or before this date. A date-only value (YYYY-MM-DD) covers the whole day in UTC; pass a full timestamp for a precise cut-off"
11604
11764
  ),
11605
11765
  blockLabel: zod.z.string().optional().describe(
@@ -11627,10 +11787,10 @@ zod.z.object({
11627
11787
  });
11628
11788
  zod.z.object({
11629
11789
  slug: zod.z.string().min(1).describe("Organization slug"),
11630
- startDate: utcDateSchema2(false).optional().describe(
11790
+ startDate: utcDateSchema(false).optional().describe(
11631
11791
  "Only include takedowns completed on or after this date. A date-only value (YYYY-MM-DD) starts at midnight UTC"
11632
11792
  ),
11633
- endDate: utcDateSchema2(true).optional().describe(
11793
+ endDate: utcDateSchema(true).optional().describe(
11634
11794
  "Only include takedowns completed on or before this date. A date-only value (YYYY-MM-DD) covers the whole day in UTC; pass a full timestamp for a precise cut-off"
11635
11795
  ),
11636
11796
  blockLabel: zod.z.string().optional().describe(
@@ -11660,10 +11820,10 @@ var TakedownProviderRoleSchema = zod.z.enum([
11660
11820
  ]);
11661
11821
  zod.z.object({
11662
11822
  slug: zod.z.string().min(1).describe("Organization slug"),
11663
- startDate: utcDateSchema2(false).optional().describe(
11823
+ startDate: utcDateSchema(false).optional().describe(
11664
11824
  "Only include takedowns completed on or after this date. A date-only value (YYYY-MM-DD) starts at midnight UTC"
11665
11825
  ),
11666
- endDate: utcDateSchema2(true).optional().describe(
11826
+ endDate: utcDateSchema(true).optional().describe(
11667
11827
  "Only include takedowns completed on or before this date. A date-only value (YYYY-MM-DD) covers the whole day in UTC; pass a full timestamp for a precise cut-off"
11668
11828
  ),
11669
11829
  roles: zod.z.array(TakedownProviderRoleSchema).optional().describe(
@@ -12299,8 +12459,10 @@ var reportCreateInputSchema = zod.z.object({
12299
12459
  ).optional().refine((value) => !value || !isPhoneNumberMissingCountryCode(value), {
12300
12460
  message: PHONE_COUNTRY_CODE_ERROR_MESSAGE
12301
12461
  }),
12302
- /** Optional list of URLs for images to be attached to the report. */
12303
- attachmentUrls: zod.z.array(zod.z.string().url()).optional().describe("URLs of images to attach to the report"),
12462
+ /** Optional list of URLs for files to be attached to the report as evidence. */
12463
+ attachmentUrls: zod.z.array(zod.z.string().url()).optional().describe(
12464
+ "URLs of files to attach to the report as evidence. Any file type, not only images: .eml/.msg messages, PDFs, and documents are all supported. Upload a file to POST /attachment/upload to get a URL, or pass a publicly reachable URL you host yourself."
12465
+ ),
12304
12466
  /** Optional link to the external submission (e.g. Telegram message link) */
12305
12467
  externalSubmissionLink: zod.z.string().url().optional().describe("Link to the external submission (e.g. Telegram message link)"),
12306
12468
  /** Optional user agent string from the reporter's browser */
@@ -12468,6 +12630,38 @@ for parsing the dates.`
12468
12630
  path: ["startDate"]
12469
12631
  }
12470
12632
  );
12633
+ var TakedownProofType = {
12634
+ ProviderEmail: "provider-email"
12635
+ };
12636
+ var takedownProofEmailSchema = zod.z.object({
12637
+ text: zod.z.string().describe(
12638
+ "The provider's reply, verbatim. Plain-text body where the provider sent one, otherwise the raw HTML body \u2014 treat it as untrusted content and escape it before rendering."
12639
+ ),
12640
+ subject: zod.z.string().nullable().describe("Subject line of the provider's reply.")
12641
+ }).nullable().describe(
12642
+ "Present when `type` is `provider-email`, `null` for every other proof type."
12643
+ );
12644
+ var takedownProofSchema = zod.z.object({
12645
+ type: zod.z.nativeEnum(TakedownProofType).describe(
12646
+ "Which kind of evidence this is. Currently only `provider-email`. New types may be added over time \u2014 read `type` before reading any of the type-specific objects below, and treat an unrecognised value as an opaque proof rather than an error."
12647
+ ),
12648
+ source: zod.z.string().nullable().describe(
12649
+ "Who confirmed the takedown, in whatever form that provider identifies itself \u2014 an address such as `abuse@example.com` for `provider-email`."
12650
+ ),
12651
+ confirmedAt: zod.z.date().describe("When the provider confirmed the takedown."),
12652
+ email: takedownProofEmailSchema
12653
+ });
12654
+ var takedownProofsSchema = zod.z.array(takedownProofSchema).describe(
12655
+ `Evidence that this takedown is ours: providers confirming they removed the asset, newest first.
12656
+
12657
+ A takedown filed at several providers can be confirmed by more than one of them, so this is a list. At most 5 are returned per takedown.
12658
+
12659
+ \`type\`, \`source\` and \`confirmedAt\` are present on every entry, so a caller that only needs to show "confirmed by X on date Y" never has to branch on the type. The type-specific object (\`email\`, and others as they are added) carries the underlying evidence.
12660
+
12661
+ Empty unless the takedown is COMPLETED and we hold a confirmation \u2014 which is the common case, because most providers either never reply or reply without confirming they acted. An empty list is not evidence that the asset is still up.
12662
+
12663
+ Requires the \`takedown-proof-api\` feature flag; without it this is always empty.`
12664
+ );
12471
12665
  var takedownItemSchema = zod.z.object({
12472
12666
  id: zod.z.number().describe("Takedown ID"),
12473
12667
  status: zod.z.nativeEnum(TakedownStatus).describe("Takedown status"),
@@ -12517,7 +12711,8 @@ var takedownItemSchema = zod.z.object({
12517
12711
  name: zod.z.string().describe("TLD registrar name (e.g. `Verisign`, `Public Interest Registry`)")
12518
12712
  }).nullable().describe(
12519
12713
  "Top-level-domain registrar assigned to this takedown. `null` when unresolved."
12520
- )
12714
+ ),
12715
+ proofs: takedownProofsSchema
12521
12716
  });
12522
12717
  zod.z.object({
12523
12718
  takedowns: zod.z.array(takedownItemSchema).describe("List of takedowns"),
@@ -12833,12 +13028,17 @@ var ONE_PAGER_BUDGETS = {
12833
13028
  headline: 60,
12834
13029
  badge: 28,
12835
13030
  frontLabel: 44,
12836
- paragraph: 480,
12837
13031
  paragraphsMax: 2,
12838
13032
  heroPhrase: 80,
12839
- heroNarrative: 300,
12840
- divergenceLine: 220,
12841
- xp01Line: 220
13033
+ landscapeCaption: 180,
13034
+ xp01Line: 220,
13035
+ screenshotCaption: 48,
13036
+ divergenceLine: 220
13037
+ };
13038
+ var ONE_PAGER_STORED_MAX = {
13039
+ paragraph: 480,
13040
+ paragraph2Lead: 60,
13041
+ heroNarrative: 300
12842
13042
  };
12843
13043
  var onePagerFactPayloadSchema = zod.z.object({
12844
13044
  /** Raw (not defanged) asset contents the prose may reference. */
@@ -12850,24 +13050,56 @@ var onePagerFactPayloadSchema = zod.z.object({
12850
13050
  platforms: zod.z.array(zod.z.string()),
12851
13051
  groupSize: zod.z.number(),
12852
13052
  takedownCompletedAt: zod.z.string().nullable(),
12853
- activeSince: zod.z.string().nullable()
13053
+ activeSince: zod.z.string().nullable(),
13054
+ // ---- v2 enrichment ----------------------------------------------------
13055
+ // Optional rather than defaulted so rows stored by v1 keep parsing AND the
13056
+ // inferred type stays assignable from a v1-shaped literal.
13057
+ /** How the attacker paid for the surface ("free_subdomain" | ...). */
13058
+ hostingPattern: zod.z.string().nullable().optional(),
13059
+ /** Who surfaced it first ("client_reported" | "proactive"). */
13060
+ sourceKind: zod.z.string().nullable().optional(),
13061
+ /** Prior blocked assets in the same relaunch family. */
13062
+ relaunchCount: zod.z.number().nullable().optional(),
13063
+ /** Earliest sighting, ISO. */
13064
+ firstSeenAt: zod.z.string().nullable().optional(),
13065
+ /**
13066
+ * Pre-computed hours from first sighting to confirmed removal, as a string
13067
+ * so it lands in the same allowlist as `numbers`. The model is forbidden
13068
+ * from doing arithmetic, so every duration it may cite is computed here.
13069
+ */
13070
+ timeToRemovalHrs: zod.z.string().nullable().optional()
12854
13071
  });
12855
13072
  var onePagerStorySchema = zod.z.object({
12856
13073
  archetypeId: zod.z.string(),
12857
13074
  archetypeCategory: zod.z.string(),
12858
13075
  /** 1-5 = placed on the page; null = alternate available for swap. */
12859
13076
  slot: zod.z.number().int().min(1).max(5).nullable(),
13077
+ /** Column layout the story occupies; slot 1 is full-width by convention. */
13078
+ layout: zod.z.enum(["full", "half"]).default("half"),
12860
13079
  frontLabel: zod.z.string().max(ONE_PAGER_BUDGETS.frontLabel),
12861
13080
  headline: zod.z.string().max(ONE_PAGER_BUDGETS.headline),
13081
+ /** Compound "10 of 10 removed · 3 hrs". */
12862
13082
  badge: zod.z.string().max(ONE_PAGER_BUDGETS.badge),
12863
- paragraphs: zod.z.array(zod.z.string().max(ONE_PAGER_BUDGETS.paragraph)).min(1).max(ONE_PAGER_BUDGETS.paragraphsMax),
13083
+ paragraphs: zod.z.array(zod.z.string().max(ONE_PAGER_STORED_MAX.paragraph)).min(1).max(ONE_PAGER_BUDGETS.paragraphsMax),
13084
+ /** Bold lead-in shown ahead of the second paragraph. */
13085
+ paragraph2Lead: zod.z.string().max(ONE_PAGER_STORED_MAX.paragraph2Lead).nullable().default(null),
12864
13086
  /** Defanged, display-ready asset identifiers. */
12865
- assetList: zod.z.array(zod.z.string()).max(10),
13087
+ assetList: zod.z.array(zod.z.string()).max(12),
13088
+ /** Story-bank identity for the referenced assets. */
13089
+ assetIds: zod.z.array(zod.z.number()).default([]),
12866
13090
  screenshotUrls: zod.z.array(zod.z.string()),
12867
13091
  selectedScreenshotUrls: zod.z.array(zod.z.string()).max(2),
13092
+ /** Parallel to selectedScreenshotUrls. */
13093
+ screenshotCaptions: zod.z.array(zod.z.string().max(ONE_PAGER_BUDGETS.screenshotCaption)).max(2).default([]),
13094
+ /** Manual redact toggle, parallel to selectedScreenshotUrls. */
13095
+ screenshotBlur: zod.z.array(zod.z.boolean()).max(2).default([]),
12868
13096
  xp01Line: zod.z.string().max(ONE_PAGER_BUDGETS.xp01Line).nullable(),
12869
13097
  factPayload: onePagerFactPayloadSchema,
12870
- proseSource: zod.z.enum(["llm", "template"])
13098
+ proseSource: zod.z.enum(["llm", "template"]),
13099
+ /** Cross-period continuation framing. */
13100
+ continuation: zod.z.boolean().default(false),
13101
+ /** Shown in the editor when this story overlaps with a prior period. */
13102
+ priorHeadline: zod.z.string().nullable().default(null)
12871
13103
  });
12872
13104
  var onePagerLandscapeRowSchema = zod.z.object({
12873
13105
  platform: zod.z.string(),
@@ -12878,25 +13110,55 @@ var onePagerFormDataObjectSchema = zod.z.object({
12878
13110
  orgName: zod.z.string(),
12879
13111
  orgSlug: zod.z.string(),
12880
13112
  periodLabel: zod.z.string(),
13113
+ partnershipLabel: zod.z.string().max(40).default("AN ONGOING PARTNERSHIP"),
13114
+ coverageWindow: zod.z.object({ start: zod.z.string(), end: zod.z.string(), label: zod.z.string(), short: zod.z.boolean() }).nullable().default(null),
12881
13115
  heroStat: zod.z.object({
12882
13116
  value: zod.z.string(),
12883
13117
  phrase: zod.z.string().max(ONE_PAGER_BUDGETS.heroPhrase)
12884
13118
  }),
12885
- heroNarrative: zod.z.string().max(ONE_PAGER_BUDGETS.heroNarrative),
12886
- metricsRows: zod.z.array(zod.z.object({ label: zod.z.string(), value: zod.z.string() })).length(4),
13119
+ heroNarrative: zod.z.string().max(ONE_PAGER_STORED_MAX.heroNarrative),
13120
+ /**
13121
+ * Up to 4 rows, but the metric library legitimately returns fewer on a thin
13122
+ * month (a zero-valued metric is excluded outright rather than rendered as
13123
+ * a "0" row), so this is a range, not a fixed length. Below 2 the block
13124
+ * reads as broken rather than short.
13125
+ */
13126
+ metricsRows: zod.z.array(
13127
+ zod.z.object({
13128
+ key: zod.z.string().default("legacy"),
13129
+ label: zod.z.string(),
13130
+ value: zod.z.string()
13131
+ })
13132
+ ).min(2).max(4),
12887
13133
  landscape: zod.z.object({
12888
13134
  rows: zod.z.array(onePagerLandscapeRowSchema).max(8),
12889
13135
  otherCount: zod.z.number().nullable(),
12890
13136
  otherPlatformsLabel: zod.z.string().nullable(),
12891
- divergenceLine: zod.z.string().max(ONE_PAGER_BUDGETS.divergenceLine).nullable()
13137
+ /** Kept for legacy row parse; caption is preferred going forward. */
13138
+ divergenceLine: zod.z.string().max(ONE_PAGER_BUDGETS.divergenceLine).nullable(),
13139
+ caption: zod.z.string().max(ONE_PAGER_BUDGETS.landscapeCaption).nullable().default(null)
12892
13140
  }),
12893
13141
  stories: zod.z.array(onePagerStorySchema).min(1).max(6),
12894
- footer: zod.z.object({ contactName: zod.z.string(), contactLine: zod.z.string() })
13142
+ footer: zod.z.object({
13143
+ contactName: zod.z.string(),
13144
+ contactLine: zod.z.string(),
13145
+ contactEmail: zod.z.string().default(""),
13146
+ bookingLink: zod.z.string().default(""),
13147
+ ctaLine: zod.z.string().default("Anything your community has flagged, send it over.")
13148
+ }),
13149
+ /** Engine v2 writes 2; absent/older rows default to 1. */
13150
+ schemaVersion: zod.z.number().default(1)
12895
13151
  });
12896
13152
  onePagerFormDataObjectSchema.refine(
12897
13153
  (data) => data.stories.some((s2) => s2.slot !== null),
12898
13154
  { message: "at least one story must be placed", path: ["stories"] }
12899
13155
  );
13156
+ var INTERNAL_ORG_SLUGS = [
13157
+ "chainpatrol",
13158
+ "chainpatrol-automation",
13159
+ "mountaintop"
13160
+ ];
13161
+ new Set(INTERNAL_ORG_SLUGS);
12900
13162
  zod.z.object({
12901
13163
  x: zod.z.number().min(0).max(1),
12902
13164
  y: zod.z.number().min(0).max(1),
@@ -13662,20 +13924,20 @@ var convertA98ToXyz65_default = convertA98ToXyz65;
13662
13924
 
13663
13925
  // ../../node_modules/culori/src/a98/convertXyz65ToA98.js
13664
13926
  var gamma = (v) => Math.pow(Math.abs(v), 256 / 563) * Math.sign(v);
13665
- var convertXyz65ToA98 = ({ x, y, z: z61, alpha }) => {
13927
+ var convertXyz65ToA98 = ({ x, y, z: z64, alpha }) => {
13666
13928
  if (x === void 0) x = 0;
13667
13929
  if (y === void 0) y = 0;
13668
- if (z61 === void 0) z61 = 0;
13930
+ if (z64 === void 0) z64 = 0;
13669
13931
  let res = {
13670
13932
  mode: "a98",
13671
13933
  r: gamma(
13672
- x * 2.0415879038107465 - y * 0.5650069742788597 - 0.3447313507783297 * z61
13934
+ x * 2.0415879038107465 - y * 0.5650069742788597 - 0.3447313507783297 * z64
13673
13935
  ),
13674
13936
  g: gamma(
13675
- x * -0.9692436362808798 + y * 1.8759675015077206 + 0.0415550574071756 * z61
13937
+ x * -0.9692436362808798 + y * 1.8759675015077206 + 0.0415550574071756 * z64
13676
13938
  ),
13677
13939
  b: gamma(
13678
- x * 0.0134442806320312 - y * 0.1183623922310184 + 1.0151749943912058 * z61
13940
+ x * 0.0134442806320312 - y * 0.1183623922310184 + 1.0151749943912058 * z64
13679
13941
  )
13680
13942
  };
13681
13943
  if (alpha !== void 0) {
@@ -13742,14 +14004,14 @@ var convertLrgbToRgb = ({ r, g, b, alpha }, mode = "rgb") => {
13742
14004
  var convertLrgbToRgb_default = convertLrgbToRgb;
13743
14005
 
13744
14006
  // ../../node_modules/culori/src/xyz65/convertXyz65ToRgb.js
13745
- var convertXyz65ToRgb = ({ x, y, z: z61, alpha }) => {
14007
+ var convertXyz65ToRgb = ({ x, y, z: z64, alpha }) => {
13746
14008
  if (x === void 0) x = 0;
13747
14009
  if (y === void 0) y = 0;
13748
- if (z61 === void 0) z61 = 0;
14010
+ if (z64 === void 0) z64 = 0;
13749
14011
  let res = convertLrgbToRgb_default({
13750
- r: x * 3.2409699419045226 - y * 1.537383177570094 - 0.4986107602930034 * z61,
13751
- g: x * -0.9692436362808796 + y * 1.8759675015077204 + 0.0415550574071756 * z61,
13752
- b: x * 0.0556300796969936 - y * 0.2039769588889765 + 1.0569715142428784 * z61
14012
+ r: x * 3.2409699419045226 - y * 1.537383177570094 - 0.4986107602930034 * z64,
14013
+ g: x * -0.9692436362808796 + y * 1.8759675015077204 + 0.0415550574071756 * z64,
14014
+ b: x * 0.0556300796969936 - y * 0.2039769588889765 + 1.0569715142428784 * z64
13753
14015
  });
13754
14016
  if (alpha !== void 0) {
13755
14017
  res.alpha = alpha;
@@ -13999,13 +14261,13 @@ var convertLab65ToRgb_default = convertLab65ToRgb;
13999
14261
 
14000
14262
  // ../../node_modules/culori/src/lab65/convertXyz65ToLab65.js
14001
14263
  var f = (value) => value > e ? Math.cbrt(value) : (k * value + 16) / 116;
14002
- var convertXyz65ToLab65 = ({ x, y, z: z61, alpha }) => {
14264
+ var convertXyz65ToLab65 = ({ x, y, z: z64, alpha }) => {
14003
14265
  if (x === void 0) x = 0;
14004
14266
  if (y === void 0) y = 0;
14005
- if (z61 === void 0) z61 = 0;
14267
+ if (z64 === void 0) z64 = 0;
14006
14268
  let f0 = f(x / D65.X);
14007
14269
  let f1 = f(y / D65.Y);
14008
- let f22 = f(z61 / D65.Z);
14270
+ let f22 = f(z64 / D65.Z);
14009
14271
  let res = {
14010
14272
  mode: "lab65",
14011
14273
  l: 116 * f1 - 16,
@@ -14662,10 +14924,10 @@ var convertItpToXyz65_default = convertItpToXyz65;
14662
14924
 
14663
14925
  // ../../node_modules/culori/src/itp/convertXyz65ToItp.js
14664
14926
  var toAbs = (c2 = 0) => Math.max(c2 * YW, 0);
14665
- var convertXyz65ToItp = ({ x, y, z: z61, alpha }) => {
14927
+ var convertXyz65ToItp = ({ x, y, z: z64, alpha }) => {
14666
14928
  const absX = toAbs(x);
14667
14929
  const absY = toAbs(y);
14668
- const absZ = toAbs(z61);
14930
+ const absZ = toAbs(z64);
14669
14931
  const l2 = transferPqEncode(
14670
14932
  0.3592832590121217 * absX + 0.6976051147779502 * absY - 0.0358915932320289 * absZ
14671
14933
  );
@@ -14723,15 +14985,15 @@ var jabPqEncode = (v) => {
14723
14985
  return Math.pow((C1 + C2 * vn3) / (1 + C3 * vn3), p);
14724
14986
  };
14725
14987
  var abs = (v = 0) => Math.max(v * 203, 0);
14726
- var convertXyz65ToJab = ({ x, y, z: z61, alpha }) => {
14988
+ var convertXyz65ToJab = ({ x, y, z: z64, alpha }) => {
14727
14989
  x = abs(x);
14728
14990
  y = abs(y);
14729
- z61 = abs(z61);
14730
- let xp = 1.15 * x - 0.15 * z61;
14991
+ z64 = abs(z64);
14992
+ let xp = 1.15 * x - 0.15 * z64;
14731
14993
  let yp = 0.66 * y + 0.34 * x;
14732
- let l2 = jabPqEncode(0.41478972 * xp + 0.579999 * yp + 0.014648 * z61);
14733
- let m = jabPqEncode(-0.20151 * xp + 1.120649 * yp + 0.0531008 * z61);
14734
- let s2 = jabPqEncode(-0.0166008 * xp + 0.2648 * yp + 0.6684799 * z61);
14994
+ let l2 = jabPqEncode(0.41478972 * xp + 0.579999 * yp + 0.014648 * z64);
14995
+ let m = jabPqEncode(-0.20151 * xp + 1.120649 * yp + 0.0531008 * z64);
14996
+ let s2 = jabPqEncode(-0.0166008 * xp + 0.2648 * yp + 0.6684799 * z64);
14735
14997
  let i = (l2 + m) / 2;
14736
14998
  let res = {
14737
14999
  mode: "jab",
@@ -14917,14 +15179,14 @@ var convertLabToXyz50 = ({ l: l2, a, b, alpha }) => {
14917
15179
  var convertLabToXyz50_default = convertLabToXyz50;
14918
15180
 
14919
15181
  // ../../node_modules/culori/src/xyz50/convertXyz50ToRgb.js
14920
- var convertXyz50ToRgb = ({ x, y, z: z61, alpha }) => {
15182
+ var convertXyz50ToRgb = ({ x, y, z: z64, alpha }) => {
14921
15183
  if (x === void 0) x = 0;
14922
15184
  if (y === void 0) y = 0;
14923
- if (z61 === void 0) z61 = 0;
15185
+ if (z64 === void 0) z64 = 0;
14924
15186
  let res = convertLrgbToRgb_default({
14925
- r: x * 3.1341359569958707 - y * 1.6173863321612538 - 0.4906619460083532 * z61,
14926
- g: x * -0.978795502912089 + y * 1.916254567259524 + 0.03344273116131949 * z61,
14927
- b: x * 0.07195537988411677 - y * 0.2289768264158322 + 1.405386058324125 * z61
15187
+ r: x * 3.1341359569958707 - y * 1.6173863321612538 - 0.4906619460083532 * z64,
15188
+ g: x * -0.978795502912089 + y * 1.916254567259524 + 0.03344273116131949 * z64,
15189
+ b: x * 0.07195537988411677 - y * 0.2289768264158322 + 1.405386058324125 * z64
14928
15190
  });
14929
15191
  if (alpha !== void 0) {
14930
15192
  res.alpha = alpha;
@@ -14955,13 +15217,13 @@ var convertRgbToXyz50_default = convertRgbToXyz50;
14955
15217
 
14956
15218
  // ../../node_modules/culori/src/lab/convertXyz50ToLab.js
14957
15219
  var f2 = (value) => value > e3 ? Math.cbrt(value) : (k3 * value + 16) / 116;
14958
- var convertXyz50ToLab = ({ x, y, z: z61, alpha }) => {
15220
+ var convertXyz50ToLab = ({ x, y, z: z64, alpha }) => {
14959
15221
  if (x === void 0) x = 0;
14960
15222
  if (y === void 0) y = 0;
14961
- if (z61 === void 0) z61 = 0;
15223
+ if (z64 === void 0) z64 = 0;
14962
15224
  let f0 = f2(x / D50.X);
14963
15225
  let f1 = f2(y / D50.Y);
14964
- let f22 = f2(z61 / D50.Z);
15226
+ let f22 = f2(z64 / D50.Z);
14965
15227
  let res = {
14966
15228
  mode: "lab",
14967
15229
  l: 116 * f1 - 16,
@@ -15196,18 +15458,18 @@ var convertLchuvToLuv = ({ l: l2, c: c2, h, alpha }) => {
15196
15458
  var convertLchuvToLuv_default = convertLchuvToLuv;
15197
15459
 
15198
15460
  // ../../node_modules/culori/src/luv/convertXyz50ToLuv.js
15199
- var u_fn = (x, y, z61) => 4 * x / (x + 15 * y + 3 * z61);
15200
- var v_fn = (x, y, z61) => 9 * y / (x + 15 * y + 3 * z61);
15461
+ var u_fn = (x, y, z64) => 4 * x / (x + 15 * y + 3 * z64);
15462
+ var v_fn = (x, y, z64) => 9 * y / (x + 15 * y + 3 * z64);
15201
15463
  var un = u_fn(D50.X, D50.Y, D50.Z);
15202
15464
  var vn = v_fn(D50.X, D50.Y, D50.Z);
15203
15465
  var l_fn = (value) => value <= e3 ? k3 * value : 116 * Math.cbrt(value) - 16;
15204
- var convertXyz50ToLuv = ({ x, y, z: z61, alpha }) => {
15466
+ var convertXyz50ToLuv = ({ x, y, z: z64, alpha }) => {
15205
15467
  if (x === void 0) x = 0;
15206
15468
  if (y === void 0) y = 0;
15207
- if (z61 === void 0) z61 = 0;
15469
+ if (z64 === void 0) z64 = 0;
15208
15470
  let l2 = l_fn(y / D50.Y);
15209
- let u = u_fn(x, y, z61);
15210
- let v = v_fn(x, y, z61);
15471
+ let u = u_fn(x, y, z64);
15472
+ let v = v_fn(x, y, z64);
15211
15473
  if (!isFinite(u) || !isFinite(v)) {
15212
15474
  l2 = u = v = 0;
15213
15475
  } else {
@@ -15228,8 +15490,8 @@ var convertXyz50ToLuv = ({ x, y, z: z61, alpha }) => {
15228
15490
  var convertXyz50ToLuv_default = convertXyz50ToLuv;
15229
15491
 
15230
15492
  // ../../node_modules/culori/src/luv/convertLuvToXyz50.js
15231
- var u_fn2 = (x, y, z61) => 4 * x / (x + 15 * y + 3 * z61);
15232
- var v_fn2 = (x, y, z61) => 9 * y / (x + 15 * y + 3 * z61);
15493
+ var u_fn2 = (x, y, z64) => 4 * x / (x + 15 * y + 3 * z64);
15494
+ var v_fn2 = (x, y, z64) => 9 * y / (x + 15 * y + 3 * z64);
15233
15495
  var un2 = u_fn2(D50.X, D50.Y, D50.Z);
15234
15496
  var vn2 = v_fn2(D50.X, D50.Y, D50.Z);
15235
15497
  var convertLuvToXyz50 = ({ l: l2, u, v, alpha }) => {
@@ -15243,8 +15505,8 @@ var convertLuvToXyz50 = ({ l: l2, u, v, alpha }) => {
15243
15505
  let vp = v / (13 * l2) + vn2;
15244
15506
  let y = D50.Y * (l2 <= 8 ? l2 / k3 : Math.pow((l2 + 16) / 116, 3));
15245
15507
  let x = y * (9 * up) / (4 * vp);
15246
- let z61 = y * (12 - 3 * up - 20 * vp) / (4 * vp);
15247
- let res = { mode: "xyz50", x, y, z: z61 };
15508
+ let z64 = y * (12 - 3 * up - 20 * vp) / (4 * vp);
15509
+ let res = { mode: "xyz50", x, y, z: z64 };
15248
15510
  if (alpha !== void 0) {
15249
15511
  res.alpha = alpha;
15250
15512
  }
@@ -15861,15 +16123,15 @@ var convertP3ToXyz65 = (rgb2) => {
15861
16123
  var convertP3ToXyz65_default = convertP3ToXyz65;
15862
16124
 
15863
16125
  // ../../node_modules/culori/src/p3/convertXyz65ToP3.js
15864
- var convertXyz65ToP3 = ({ x, y, z: z61, alpha }) => {
16126
+ var convertXyz65ToP3 = ({ x, y, z: z64, alpha }) => {
15865
16127
  if (x === void 0) x = 0;
15866
16128
  if (y === void 0) y = 0;
15867
- if (z61 === void 0) z61 = 0;
16129
+ if (z64 === void 0) z64 = 0;
15868
16130
  let res = convertLrgbToRgb_default(
15869
16131
  {
15870
- r: x * 2.4934969119414263 - y * 0.9313836179191242 - 0.402710784450717 * z61,
15871
- g: x * -0.8294889695615749 + y * 1.7626640603183465 + 0.0236246858419436 * z61,
15872
- b: x * 0.0358458302437845 - y * 0.0761723892680418 + 0.9568845240076871 * z61
16132
+ r: x * 2.4934969119414263 - y * 0.9313836179191242 - 0.402710784450717 * z64,
16133
+ g: x * -0.8294889695615749 + y * 1.7626640603183465 + 0.0236246858419436 * z64,
16134
+ b: x * 0.0358458302437845 - y * 0.0761723892680418 + 0.9568845240076871 * z64
15873
16135
  },
15874
16136
  "p3"
15875
16137
  );
@@ -15904,19 +16166,19 @@ var gamma2 = (v) => {
15904
16166
  }
15905
16167
  return 16 * v;
15906
16168
  };
15907
- var convertXyz50ToProphoto = ({ x, y, z: z61, alpha }) => {
16169
+ var convertXyz50ToProphoto = ({ x, y, z: z64, alpha }) => {
15908
16170
  if (x === void 0) x = 0;
15909
16171
  if (y === void 0) y = 0;
15910
- if (z61 === void 0) z61 = 0;
16172
+ if (z64 === void 0) z64 = 0;
15911
16173
  let res = {
15912
16174
  mode: "prophoto",
15913
16175
  r: gamma2(
15914
- x * 1.3457868816471585 - y * 0.2555720873797946 - 0.0511018649755453 * z61
16176
+ x * 1.3457868816471585 - y * 0.2555720873797946 - 0.0511018649755453 * z64
15915
16177
  ),
15916
16178
  g: gamma2(
15917
- x * -0.5446307051249019 + y * 1.5082477428451466 + 0.0205274474364214 * z61
16179
+ x * -0.5446307051249019 + y * 1.5082477428451466 + 0.0205274474364214 * z64
15918
16180
  ),
15919
- b: gamma2(x * 0 + y * 0 + 1.2119675456389452 * z61)
16181
+ b: gamma2(x * 0 + y * 0 + 1.2119675456389452 * z64)
15920
16182
  };
15921
16183
  if (alpha !== void 0) {
15922
16184
  res.alpha = alpha;
@@ -15976,20 +16238,20 @@ var gamma3 = (v) => {
15976
16238
  }
15977
16239
  return 4.5 * v;
15978
16240
  };
15979
- var convertXyz65ToRec2020 = ({ x, y, z: z61, alpha }) => {
16241
+ var convertXyz65ToRec2020 = ({ x, y, z: z64, alpha }) => {
15980
16242
  if (x === void 0) x = 0;
15981
16243
  if (y === void 0) y = 0;
15982
- if (z61 === void 0) z61 = 0;
16244
+ if (z64 === void 0) z64 = 0;
15983
16245
  let res = {
15984
16246
  mode: "rec2020",
15985
16247
  r: gamma3(
15986
- x * 1.7166511879712683 - y * 0.3556707837763925 - 0.2533662813736599 * z61
16248
+ x * 1.7166511879712683 - y * 0.3556707837763925 - 0.2533662813736599 * z64
15987
16249
  ),
15988
16250
  g: gamma3(
15989
- x * -0.6666843518324893 + y * 1.6164812366349395 + 0.0157685458139111 * z61
16251
+ x * -0.6666843518324893 + y * 1.6164812366349395 + 0.0157685458139111 * z64
15990
16252
  ),
15991
16253
  b: gamma3(
15992
- x * 0.0176398574453108 - y * 0.0427706132578085 + 0.9421031212354739 * z61
16254
+ x * 0.0176398574453108 - y * 0.0427706132578085 + 0.9421031212354739 * z64
15993
16255
  )
15994
16256
  };
15995
16257
  if (alpha !== void 0) {
@@ -16142,15 +16404,15 @@ var definition_default26 = definition26;
16142
16404
 
16143
16405
  // ../../node_modules/culori/src/xyz65/convertXyz65ToXyz50.js
16144
16406
  var convertXyz65ToXyz50 = (xyz652) => {
16145
- let { x, y, z: z61, alpha } = xyz652;
16407
+ let { x, y, z: z64, alpha } = xyz652;
16146
16408
  if (x === void 0) x = 0;
16147
16409
  if (y === void 0) y = 0;
16148
- if (z61 === void 0) z61 = 0;
16410
+ if (z64 === void 0) z64 = 0;
16149
16411
  let res = {
16150
16412
  mode: "xyz50",
16151
- x: 1.0479298208405488 * x + 0.0229467933410191 * y - 0.0501922295431356 * z61,
16152
- y: 0.0296278156881593 * x + 0.990434484573249 * y - 0.0170738250293851 * z61,
16153
- z: -0.0092430581525912 * x + 0.0150551448965779 * y + 0.7518742899580008 * z61
16413
+ x: 1.0479298208405488 * x + 0.0229467933410191 * y - 0.0501922295431356 * z64,
16414
+ y: 0.0296278156881593 * x + 0.990434484573249 * y - 0.0170738250293851 * z64,
16415
+ z: -0.0092430581525912 * x + 0.0150551448965779 * y + 0.7518742899580008 * z64
16154
16416
  };
16155
16417
  if (alpha !== void 0) {
16156
16418
  res.alpha = alpha;
@@ -16161,15 +16423,15 @@ var convertXyz65ToXyz50_default = convertXyz65ToXyz50;
16161
16423
 
16162
16424
  // ../../node_modules/culori/src/xyz65/convertXyz50ToXyz65.js
16163
16425
  var convertXyz50ToXyz65 = (xyz502) => {
16164
- let { x, y, z: z61, alpha } = xyz502;
16426
+ let { x, y, z: z64, alpha } = xyz502;
16165
16427
  if (x === void 0) x = 0;
16166
16428
  if (y === void 0) y = 0;
16167
- if (z61 === void 0) z61 = 0;
16429
+ if (z64 === void 0) z64 = 0;
16168
16430
  let res = {
16169
16431
  mode: "xyz65",
16170
- x: 0.9554734527042182 * x - 0.0230985368742614 * y + 0.0632593086610217 * z61,
16171
- y: -0.0283697069632081 * x + 1.0099954580058226 * y + 0.021041398966943 * z61,
16172
- z: 0.0123140016883199 * x - 0.0205076964334779 * y + 1.3303659366080753 * z61
16432
+ x: 0.9554734527042182 * x - 0.0230985368742614 * y + 0.0632593086610217 * z64,
16433
+ y: -0.0283697069632081 * x + 1.0099954580058226 * y + 0.021041398966943 * z64,
16434
+ z: 0.0123140016883199 * x - 0.0205076964334779 * y + 1.3303659366080753 * z64
16173
16435
  };
16174
16436
  if (alpha !== void 0) {
16175
16437
  res.alpha = alpha;
@@ -16406,6 +16668,13 @@ function validateTermsString(termsString) {
16406
16668
  };
16407
16669
  }
16408
16670
  } else {
16671
+ if (term.startsWith("*") || term.endsWith("*")) {
16672
+ const inner = term.replace(/^\*+|\*+$/g, "");
16673
+ return {
16674
+ valid: false,
16675
+ error: `Term "${term}" has an unmatched asterisk. Use *${inner}* for exact matching, or ${inner} for loose matching.`
16676
+ };
16677
+ }
16409
16678
  normalizedTerm = term.replace(/\s+/g, "");
16410
16679
  if (normalizedTerm.length < 6) {
16411
16680
  return {
@@ -17003,6 +17272,8 @@ var SCAN_TEMPLATES = [
17003
17272
  new Map(
17004
17273
  SCAN_TEMPLATES.map((template) => [template.id, template])
17005
17274
  );
17275
+ var DARK_WEB_ENTITY_SEARCH_KINDS = ["domain", "email", "crypto"];
17276
+ zod.z.enum(DARK_WEB_ENTITY_SEARCH_KINDS);
17006
17277
 
17007
17278
  // src/client.ts
17008
17279
  function trimTrailingSlashes(url) {