@chainpatrol/sdk 1.6.0 → 1.8.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.mjs CHANGED
@@ -1255,17 +1255,17 @@ var PolyDateFormatter = class {
1255
1255
  constructor(dt, intl, opts) {
1256
1256
  this.opts = opts;
1257
1257
  this.originalZone = void 0;
1258
- let z50 = void 0;
1258
+ let z55 = void 0;
1259
1259
  if (this.opts.timeZone) {
1260
1260
  this.dt = dt;
1261
1261
  } else if (dt.zone.type === "fixed") {
1262
1262
  const gmtOffset = -1 * (dt.offset / 60);
1263
1263
  const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`;
1264
1264
  if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) {
1265
- z50 = offsetZ;
1265
+ z55 = offsetZ;
1266
1266
  this.dt = dt;
1267
1267
  } else {
1268
- z50 = "UTC";
1268
+ z55 = "UTC";
1269
1269
  this.dt = dt.offset === 0 ? dt : dt.setZone("UTC").plus({ minutes: dt.offset });
1270
1270
  this.originalZone = dt.zone;
1271
1271
  }
@@ -1273,14 +1273,14 @@ var PolyDateFormatter = class {
1273
1273
  this.dt = dt;
1274
1274
  } else if (dt.zone.type === "iana") {
1275
1275
  this.dt = dt;
1276
- z50 = dt.zone.name;
1276
+ z55 = dt.zone.name;
1277
1277
  } else {
1278
- z50 = "UTC";
1278
+ z55 = "UTC";
1279
1279
  this.dt = dt.setZone("UTC").plus({ minutes: dt.offset });
1280
1280
  this.originalZone = dt.zone;
1281
1281
  }
1282
1282
  const intlOpts = __spreadValues({}, this.opts);
1283
- intlOpts.timeZone = intlOpts.timeZone || z50;
1283
+ intlOpts.timeZone = intlOpts.timeZone || z55;
1284
1284
  this.dtf = getCachedDTF(intl, intlOpts);
1285
1285
  }
1286
1286
  format() {
@@ -7406,868 +7406,78 @@ z.object({
7406
7406
  z.object({
7407
7407
  result: z.string()
7408
7408
  });
7409
- z.object({
7410
- slug: z.string().min(1),
7411
- configId: z.number().int().positive(),
7412
- status: z.nativeEnum(ThreatDetectionConfigStatus).optional(),
7413
- title: z.string().trim().optional(),
7414
- description: z.string().trim().nullable().optional(),
7415
- cron: z.string().trim().nullable().optional(),
7416
- config: z.record(z.unknown()).optional(),
7417
- mergeConfig: z.boolean().default(false),
7418
- brandId: z.number().int().positive().nullable().optional().describe(
7419
- "Optional brand connection for this detection config. Pass null to clear the link. Only valid for org-scoped configs; the brand must belong to the same organization."
7420
- )
7421
- });
7422
- z.object({
7423
- config: z.object({
7424
- id: z.number(),
7425
- source: z.string(),
7426
- status: z.nativeEnum(ThreatDetectionConfigStatus),
7427
- title: z.string(),
7428
- description: z.string().nullable(),
7429
- cron: z.string().nullable(),
7430
- config: z.record(z.unknown()),
7431
- updatedAt: z.date(),
7432
- brandId: z.number().nullable()
7433
- })
7434
- });
7435
- z.object({
7436
- slug: z.string().min(1),
7437
- source: z.string().optional(),
7438
- minResults: z.number().int().min(0).default(1),
7439
- lookbackHours: z.number().int().min(1).default(24 * 7),
7440
- runBeforeValidate: z.boolean().default(false),
7441
- includeDisabled: z.boolean().default(false)
7442
- });
7443
- z.object({
7444
- ok: z.boolean(),
7445
- summary: z.object({
7446
- checkedConfigs: z.number(),
7447
- passingConfigs: z.number(),
7448
- failingConfigs: z.number(),
7449
- lookbackHours: z.number(),
7450
- minResults: z.number()
7451
- }),
7452
- validations: z.array(
7453
- z.object({
7454
- configId: z.number(),
7455
- source: z.string(),
7456
- status: z.nativeEnum(ThreatDetectionConfigStatus),
7457
- ran: z.boolean(),
7458
- runOk: z.boolean(),
7459
- runMessage: z.string().nullable(),
7460
- recentResultCount: z.number(),
7461
- valid: z.boolean()
7462
- })
7463
- )
7464
- });
7465
- z.object({
7466
- slug: z.string().min(1),
7467
- configId: z.number().int().positive().optional(),
7468
- source: z.string().min(1).optional(),
7469
- includeDisabled: z.boolean().default(false)
7470
- });
7471
- z.object({
7472
- ranCount: z.number(),
7473
- successCount: z.number(),
7474
- failedCount: z.number(),
7475
- results: z.array(
7476
- z.object({
7477
- configId: z.number(),
7478
- source: z.string(),
7479
- ok: z.boolean(),
7480
- message: z.string().nullable(),
7481
- assetsCount: z.number()
7482
- })
7483
- )
7484
- });
7485
- var DetectionDriftThresholdsSchema = z.object({
7486
- zeroResultsMaxHours: z.number().int().positive().default(72),
7487
- noisyResultsPerDay: z.number().positive().default(100),
7488
- noisyAllowedRatioThreshold: z.number().min(0).max(1).default(0.6),
7489
- staleConfigDays: z.number().int().positive().default(30)
7490
- });
7491
- z.object({
7492
- slug: z.string().min(1),
7493
- lookbackHours: z.number().int().positive().default(168),
7494
- startDate: z.date().optional(),
7495
- endDate: z.date().optional(),
7496
- source: z.string().min(1).optional(),
7497
- configIds: z.array(z.number().int().positive()).optional(),
7498
- includeDisabled: z.boolean().default(false),
7499
- thresholds: DetectionDriftThresholdsSchema.optional()
7500
- }).refine(
7501
- (value) => !value.startDate && !value.endDate || Boolean(value.startDate) && Boolean(value.endDate),
7502
- {
7503
- message: "Provide both startDate and endDate when using explicit date range",
7504
- path: ["startDate"]
7505
- }
7506
- );
7507
- var DetectionDriftSignalSchema = z.object({
7508
- signal: z.enum(["zero_results_too_long", "noisy_source", "stale_query"]),
7509
- configId: z.number().int().positive(),
7510
- source: z.string(),
7511
- title: z.string().nullable(),
7512
- status: z.string(),
7513
- severity: z.enum(["low", "medium", "high"]),
7514
- details: z.record(z.unknown())
7515
- });
7516
- z.object({
7517
- ok: z.boolean(),
7518
- range: z.object({
7519
- startDate: z.date(),
7520
- endDate: z.date(),
7521
- lookbackHours: z.number().int().positive()
7522
- }),
7523
- thresholds: DetectionDriftThresholdsSchema,
7524
- summary: z.object({
7525
- checkedConfigs: z.number().int().nonnegative(),
7526
- signalCount: z.number().int().nonnegative(),
7527
- zeroResultsCount: z.number().int().nonnegative(),
7528
- noisyCount: z.number().int().nonnegative(),
7529
- staleCount: z.number().int().nonnegative()
7530
- }),
7531
- signals: z.array(DetectionDriftSignalSchema)
7532
- });
7533
- var BucketsSchema = z.object({
7534
- lt24h: z.number().int().nonnegative(),
7535
- h24to72: z.number().int().nonnegative(),
7536
- h72to168: z.number().int().nonnegative(),
7537
- gte168h: z.number().int().nonnegative()
7538
- });
7539
- z.object({
7540
- slug: z.string().min(1).optional(),
7541
- all: z.boolean().default(false),
7542
- windowHours: z.number().int().positive().default(168)
7543
- });
7544
- z.object({
7545
- generatedAt: z.date(),
7546
- scope: z.object({
7547
- slug: z.string().nullable(),
7548
- all: z.boolean()
7549
- }),
7550
- reviewQueue: z.object({
7551
- totalPendingProposals: z.number().int().nonnegative(),
7552
- distinctReports: z.number().int().nonnegative(),
7553
- ageBuckets: BucketsSchema,
7554
- slaBuckets: z.object({
7555
- breached: z.number().int().nonnegative(),
7556
- dueWithin24h: z.number().int().nonnegative(),
7557
- dueWithin72h: z.number().int().nonnegative(),
7558
- beyond72h: z.number().int().nonnegative(),
7559
- missingSla: z.number().int().nonnegative()
7560
- }),
7561
- byOrg: z.array(
7562
- z.object({
7563
- slug: z.string(),
7564
- pendingProposals: z.number().int().nonnegative()
7565
- })
7566
- )
7567
- }),
7568
- takedownQueue: z.object({
7569
- totalOpen: z.number().int().nonnegative(),
7570
- statusCounts: z.object({
7571
- todo: z.number().int().nonnegative(),
7572
- inProgress: z.number().int().nonnegative(),
7573
- pendingInput: z.number().int().nonnegative()
7574
- }),
7575
- ageBuckets: BucketsSchema,
7576
- staleInProgress: z.number().int().nonnegative(),
7577
- byOrg: z.array(
7578
- z.object({
7579
- slug: z.string(),
7580
- openTakedowns: z.number().int().nonnegative()
7581
- })
7582
- )
7583
- })
7584
- });
7585
- var HealthcheckCategorySchema = z.enum([
7586
- "detection",
7587
- "reviewing",
7588
- "blocklisting",
7589
- "takedowns",
7590
- "assets",
7591
- "organization"
7592
- ]);
7593
- var HealthcheckSeveritySchema = z.enum(["ok", "warn", "fail"]);
7594
- var HealthcheckFindingSchema = z.object({
7595
- kind: z.string(),
7596
- ref: z.string().nullable(),
7597
- message: z.string(),
7598
- severity: z.enum(["warn", "fail"])
7599
- });
7600
- z.object({
7601
- id: z.string(),
7602
- title: z.string(),
7603
- category: HealthcheckCategorySchema,
7604
- generatedAt: z.date(),
7605
- scope: z.object({
7606
- slug: z.string().nullable()
7607
- }),
7608
- ok: z.boolean(),
7609
- severity: HealthcheckSeveritySchema,
7610
- observed: z.record(z.union([z.number(), z.string(), z.boolean()]).nullable()),
7611
- threshold: z.record(z.union([z.number(), z.string(), z.boolean()]).nullable()),
7612
- findings: z.array(HealthcheckFindingSchema),
7613
- suggestedAction: z.string().nullable(),
7614
- appUrl: z.string().nullable()
7615
- });
7616
7409
 
7617
- // ../../internal/validation/src/public/healthchecks/assets-dead-asset-spike.ts
7618
- z.object({
7619
- slug: z.string().min(1),
7620
- windowHours: z.number().int().positive().default(24),
7621
- baselineDays: z.number().int().positive().default(7),
7622
- warnMultiplier: z.number().positive().default(2),
7623
- failMultiplier: z.number().positive().default(4),
7624
- minSpikeCount: z.number().int().min(1).default(10)
7625
- });
7626
- z.object({});
7627
- var HealthcheckRegistryEntrySchema = z.object({
7628
- id: z.string(),
7629
- title: z.string(),
7630
- description: z.string(),
7631
- category: HealthcheckCategorySchema,
7632
- implemented: z.boolean(),
7633
- endpoint: z.string().nullable(),
7634
- defaultThreshold: z.record(z.union([z.number(), z.string()])).optional(),
7635
- notImplementedReason: z.string().optional()
7636
- });
7637
- z.object({
7638
- checks: z.array(HealthcheckRegistryEntrySchema)
7639
- });
7640
- z.object({
7641
- slug: z.string().min(1)
7642
- });
7643
- z.object({
7644
- slug: z.string().min(1),
7645
- warnThreshold: z.number().int().nonnegative().default(50),
7646
- failThreshold: z.number().int().nonnegative().default(100)
7647
- });
7648
- z.object({
7649
- slug: z.string().min(1),
7650
- warnAgeHours: z.number().int().positive().default(24 * 7),
7651
- failAgeHours: z.number().int().positive().default(24 * 14)
7652
- });
7653
- z.object({
7654
- slug: z.string().min(1),
7655
- warnAgeHours: z.number().int().nonnegative().default(24 * 30),
7656
- failAgeHours: z.number().int().nonnegative().default(24 * 60)
7657
- });
7658
- z.object({
7659
- slug: z.string().min(1),
7660
- lookbackHours: z.number().int().positive().default(24 * 7),
7661
- warnThreshold: z.number().int().nonnegative().default(3),
7662
- failThreshold: z.number().int().nonnegative().default(10)
7663
- });
7664
- z.object({
7665
- slug: z.string().min(1),
7666
- warnThreshold: z.number().int().nonnegative().default(30),
7667
- failThreshold: z.number().int().nonnegative().default(75)
7668
- });
7669
- z.object({
7670
- slug: z.string().min(1),
7671
- staleThresholdHours: z.number().int().positive().default(24 * 7),
7672
- warnThreshold: z.number().int().nonnegative().default(1),
7673
- failThreshold: z.number().int().nonnegative().default(5)
7674
- });
7675
- z.object({
7676
- slug: z.string().min(1),
7677
- warnThreshold: z.number().int().nonnegative().default(50),
7678
- failThreshold: z.number().int().nonnegative().default(100)
7679
- });
7680
- var BreakdownBySchema = z.enum(["day", "type", "brand"]);
7681
- z.object({
7682
- slug: z.string().min(1),
7683
- by: BreakdownBySchema,
7684
- startDate: z.date().optional(),
7685
- endDate: z.date().optional(),
7686
- brandIds: z.array(z.number().int().positive()).optional()
7687
- });
7688
- z.object({
7689
- by: BreakdownBySchema,
7690
- points: z.array(
7691
- z.object({
7692
- key: z.string(),
7693
- count: z.number(),
7694
- date: z.string().optional(),
7695
- type: z.string().optional(),
7696
- brandId: z.number().optional(),
7697
- brandSlug: z.string().optional(),
7698
- brandName: z.string().optional()
7699
- })
7700
- )
7701
- });
7702
- z.object({
7703
- slug: z.string().min(1),
7704
- startDate: z.date(),
7705
- endDate: z.date(),
7706
- brandIds: z.array(z.number().int().positive()).optional()
7707
- });
7708
- z.object({
7709
- metric: z.literal("new_threats"),
7710
- found: z.number(),
7711
- range: z.object({
7712
- startDate: z.date(),
7713
- endDate: z.date()
7714
- })
7715
- });
7716
- z.object({
7717
- slug: z.string().min(1),
7718
- startDate: z.date().optional(),
7719
- endDate: z.date().optional(),
7720
- brandIds: z.array(z.number().int().positive()).optional()
7721
- });
7722
- z.object({
7723
- metrics: z.object({
7724
- reports: z.number(),
7725
- newThreats: z.number(),
7726
- threatsWatchlisted: z.number(),
7727
- takedownsFiled: z.number(),
7728
- takedownsCompleted: z.number(),
7729
- domainThreats: z.number(),
7730
- twitterThreats: z.number(),
7731
- telegramThreats: z.number(),
7732
- otherThreats: z.number()
7733
- }),
7734
- blockedByDay: z.array(
7735
- z.object({
7736
- date: z.string(),
7737
- count: z.number()
7738
- })
7739
- ),
7740
- blockedByType: z.array(
7741
- z.object({
7742
- type: z.string(),
7743
- count: z.number()
7744
- })
7745
- )
7746
- });
7747
- z.object({
7748
- type: z.nativeEnum(AssetType).optional().describe("Filter by asset type (URL, ADDRESS, etc.)"),
7749
- groupId: z.number().int().optional().describe(
7750
- "Filter by group ID. Use -1 for ungrouped assets only. Omit for all assets."
7751
- ),
7752
- query: z.string().optional().describe("Search query to filter assets by content"),
7753
- per_page: z.number().int().min(1).max(1e3).optional().default(100).describe("The number of assets to return per page (max 1000)"),
7754
- next_page: z.string().optional().nullable().describe("Cursor for fetching the next page of results")
7755
- }).describe(
7756
- `List organization assets request body
7757
-
7758
- Returns all assets belonging to the organization associated with your API key.
7759
- Supports filtering by type, group, and search query.`
7760
- );
7761
- var organizationAssetItemSchema = z.object({
7762
- id: z.number().describe("Asset ID"),
7763
- content: z.string().describe("Asset content (URL, address, handle, etc.)"),
7764
- type: z.nativeEnum(AssetType).describe("Asset type"),
7765
- status: z.nativeEnum(AssetStatus).describe("Asset status"),
7766
- name: z.string().nullable().describe("Asset display name"),
7767
- description: z.string().nullable().describe("Asset description"),
7768
- group: z.object({
7769
- id: z.number().describe("Group ID"),
7770
- name: z.string().describe("Group name")
7771
- }).nullable().describe("Asset group information"),
7772
- livenessStatus: z.nativeEnum(LivenessStatus).nullable().describe(
7773
- "Whether the asset is currently reachable (`ALIVE`), gone (`DEAD`), or hasn't been checked (`UNKNOWN`). `null` when liveness has never been evaluated."
7774
- ),
7775
- blockedAt: z.date().nullable().describe(
7776
- "When the asset transitioned to BLOCKED status. `null` for non-blocked assets. Distinct from `updatedAt`."
7777
- ),
7778
- createdAt: z.date().describe("When the asset was created"),
7779
- updatedAt: z.date().describe("When the asset was last updated")
7780
- });
7781
- z.object({
7782
- assets: z.array(organizationAssetItemSchema).describe("List of assets"),
7783
- next_page: z.string().nullable().optional().describe("Cursor for fetching the next page of results")
7784
- }).describe("Successful operation");
7785
- var addAssetItemSchema = z.object({
7786
- content: z.string().describe("Asset content (URL, address, handle, etc.)"),
7787
- name: z.string().optional().describe("Optional display name for the asset"),
7788
- description: z.string().optional().describe("Optional description for the asset"),
7789
- groupId: z.number().int().positive().optional().describe("Optional group ID to assign the asset to")
7790
- });
7791
- z.object({
7792
- assets: z.array(addAssetItemSchema).min(1).max(1e3).describe("Array of assets to add (max 1000 per request)")
7793
- }).describe(
7794
- `Add assets to organization allowlist
7795
-
7796
- Batch add multiple assets to your organization's allowlist.
7797
- Each asset will be automatically parsed and classified.
7798
- Assets will be auto-approved as ALLOWED status.`
7799
- );
7800
- var addAssetResultSchema = z.object({
7801
- content: z.string().describe("Asset content"),
7802
- success: z.boolean().describe("Whether the asset was added successfully"),
7803
- id: z.number().optional().describe("Asset ID if successful"),
7804
- error: z.string().optional().describe("Error message if failed")
7805
- });
7806
- z.object({
7807
- results: z.array(addAssetResultSchema).describe("Results for each asset"),
7808
- successCount: z.number().describe("Number of assets successfully added"),
7809
- errorCount: z.number().describe("Number of assets that failed to add")
7810
- }).describe("Batch add operation results");
7811
- z.object({
7812
- assetId: z.number().int().positive().describe("ID of the asset to update"),
7813
- name: z.string().optional().describe("New display name for the asset"),
7814
- description: z.string().nullable().optional().describe("New description for the asset"),
7815
- groupId: z.number().int().positive().nullable().optional().describe("New group ID (null to ungroup)")
7816
- }).describe(
7817
- `Update an organization asset
7818
-
7819
- Update the name, description, or group assignment of an asset.`
7820
- );
7821
- z.object({
7822
- id: z.number().describe("Asset ID"),
7823
- content: z.string().describe("Asset content"),
7824
- name: z.string().nullable().describe("Asset display name"),
7825
- description: z.string().nullable().describe("Asset description"),
7826
- groupId: z.number().nullable().describe("Group ID")
7827
- }).describe("Updated asset");
7828
- z.object({
7829
- assetId: z.number().int().positive().describe("ID of the asset to remove")
7830
- }).describe(
7831
- `Remove an asset from the organization
7832
-
7833
- This removes the asset from the organization's allowlist.`
7834
- );
7835
- z.object({
7836
- success: z.boolean().describe("Whether the asset was removed successfully"),
7837
- id: z.number().describe("Asset ID that was removed")
7838
- }).describe("Delete operation result");
7839
- z.object({}).describe(
7840
- `List organization asset groups
7841
-
7842
- Returns all asset groups belonging to the organization associated with your API key.`
7843
- );
7844
- var assetGroupItemSchema = z.object({
7845
- id: z.number().describe("Group ID"),
7846
- name: z.string().describe("Group name"),
7847
- assetCount: z.number().describe("Number of assets in this group")
7848
- });
7849
- z.object({
7850
- groups: z.array(assetGroupItemSchema).describe("List of asset groups")
7851
- }).describe("Successful operation");
7852
- z.object({
7853
- name: z.string().min(1).max(255).describe("Name for the new group")
7854
- }).describe(
7855
- `Create a new asset group
7856
-
7857
- Creates a new asset group for organizing your organization's assets.`
7858
- );
7859
- z.object({
7860
- id: z.number().describe("Created group ID"),
7861
- name: z.string().describe("Group name")
7862
- }).describe("Created group");
7863
- z.object({
7864
- groupId: z.number().int().positive().describe("ID of the group to update"),
7865
- name: z.string().min(1).max(255).describe("New name for the group")
7866
- }).describe(
7867
- `Update an asset group
7868
-
7869
- Rename an existing asset group.`
7870
- );
7871
- z.object({
7872
- id: z.number().describe("Group ID"),
7873
- name: z.string().describe("Updated group name")
7874
- }).describe("Updated group");
7875
- z.object({
7876
- groupId: z.number().int().positive().describe("ID of the group to delete")
7877
- }).describe(
7878
- `Delete an asset group
7879
-
7880
- Deletes an asset group. Assets in this group will become ungrouped.`
7881
- );
7882
- z.object({
7883
- success: z.boolean().describe("Whether the group was deleted successfully"),
7884
- id: z.number().describe("Group ID that was deleted"),
7885
- unassignedAssetCount: z.number().describe("Number of assets that were unassigned from this group")
7886
- }).describe("Delete operation result");
7887
- z.object({}).describe(
7888
- `List organization brands
7889
-
7890
- Returns all brands belonging to the organization associated with your API key,
7891
- including sub-brands (\`ORGANIZATION\`), individual / employee brands
7892
- (\`INDIVIDUAL\`), and product brands (\`PRODUCT\`). Soft-deleted brands are
7893
- excluded.`
7894
- );
7895
- var brandLegalDocumentSchema = z.object({
7896
- present: z.boolean().describe("Whether the brand has this document attached"),
7897
- fileName: z.string().nullable().describe("Original filename of the uploaded document (null when not present)"),
7898
- fileUrl: z.string().nullable().describe("Direct URL to view or download the document (null when not present)")
7899
- });
7900
- var brandTrademarkRegistrationSchema = z.object({
7901
- id: z.number().describe("Trademark registration ID"),
7902
- brandName: z.string().describe("Trademarked brand name as it appears on the registration"),
7903
- trademarkOffice: z.string().describe("Issuing trademark office (e.g. `USPTO`, `EUIPO`)"),
7904
- registrationNumber: z.string().describe("Registration number assigned by the office"),
7905
- goodsAndServicesClass: z.string().describe("Nice Classification class(es) the registration covers"),
7906
- rightsOwnerName: z.string().nullable().describe("Legal entity the trademark is registered to, if recorded"),
7907
- registrationPageUrl: z.string().nullable().describe("Public URL on the trademark office's site, if recorded"),
7908
- certificateFileName: z.string().nullable().describe(
7909
- "Original filename of the uploaded certificate PDF (null when no certificate is attached)"
7910
- ),
7911
- certificateFileUrl: z.string().nullable().describe(
7912
- "Direct URL to view or download the certificate PDF (null when no certificate is attached)"
7913
- )
7914
- });
7915
- var brandItemSchema = z.object({
7916
- id: z.number().describe("Brand ID"),
7917
- slug: z.string().describe("Brand slug (stable, URL-safe identifier)"),
7918
- name: z.string().describe("Display name"),
7919
- type: z.nativeEnum(BrandType).describe(
7920
- "Brand type: `ORGANIZATION` for parent brands, `INDIVIDUAL` for employee or person brands, `PRODUCT` for a specific product or service offering"
7921
- ),
7922
- description: z.string().nullable().describe("Free-form description, if set"),
7923
- avatarUrl: z.string().nullable().describe("URL of the brand's avatar / logo image"),
7924
- websiteUrl: z.string().nullable().describe("Official brand website URL"),
7925
- twitterHandle: z.string().nullable().describe("Official Twitter / X handle (without @)"),
7926
- brandColors: z.array(z.string()).describe("HEX color strings associated with the brand (e.g. `#FF0000`)"),
7927
- includedTerms: z.array(z.string()).describe("Terms that should be included when matching this brand"),
7928
- excludedTerms: z.array(z.string()).describe("Terms that should be excluded when matching this brand"),
7929
- tickers: z.array(z.string()).describe("Ticker symbols associated with the brand (e.g. `$JUP`)"),
7930
- brandGroupId: z.number().nullable().describe(
7931
- "Group this brand belongs to (only set for `INDIVIDUAL` and `PRODUCT` brands)"
7932
- ),
7933
- createdAt: z.date().describe("When the brand was created"),
7934
- useOrganizationDocs: z.boolean().describe(
7935
- "When true, this brand inherits its Letter of Authorization and Power of Attorney from the organization rather than carrying its own. The `legalDocuments` block below always reflects the brand-level attachments \u2014 read `/user/orgs/{slug}` for the org-level fallbacks."
7936
- ),
7937
- legalDocuments: z.object({
7938
- letterOfAuthorization: brandLegalDocumentSchema,
7939
- powerOfAttorney: brandLegalDocumentSchema
7940
- }).describe("Brand-level Letter of Authorization and Power of Attorney attachments"),
7941
- trademarkRegistrations: z.array(brandTrademarkRegistrationSchema).describe(
7942
- "Trademark registrations attached to this brand. An empty array means no trademarks are on file for the brand \u2014 use this to identify brands that still need them added."
7943
- )
7944
- });
7945
- z.object({
7946
- brands: z.array(brandItemSchema).describe("List of brands")
7947
- }).describe("Successful operation");
7948
- var FILTERABLE_SUBSCRIPTION_STATUSES = [
7949
- SubscriptionStatus.PROSPECT,
7950
- SubscriptionStatus.POC,
7951
- SubscriptionStatus.ACTIVE,
7952
- SubscriptionStatus.INTEGRATION
7953
- ];
7954
- var UserOrgsSubscriptionStatusSchema = z.enum(
7955
- FILTERABLE_SUBSCRIPTION_STATUSES
7956
- );
7957
- var takedownsServiceFilterSchema = z.object({
7958
- active: z.boolean().optional(),
7959
- automated: z.boolean().optional()
7960
- }).optional();
7961
- var singleServiceFilterSchema = z.object({
7962
- active: z.boolean().optional()
7963
- }).optional();
7964
- var userOrgsServicesFilterObjectSchema = z.object({
7965
- reporting: singleServiceFilterSchema,
7966
- reviewing: singleServiceFilterSchema,
7967
- protection: singleServiceFilterSchema,
7968
- takedowns: takedownsServiceFilterSchema,
7969
- detection: singleServiceFilterSchema,
7970
- darkWebMonitoring: singleServiceFilterSchema
7971
- });
7972
- var userOrgsObligatoryAdminApprovalFilterSchema = z.object({
7973
- active: z.boolean().optional(),
7974
- assetTypes: z.array(z.nativeEnum(AssetType)).min(1).optional()
7975
- }).optional();
7976
- var PendingApprovalServiceSchema = z.enum(["protection", "takedowns"]);
7977
- var userOrgsPendingServiceApprovalFilterSchema = z.object({
7978
- active: z.boolean().optional(),
7979
- services: z.array(PendingApprovalServiceSchema).min(1).optional()
7980
- }).optional();
7981
- z.object({
7982
- query: z.string().default(""),
7983
- subscriptionStatus: z.array(UserOrgsSubscriptionStatusSchema).min(1).optional(),
7984
- services: userOrgsServicesFilterObjectSchema.optional(),
7985
- obligatoryAdminApproval: userOrgsObligatoryAdminApprovalFilterSchema,
7986
- pendingServiceApproval: userOrgsPendingServiceApprovalFilterSchema
7987
- });
7988
- var takedownsServiceSchema = z.object({
7989
- active: z.boolean(),
7990
- automated: z.boolean()
7991
- });
7992
- var singleServiceSchema = z.object({
7993
- active: z.boolean()
7994
- });
7995
- var UserOrgObligatoryAdminApprovalSchema = z.object({
7996
- active: z.boolean(),
7997
- assetTypes: z.array(z.nativeEnum(AssetType))
7998
- });
7999
- var PendingServiceApprovalSchema = z.object({
8000
- // Friendly service family, matching a key in the `services` object.
8001
- service: PendingApprovalServiceSchema,
8002
- // Whether the request is for the automated variant of the service
8003
- // (e.g. "Automated Wallet Blocking" rather than "Wallet Blocking").
8004
- automated: z.boolean(),
8005
- // Raw `ServiceType` enum value, e.g. "isProtectionActive". Lets callers
8006
- // distinguish the exact column without re-deriving it from `service` +
8007
- // `automated`.
8008
- serviceType: z.nativeEnum(ServiceType),
8009
- // Human-readable service label, e.g. "Wallet Blocking".
8010
- serviceName: z.string(),
8011
- // When the enable request was submitted (ISO 8601, UTC).
8012
- requestedAt: z.string()
8013
- });
8014
- var UserOrgIntegrationsSchema = z.object({
8015
- slack: z.boolean(),
8016
- discord: z.boolean(),
8017
- telegram: z.object({
8018
- connected: z.boolean(),
8019
- groupCount: z.number()
8020
- }),
8021
- vercel: z.boolean(),
8022
- intercom: z.boolean(),
8023
- moderation: z.boolean()
8024
- });
8025
- var UserOrgLegalDocumentSchema = z.object({
8026
- present: z.boolean().describe("Whether the organization has this document attached"),
8027
- fileName: z.string().nullable().describe("Original filename of the uploaded document (null when not present)"),
8028
- fileUrl: z.string().nullable().describe("Direct URL to view or download the document (null when not present)")
8029
- });
8030
- var UserOrgLegalDocumentsSchema = z.object({
8031
- letterOfAuthorization: UserOrgLegalDocumentSchema,
8032
- powerOfAttorney: UserOrgLegalDocumentSchema
8033
- });
8034
- var UserOrgTrademarkRegistrationSchema = z.object({
8035
- id: z.number().describe("Trademark registration ID"),
8036
- brandName: z.string().describe("Trademarked brand name as it appears on the registration"),
8037
- trademarkOffice: z.string().describe("Issuing trademark office (e.g. `USPTO`, `EUIPO`)"),
8038
- registrationNumber: z.string().describe("Registration number assigned by the office"),
8039
- goodsAndServicesClass: z.string().describe("Nice Classification class(es) the registration covers"),
8040
- rightsOwnerName: z.string().nullable().describe("Legal entity the trademark is registered to, if recorded"),
8041
- registrationPageUrl: z.string().nullable().describe("Public URL on the trademark office's site, if recorded"),
8042
- certificateFileName: z.string().nullable().describe(
8043
- "Original filename of the uploaded certificate PDF (null when no certificate is attached)"
8044
- ),
8045
- certificateFileUrl: z.string().nullable().describe(
8046
- "Direct URL to view or download the certificate PDF (null when no certificate is attached)"
8047
- )
8048
- });
8049
- var UserOrgBrandMetadataSchema = z.object({
8050
- websiteUrl: z.string().nullable().describe("Public website URL of the brand (linked from the portal header)"),
8051
- twitterHandle: z.string().nullable().describe(
8052
- "Public Twitter/X handle of the brand, stored with the leading `@` (e.g. `@acme`)"
8053
- ),
8054
- securityContactEmail: z.string().nullable().describe(
8055
- "Email address for security correspondence \u2014 used by takedown providers and researchers, distinct from the internal customer POC email"
8056
- ),
8057
- industry: z.string().nullable().describe('Free-form industry label (e.g. "DeFi", "CEX", "NFT", "Wallet")')
8058
- });
8059
- var UserOrgPortalCustomizationSchema = z.object({
8060
- useCustomDetails: z.boolean().describe(
8061
- "When true, the portal uses `name`/`slug`/`avatarUrl` from this object instead of the org's own name/slug/avatar"
8062
- ),
8063
- name: z.string().nullable().describe(
8064
- "Custom display name shown on the portal (used only when `useCustomDetails=true`)"
8065
- ),
8066
- slug: z.string().nullable().describe(
8067
- "Custom URL slug (`chainpatrol.io/<slug>`) \u2014 takes precedence over the org's own slug when set, regardless of `useCustomDetails`"
8068
- ),
8069
- avatarUrl: z.string().nullable().describe(
8070
- "Custom avatar URL shown on the portal (used only when `useCustomDetails=true`)"
8071
- ),
8072
- bannerEnabled: z.boolean().describe(
8073
- "When true, the portal renders `bannerContent` as a highlighted banner at the top of the page"
8074
- ),
8075
- bannerContent: z.string().nullable().describe(
8076
- "Markdown body of the portal banner. Null (or empty) with `bannerEnabled=true` means the toggle is on but no content has been written yet"
8077
- )
8078
- });
8079
- var UserOrgSchema = z.object({
8080
- id: z.number(),
8081
- name: z.string(),
8082
- slug: z.string(),
8083
- avatarUrl: z.string().nullable(),
8084
- contactUrl: z.string().nullable(),
8085
- subscriptionStatus: z.nativeEnum(SubscriptionStatus),
8086
- portalVisibility: z.nativeEnum(OrganizationPortalVisibility).describe(
8087
- "Visibility of the org's public security portal (chainpatrol.io/<slug>). `PUBLIC` is discoverable; `PRIVATE` renders only the report form (no metrics or listings); `DISABLED` returns a 404."
8088
- ),
8089
- reportVisibility: z.nativeEnum(ReportVisibility).describe(
8090
- "Whether the report listings on the public portal are visible to visitors. `PUBLIC` shows the org's reports; `PRIVATE` hides the report list even when the portal is discoverable."
8091
- ),
8092
- metricsVisibility: z.nativeEnum(MetricsVisibility).describe(
8093
- "Whether the metrics/threats-blocked stats render on the public portal. `PUBLIC` shows the metrics tab; `PRIVATE` hides it from anonymous visitors; `DISABLED` doesn't compute metrics at all."
8094
- ),
8095
- brandMetadata: UserOrgBrandMetadataSchema.describe(
8096
- "Public brand-facing metadata (website, twitter, security contact, industry) shown on the portal and used by staff for outbound"
8097
- ),
8098
- portalCustomization: UserOrgPortalCustomizationSchema.describe(
8099
- "Customer-configurable presentation of the public security portal \u2014 custom name/slug/avatar and the banner content"
8100
- ),
8101
- services: z.object({
8102
- reporting: singleServiceSchema,
8103
- reviewing: singleServiceSchema,
8104
- protection: singleServiceSchema,
8105
- takedowns: takedownsServiceSchema,
8106
- detection: singleServiceSchema,
8107
- darkWebMonitoring: singleServiceSchema
8108
- }),
8109
- integrations: UserOrgIntegrationsSchema,
8110
- obligatoryAdminApproval: UserOrgObligatoryAdminApprovalSchema,
8111
- pendingServiceApprovals: z.array(PendingServiceApprovalSchema),
8112
- legalDocuments: UserOrgLegalDocumentsSchema.describe(
8113
- "Org-level Letter of Authorization and Power of Attorney attachments"
8114
- ),
8115
- trademarkRegistrations: z.array(UserOrgTrademarkRegistrationSchema).describe(
8116
- "Org-level trademark registrations attached to the organization. An empty array means no trademarks are on file \u2014 use this to identify customers who still need to add them."
8117
- )
8118
- });
8119
- z.object({
8120
- organizations: z.array(UserOrgSchema)
8121
- });
8122
-
8123
- // ../../internal/validation/src/public/organization/metrics-get.ts
8124
- var organizationMetricsIncludeFieldSchema = z.enum([
8125
- "reports",
8126
- "newThreats",
8127
- "threatsWatchlisted",
8128
- "takedownsFiled",
8129
- "takedownsCompleted",
8130
- "domainThreats",
8131
- "twitterThreats",
8132
- "telegramThreats",
8133
- "otherThreats",
8134
- "blockedByType",
8135
- "blockedByDay"
8136
- ]);
8137
- organizationMetricsIncludeFieldSchema.options;
8138
- var ORGANIZATION_METRICS_MAX_SLUGS = 500;
8139
- var organizationMetricsServicesFilterSchema = z.preprocess((value) => {
8140
- if (typeof value !== "string") return value;
8141
- try {
8142
- return JSON.parse(value);
8143
- } catch (e4) {
8144
- return value;
8145
- }
8146
- }, userOrgsServicesFilterObjectSchema).optional();
8147
- z.object({
8148
- organizationSlug: z.string().optional().describe(
8149
- "Organization slug. Required when authenticating with a user session (Bearer token) and `slugs`/`allMyOrgs` are not supplied; ignored when using an org-scoped API key (org is derived from the key). Mutually exclusive with `slugs` and `allMyOrgs`."
8150
- ),
8151
- slugs: z.array(z.string()).max(ORGANIZATION_METRICS_MAX_SLUGS).optional().describe(
8152
- "Multi-org form. Each slug is auth-checked individually (org-scoped API keys may only pass their own org; sessions and user API keys must have membership or staff role per slug). When supplied with more than one slug, the response includes a `perOrg` breakdown plus `metrics` rolled up across all of them. Capped at " + String(ORGANIZATION_METRICS_MAX_SLUGS) + " slugs per call. Mutually exclusive with `organizationSlug` and `allMyOrgs`."
8153
- ),
8154
- allMyOrgs: z.preprocess((value) => {
8155
- if (value === "true") return true;
8156
- if (value === "false") return false;
8157
- return value;
8158
- }, z.boolean()).optional().describe(
8159
- "Shortcut for 'every org the caller is authorized to read'. Reuses the same filter logic as `/user/orgs`: org-scoped API keys are rejected (they're pinned to one org \u2014 use the default form); user API keys / Bearer sessions resolve to the user's memberships (or every active org for staff). Combine with `subscriptionStatus` and `services` to narrow (e.g. only paying customers with takedowns enabled). The resolved org set is still capped at " + String(ORGANIZATION_METRICS_MAX_SLUGS) + " and a 413 is returned if exceeded. Mutually exclusive with `organizationSlug`, `slugs`, and `brandSlug`."
8160
- ),
8161
- subscriptionStatus: z.array(UserOrgsSubscriptionStatusSchema).min(1).optional().describe(
8162
- "Only meaningful with `allMyOrgs: true`. Defaults to the same set `/user/orgs` uses (ACTIVE/POC/PROSPECT/INTEGRATION \u2014 INACTIVE is always excluded)."
8163
- ),
8164
- services: organizationMetricsServicesFilterSchema.describe(
8165
- "Only meaningful with `allMyOrgs: true`. Same shape as `/user/orgs`'s `services` filter \u2014 every service accepts `{ active }`, and **only `takedowns` additionally accepts `automated`** (the one service where manual-vs-automated changes real platform behavior). E.g. `{ takedowns: { active: true, automated: false } }` for 'orgs with takedowns enabled but automation off'."
8166
- ),
8167
- brandSlug: z.string().optional(),
8168
- startDate: z.coerce.date().optional(),
8169
- endDate: z.coerce.date().optional(),
8170
- include: z.array(organizationMetricsIncludeFieldSchema).optional().describe(
8171
- "Subset of metrics to compute. When omitted or empty, every metric is computed (legacy behavior). Each value in `include` costs roughly one Prisma aggregate, so narrow the list when an agent only needs a couple of numbers \u2014 this is the main lever for keeping big-org calls inside the 30s function cap. Fields not in `include` come back as `null`."
8172
- )
8173
- }).refine(
8174
- (value) => {
8175
- const explicitForms = [
8176
- Boolean(value.organizationSlug),
8177
- Boolean(value.slugs && value.slugs.length > 0),
8178
- Boolean(value.allMyOrgs)
8179
- ].filter(Boolean).length;
8180
- return explicitForms <= 1;
8181
- },
8182
- {
8183
- message: "Pass at most one of `organizationSlug`, `slugs`, or `allMyOrgs`.",
8184
- path: ["allMyOrgs"]
8185
- }
8186
- ).refine((value) => !(value.brandSlug && value.slugs && value.slugs.length > 1), {
8187
- message: "`brandSlug` is only valid alongside a single organization, not `slugs`.",
8188
- path: ["brandSlug"]
8189
- }).refine((value) => !(value.brandSlug && value.allMyOrgs), {
8190
- message: "`brandSlug` is only valid for a single org, not `allMyOrgs`.",
8191
- path: ["brandSlug"]
8192
- });
8193
- var metricValue = z.number().nullable();
8194
- var metricsObjectSchema = z.object({
8195
- reports: metricValue,
8196
- newThreats: metricValue,
8197
- threatsWatchlisted: metricValue,
8198
- takedownsFiled: metricValue,
8199
- takedownsCompleted: metricValue,
8200
- domainThreats: metricValue,
8201
- twitterThreats: metricValue,
8202
- telegramThreats: metricValue,
8203
- otherThreats: metricValue
8204
- });
8205
- var blockedByTypeSchema = z.array(
8206
- z.object({
8207
- type: z.string(),
8208
- count: z.number()
8209
- })
8210
- ).nullable();
8211
- var blockedByDaySchema = z.array(
8212
- z.object({
8213
- date: z.string(),
8214
- count: z.number()
8215
- })
8216
- ).nullable();
8217
- z.object({
8218
- /**
8219
- * Aggregate metrics. For single-org callers this is just that org's
8220
- * numbers; for multi-org callers (`slugs.length > 1` or `allMyOrgs`)
8221
- * it is the sum across all queried orgs.
8222
- */
8223
- metrics: metricsObjectSchema,
8224
- blockedByType: blockedByTypeSchema,
8225
- blockedByDay: blockedByDaySchema,
8226
- /**
8227
- * Derived averages over the time window (and, in multi-org mode,
8228
- * across orgs). `perDay = metrics / windowDays`. In multi-org mode
8229
- * `perOrgPerDay = metrics / numOrgs / windowDays`; in single-org
8230
- * mode it is `null`. Counts are floats here — the underlying
8231
- * `metrics` fields stay integer counts.
8232
- */
8233
- averages: z.object({
8234
- perDay: metricsObjectSchema.nullable(),
8235
- perOrgPerDay: metricsObjectSchema.nullable(),
8236
- windowDays: z.number().nullable()
8237
- }),
8238
- /**
8239
- * Per-org breakdown. Only populated in multi-org mode; `null` for
8240
- * single-org callers.
8241
- */
8242
- perOrg: z.record(
8243
- z.string(),
8244
- z.object({
8245
- metrics: metricsObjectSchema,
8246
- blockedByType: blockedByTypeSchema,
8247
- blockedByDay: blockedByDaySchema
8248
- })
8249
- ).nullable(),
8250
- /**
8251
- * Echoes the actual orgs the response covers, in the order they
8252
- * were resolved. Single-org responses always have length 1. The
8253
- * `resolvedFrom` field distinguishes how the caller asked for the
8254
- * scope (useful for agent reporting).
8255
- */
8256
- scope: z.object({
8257
- mode: z.enum(["single", "multi"]),
8258
- orgs: z.array(z.string()),
8259
- resolvedFrom: z.enum(["api-key", "organizationSlug", "slugs", "allMyOrgs"])
8260
- })
8261
- });
8262
-
8263
- // ../../internal/utils/src/enrichments.ts
8264
- var enrichments_exports = {};
8265
- __export(enrichments_exports, {
8266
- ASSET_SCAN_ENRICHMENT_SOURCE_LABELS: () => ASSET_SCAN_ENRICHMENT_SOURCE_LABELS,
8267
- ASSET_SCAN_ENRICHMENT_SOURCE_TO_TYPES: () => ASSET_SCAN_ENRICHMENT_SOURCE_TO_TYPES,
8268
- ASSET_SCAN_ENRICHMENT_TYPE_LABELS: () => ASSET_SCAN_ENRICHMENT_TYPE_LABELS,
8269
- AssetScanEnrichmentSource: () => AssetScanEnrichmentSource,
8270
- AssetScanEnrichmentType: () => AssetScanEnrichmentType
7410
+ // ../../internal/utils/src/detection.ts
7411
+ var ThreatDetectionSourceKey = /* @__PURE__ */ ((ThreatDetectionSourceKey2) => {
7412
+ ThreatDetectionSourceKey2["META_ADS_SEARCH"] = "meta_ads_search";
7413
+ ThreatDetectionSourceKey2["TELEGRAM_CHANNELS_SEARCH"] = "telegram_channels_search";
7414
+ ThreatDetectionSourceKey2["TELEGRAM_USER_SEARCH"] = "telegram_user_search";
7415
+ ThreatDetectionSourceKey2["TELEGRAM_CHANNELS_SEARCH_VETRIC"] = "telegram_channels_search_vetric";
7416
+ ThreatDetectionSourceKey2["TELEGRAM_USER_SEARCH_VETRIC"] = "telegram_user_search_vetric";
7417
+ ThreatDetectionSourceKey2["FACEBOOK_PAGE_SEARCH_VETRIC"] = "facebook_page_search_vetric";
7418
+ ThreatDetectionSourceKey2["INSTAGRAM_ACCOUNT_SEARCH_VETRIC"] = "instagram_account_search_vetric";
7419
+ ThreatDetectionSourceKey2["TWITTER_SEARCH_VETRIC"] = "twitter_search_vetric";
7420
+ ThreatDetectionSourceKey2["LINKEDIN_PEOPLE_SEARCH_VETRIC"] = "linkedin_people_search_vetric";
7421
+ ThreatDetectionSourceKey2["LINKEDIN_COMPANY_SEARCH_VETRIC"] = "linkedin_company_search_vetric";
7422
+ ThreatDetectionSourceKey2["META_ADS_SEARCH_VETRIC"] = "meta_ads_search_vetric";
7423
+ ThreatDetectionSourceKey2["TIK_TOK_VIDEO_SEARCH"] = "tik_tok_video_search";
7424
+ ThreatDetectionSourceKey2["TIK_TOK_USER_SEARCH"] = "tik_tok_user_search";
7425
+ ThreatDetectionSourceKey2["TIK_TOK_USER_SEARCH_VETRIC"] = "tik_tok_user_search_vetric";
7426
+ ThreatDetectionSourceKey2["TIK_TOK_VIDEO_SEARCH_VETRIC"] = "tik_tok_video_search_vetric";
7427
+ ThreatDetectionSourceKey2["BLOCKLIST"] = "blocklist";
7428
+ ThreatDetectionSourceKey2["APPLE_APP_STORE"] = "apple_app_store";
7429
+ ThreatDetectionSourceKey2["GOOGLE_ADS_SEARCH"] = "google_ads_search";
7430
+ ThreatDetectionSourceKey2["MOZILLA_ADDON_SEARCH"] = "mozilla_addon_search";
7431
+ ThreatDetectionSourceKey2["REDDIT_SUBREDDIT_SEARCH"] = "reddit_subreddit_search";
7432
+ ThreatDetectionSourceKey2["ASSET_CHECK"] = "asset_check";
7433
+ ThreatDetectionSourceKey2["TWITTER_POST_SEARCH"] = "twitter_post_search";
7434
+ ThreatDetectionSourceKey2["MEDIUM_TAG_RSS"] = "medium_tag_rss";
7435
+ ThreatDetectionSourceKey2["TWITTER_SEARCH"] = "twitter_search";
7436
+ ThreatDetectionSourceKey2["YAHOO_SEARCH"] = "yahoo_search";
7437
+ ThreatDetectionSourceKey2["DUCK_DUCK_GO_SEARCH"] = "duck_duck_go_search";
7438
+ ThreatDetectionSourceKey2["BING_SEARCH"] = "bing_search";
7439
+ ThreatDetectionSourceKey2["GUESTBOOK"] = "guestbook";
7440
+ ThreatDetectionSourceKey2["CERTSTREAM"] = "certstream";
7441
+ ThreatDetectionSourceKey2["EXTERNAL"] = "external";
7442
+ ThreatDetectionSourceKey2["GOOGLE_SEARCH"] = "google_search";
7443
+ ThreatDetectionSourceKey2["DNS_TWIST"] = "dns_twist";
7444
+ ThreatDetectionSourceKey2["TWITTER"] = "twitter";
7445
+ ThreatDetectionSourceKey2["TWITTER_USERNAME_MONITOR"] = "twitter_username_monitor";
7446
+ ThreatDetectionSourceKey2["URLSCAN"] = "urlscan";
7447
+ ThreatDetectionSourceKey2["URLSCAN_HOSTNAME_SEARCH"] = "urlscan_hostname_search";
7448
+ ThreatDetectionSourceKey2["YOUTUBE_SEARCH"] = "youtube_search";
7449
+ ThreatDetectionSourceKey2["GOOGLE_PLAY_SEARCH"] = "google_play_search";
7450
+ ThreatDetectionSourceKey2["DEXSCREENER_SEARCH"] = "dexscreener_search";
7451
+ ThreatDetectionSourceKey2["BLOCKED_IP_SCAN"] = "blocked_ip_scan";
7452
+ ThreatDetectionSourceKey2["BLOCKED_BILIBILI_SUGGESTED"] = "blocked_bilibili_suggested";
7453
+ ThreatDetectionSourceKey2["GROK_POST_SEARCH"] = "grok_post_search";
7454
+ ThreatDetectionSourceKey2["GROK_USER_SEARCH"] = "grok_user_search";
7455
+ ThreatDetectionSourceKey2["GOOGLE_LENS_IMAGE_SEARCH"] = "google_lens_image_search";
7456
+ ThreatDetectionSourceKey2["YANDEX_SEARCH"] = "yandex_search";
7457
+ ThreatDetectionSourceKey2["LINKEDIN_EMPLOYEE_DETECTION"] = "linkedin_employee_detection";
7458
+ ThreatDetectionSourceKey2["LINKEDIN_POST_SEARCH"] = "linkedin_post_search";
7459
+ ThreatDetectionSourceKey2["LINKEDIN_COMPANY_SEARCH"] = "linkedin_company_search";
7460
+ ThreatDetectionSourceKey2["BING_ADS_SEARCH"] = "bing_ads_search";
7461
+ ThreatDetectionSourceKey2["TIK_TOK_ADS_SEARCH"] = "tik_tok_ads_search";
7462
+ ThreatDetectionSourceKey2["DNSDB"] = "dnsdb";
7463
+ ThreatDetectionSourceKey2["DAILY_MOTION_SEARCH"] = "daily_motion_search";
7464
+ ThreatDetectionSourceKey2["WATCHLIST"] = "watchlist";
7465
+ return ThreatDetectionSourceKey2;
7466
+ })(ThreatDetectionSourceKey || {});
7467
+ var ThreatDetectionScope = /* @__PURE__ */ ((ThreatDetectionScope2) => {
7468
+ ThreatDetectionScope2["ORGANIZATION"] = "organization";
7469
+ ThreatDetectionScope2["GLOBAL"] = "global";
7470
+ return ThreatDetectionScope2;
7471
+ })(ThreatDetectionScope || {});
7472
+
7473
+ // ../../internal/utils/src/enrichments.ts
7474
+ var enrichments_exports = {};
7475
+ __export(enrichments_exports, {
7476
+ ASSET_SCAN_ENRICHMENT_SOURCE_LABELS: () => ASSET_SCAN_ENRICHMENT_SOURCE_LABELS,
7477
+ ASSET_SCAN_ENRICHMENT_SOURCE_TO_TYPES: () => ASSET_SCAN_ENRICHMENT_SOURCE_TO_TYPES,
7478
+ ASSET_SCAN_ENRICHMENT_TYPE_LABELS: () => ASSET_SCAN_ENRICHMENT_TYPE_LABELS,
7479
+ AssetScanEnrichmentSource: () => AssetScanEnrichmentSource,
7480
+ AssetScanEnrichmentType: () => AssetScanEnrichmentType
8271
7481
  });
8272
7482
  var AssetScanEnrichmentType = /* @__PURE__ */ ((AssetScanEnrichmentType2) => {
8273
7483
  AssetScanEnrichmentType2["CONTENT_AND_METADATA"] = "content_and_metadata";
@@ -10852,977 +10062,2012 @@ var doCustomReplacements = (string, replacements2) => {
10852
10062
  for (const [key, value] of replacements2) {
10853
10063
  string = string.replace(new RegExp(escapeStringRegexp2(key), "g"), value);
10854
10064
  }
10855
- return string;
10065
+ return string;
10066
+ };
10067
+ function transliterate(string, options) {
10068
+ if (typeof string !== "string") {
10069
+ throw new TypeError(`Expected a string, got \`${typeof string}\``);
10070
+ }
10071
+ options = __spreadValues({
10072
+ customReplacements: []
10073
+ }, options);
10074
+ const customReplacements = new Map([
10075
+ ...replacements_default,
10076
+ ...options.customReplacements
10077
+ ]);
10078
+ string = string.normalize();
10079
+ string = doCustomReplacements(string, customReplacements);
10080
+ string = string.normalize("NFD").replace(new RegExp("\\p{Diacritic}", "gu"), "").normalize();
10081
+ return string;
10082
+ }
10083
+
10084
+ // ../../node_modules/@sindresorhus/slugify/overridable-replacements.js
10085
+ var overridableReplacements = [
10086
+ ["&", " and "],
10087
+ ["\u{1F984}", " unicorn "],
10088
+ ["\u2665", " love "]
10089
+ ];
10090
+ var overridable_replacements_default = overridableReplacements;
10091
+
10092
+ // ../../node_modules/@sindresorhus/slugify/index.js
10093
+ var decamelize = (string) => {
10094
+ return string.replace(/([A-Z]{2,})(\d+)/g, "$1 $2").replace(/([a-z\d]+)([A-Z]{2,})/g, "$1 $2").replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-rt-z\d]+)/g, "$1 $2");
10095
+ };
10096
+ var removeMootSeparators = (string, separator) => {
10097
+ const escapedSeparator = escapeStringRegexp(separator);
10098
+ return string.replace(new RegExp(`${escapedSeparator}{2,}`, "g"), separator).replace(new RegExp(`^${escapedSeparator}|${escapedSeparator}$`, "g"), "");
10099
+ };
10100
+ var buildPatternSlug = (options) => {
10101
+ let negationSetPattern = "a-z\\d";
10102
+ negationSetPattern += options.lowercase ? "" : "A-Z";
10103
+ if (options.preserveCharacters.length > 0) {
10104
+ for (const character of options.preserveCharacters) {
10105
+ if (character === options.separator) {
10106
+ throw new Error(`The separator character \`${options.separator}\` cannot be included in preserved characters: ${options.preserveCharacters}`);
10107
+ }
10108
+ negationSetPattern += escapeStringRegexp(character);
10109
+ }
10110
+ }
10111
+ return new RegExp(`[^${negationSetPattern}]+`, "g");
10112
+ };
10113
+ function slugify(string, options) {
10114
+ if (typeof string !== "string") {
10115
+ throw new TypeError(`Expected a string, got \`${typeof string}\``);
10116
+ }
10117
+ options = __spreadValues({
10118
+ separator: "-",
10119
+ lowercase: true,
10120
+ decamelize: true,
10121
+ customReplacements: [],
10122
+ preserveLeadingUnderscore: false,
10123
+ preserveTrailingDash: false,
10124
+ preserveCharacters: []
10125
+ }, options);
10126
+ const shouldPrependUnderscore = options.preserveLeadingUnderscore && string.startsWith("_");
10127
+ const shouldAppendDash = options.preserveTrailingDash && string.endsWith("-");
10128
+ const customReplacements = new Map([
10129
+ ...overridable_replacements_default,
10130
+ ...options.customReplacements
10131
+ ]);
10132
+ string = transliterate(string, { customReplacements });
10133
+ if (options.decamelize) {
10134
+ string = decamelize(string);
10135
+ }
10136
+ const patternSlug = buildPatternSlug(options);
10137
+ if (options.lowercase) {
10138
+ string = string.toLowerCase();
10139
+ }
10140
+ string = string.replace(/([a-zA-Z\d]+)'([ts])(\s|$)/g, "$1$2$3");
10141
+ string = string.replace(patternSlug, options.separator);
10142
+ string = string.replace(/\\/g, "");
10143
+ if (options.separator) {
10144
+ string = removeMootSeparators(string, options.separator);
10145
+ }
10146
+ if (shouldPrependUnderscore) {
10147
+ string = `_${string}`;
10148
+ }
10149
+ if (shouldAppendDash) {
10150
+ string = `${string}-`;
10151
+ }
10152
+ return string;
10153
+ }
10154
+
10155
+ // ../asset-parse/src/model.ts
10156
+ var AssetModel = /* @__PURE__ */ ((AssetModel2) => {
10157
+ AssetModel2["Addon"] = "addon";
10158
+ AssetModel2["App"] = "app";
10159
+ AssetModel2["Bot"] = "bot";
10160
+ AssetModel2["BusinessProfile"] = "business-profile";
10161
+ AssetModel2["Catalog"] = "catalog";
10162
+ AssetModel2["Collection"] = "collection";
10163
+ AssetModel2["Channel"] = "channel";
10164
+ AssetModel2["Group"] = "group";
10165
+ AssetModel2["Post"] = "post";
10166
+ AssetModel2["Profile"] = "profile";
10167
+ AssetModel2["Short"] = "short";
10168
+ AssetModel2["Video"] = "video";
10169
+ AssetModel2["Space"] = "space";
10170
+ AssetModel2["Issue"] = "issue";
10171
+ AssetModel2["PullRequest"] = "pull-request";
10172
+ AssetModel2["Discussion"] = "discussion";
10173
+ AssetModel2["Repository"] = "repository";
10174
+ AssetModel2["Article"] = "Article";
10175
+ AssetModel2["Comment"] = "comment";
10176
+ AssetModel2["List"] = "list";
10177
+ AssetModel2["Subreddit"] = "subreddit";
10178
+ AssetModel2["Community"] = "community";
10179
+ AssetModel2["MiniApp"] = "mini-app";
10180
+ AssetModel2["Developer"] = "developer";
10181
+ return AssetModel2;
10182
+ })(AssetModel || {});
10183
+ function isUrl(input) {
10184
+ if (input.trim() === "") {
10185
+ return false;
10186
+ }
10187
+ if (input.startsWith("/") || input.startsWith("#") || input.startsWith("?") || input.startsWith(".") || !input.includes(".")) {
10188
+ return false;
10189
+ }
10190
+ return URL.canParse(input) || URL.canParse(`https://${input}`);
10191
+ }
10192
+ function getNormalizedUrl(input) {
10193
+ if (!isUrl(input)) {
10194
+ throw new Error(`Invalid URL: ${input}`);
10195
+ }
10196
+ let url;
10197
+ try {
10198
+ url = new URL(input);
10199
+ } catch (e4) {
10200
+ try {
10201
+ url = new URL(`https://${input}`);
10202
+ } catch (e5) {
10203
+ throw new Error(`Invalid URL: ${input}`);
10204
+ }
10205
+ }
10206
+ const normalizedUrl = normalizeUrl(url.toString(), {
10207
+ defaultProtocol: "https"
10208
+ });
10209
+ try {
10210
+ return new URL(normalizedUrl);
10211
+ } catch (e4) {
10212
+ throw new Error(`Invalid URL: ${input}`);
10213
+ }
10214
+ }
10215
+ var ensureHttpsPrefix = (url) => {
10216
+ if (!url.startsWith("http")) {
10217
+ return `https://${url}`;
10218
+ }
10219
+ return url.replace(/^https?:\/{1,2}/, "https://");
10856
10220
  };
10857
- function transliterate(string, options) {
10858
- if (typeof string !== "string") {
10859
- throw new TypeError(`Expected a string, got \`${typeof string}\``);
10221
+ function getHostname(input) {
10222
+ try {
10223
+ return getNormalizedUrl(input).hostname;
10224
+ } catch (e4) {
10225
+ return null;
10860
10226
  }
10861
- options = __spreadValues({
10862
- customReplacements: []
10863
- }, options);
10864
- const customReplacements = new Map([
10865
- ...replacements_default,
10866
- ...options.customReplacements
10867
- ]);
10868
- string = string.normalize();
10869
- string = doCustomReplacements(string, customReplacements);
10870
- string = string.normalize("NFD").replace(new RegExp("\\p{Diacritic}", "gu"), "").normalize();
10871
- return string;
10227
+ }
10228
+ function getParentDomains(input) {
10229
+ const domain = getHostname(input);
10230
+ if (!domain) {
10231
+ return [];
10232
+ }
10233
+ const subdomain = getSubdomain(domain, { mixedInputs: false });
10234
+ if (!subdomain) {
10235
+ return [domain];
10236
+ }
10237
+ const domainWithSuffix = getDomain(domain, { mixedInputs: false });
10238
+ if (!domainWithSuffix) {
10239
+ return [];
10240
+ }
10241
+ const parentDomains = [domainWithSuffix];
10242
+ const parentDomainParts = subdomain.split(".");
10243
+ for (let i = parentDomainParts.length - 1; i >= 0; i--) {
10244
+ const parentDomainPart = parentDomainParts.slice(i).join(".");
10245
+ parentDomains.push(`${parentDomainPart}.${domainWithSuffix}`);
10246
+ }
10247
+ return parentDomains.reverse();
10248
+ }
10249
+ function trimDomainToLevels(domain, options = { levels: 4 }) {
10250
+ var _a;
10251
+ const parsed = parse$1(domain);
10252
+ const eTLDPlusOne = (_a = parsed.domain) != null ? _a : "";
10253
+ const subdomains = domain.replace(/https?:\/\/(www\.)?/, "").split(".");
10254
+ const eTLDPlusOneIndex = subdomains.findIndex(
10255
+ (_, i) => subdomains.slice(i).join(".") === eTLDPlusOne
10256
+ );
10257
+ const trimmedSubdomains = subdomains.slice(Math.max(eTLDPlusOneIndex - (options.levels - 1), 0)).join(".");
10258
+ return trimmedSubdomains;
10872
10259
  }
10873
10260
 
10874
- // ../../node_modules/@sindresorhus/slugify/overridable-replacements.js
10875
- var overridableReplacements = [
10876
- ["&", " and "],
10877
- ["\u{1F984}", " unicorn "],
10878
- ["\u2665", " love "]
10879
- ];
10880
- var overridable_replacements_default = overridableReplacements;
10261
+ // ../asset-parse/src/phone.ts
10262
+ var phone_exports = {};
10263
+ __export(phone_exports, {
10264
+ PHONE_NUMBER_REGEX: () => PHONE_NUMBER_REGEX,
10265
+ isPhoneNumber: () => isPhoneNumber,
10266
+ normalizePhoneNumber: () => normalizePhoneNumber
10267
+ });
10268
+ var PHONE_NUMBER_REGEX = /(?:\+?\d{1,4}[\s.-]?)?(?:\(\d{1,4}\)|\d{1,4})[\s.-]?\d{1,4}[\s.-]?\d{1,4}[\s.-]?\d{0,4}(?:\s*(?:ext|x|extension)[\s.]*\d{1,6})?/gi;
10269
+ function preparePhoneInput(input) {
10270
+ let s2 = input.trim();
10271
+ s2 = s2.replace(/^\s*tel:\s*(?:\/\/)?\s*/i, "");
10272
+ s2 = s2.trim();
10273
+ s2 = s2.replace(/[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g, " ");
10274
+ s2 = s2.replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212\uFE58\uFE63\uFF0D]/g, "-");
10275
+ s2 = s2.replace(/\uFF0B/g, "+");
10276
+ s2 = s2.replace(/\uFF08/g, "(");
10277
+ s2 = s2.replace(/\uFF09/g, ")");
10278
+ return s2.trim();
10279
+ }
10280
+ function isAllSameDigit(digits2) {
10281
+ return /^(\d)\1+$/.test(digits2);
10282
+ }
10283
+ function isStrictlyMonotonicStep1(digits2) {
10284
+ if (digits2.length < 8) {
10285
+ return false;
10286
+ }
10287
+ let increasing = true;
10288
+ let decreasing = true;
10289
+ for (let i = 1; i < digits2.length; i++) {
10290
+ const curr = digits2.charCodeAt(i) - 48;
10291
+ const prev = digits2.charCodeAt(i - 1) - 48;
10292
+ if (curr !== prev + 1) {
10293
+ increasing = false;
10294
+ }
10295
+ if (curr !== prev - 1) {
10296
+ decreasing = false;
10297
+ }
10298
+ }
10299
+ return increasing || decreasing;
10300
+ }
10301
+ function isValidNanpNational10(d10) {
10302
+ if (d10.length !== 10) {
10303
+ return false;
10304
+ }
10305
+ const npaFirst = d10.charCodeAt(0) - 48;
10306
+ const nxxFirst = d10.charCodeAt(3) - 48;
10307
+ if (npaFirst < 2 || npaFirst > 9) {
10308
+ return false;
10309
+ }
10310
+ if (nxxFirst < 2 || nxxFirst > 9) {
10311
+ return false;
10312
+ }
10313
+ return true;
10314
+ }
10315
+ function isPlausiblePhoneDigits(withoutExt) {
10316
+ const hasPlus = withoutExt.startsWith("+");
10317
+ const d = withoutExt.replace(/\D/g, "");
10318
+ if (d.length < 8 || d.length > 15) {
10319
+ return false;
10320
+ }
10321
+ if (isAllSameDigit(d) || isStrictlyMonotonicStep1(d)) {
10322
+ return false;
10323
+ }
10324
+ const onlyDigits = /^\d+$/.test(withoutExt);
10325
+ if (hasPlus) {
10326
+ if (d.length === 11 && d.startsWith("1")) {
10327
+ return isValidNanpNational10(d.slice(1));
10328
+ }
10329
+ return true;
10330
+ }
10331
+ if (onlyDigits) {
10332
+ if (d.length === 10) {
10333
+ return isValidNanpNational10(d);
10334
+ }
10335
+ if (d.length === 11 && d.startsWith("1")) {
10336
+ return isValidNanpNational10(d.slice(1));
10337
+ }
10338
+ if (d.length === 11 && d.startsWith("0")) {
10339
+ return true;
10340
+ }
10341
+ return false;
10342
+ }
10343
+ if (d.length === 10) {
10344
+ return isValidNanpNational10(d);
10345
+ }
10346
+ if (d.length === 11 && d.startsWith("1")) {
10347
+ return isValidNanpNational10(d.slice(1));
10348
+ }
10349
+ if (d.length === 11 && d.startsWith("0")) {
10350
+ return true;
10351
+ }
10352
+ if (d.length >= 12 && d.length <= 15) {
10353
+ return true;
10354
+ }
10355
+ return false;
10356
+ }
10357
+ function isPhoneNumber(input) {
10358
+ const trimmed = preparePhoneInput(input);
10359
+ if (trimmed === "") {
10360
+ return false;
10361
+ }
10362
+ if (!/^[+\d(]/.test(trimmed)) {
10363
+ return false;
10364
+ }
10365
+ const withoutExt = trimmed.replace(/\s*(ext|extension|x)\s*\d+$/i, "");
10366
+ if (/[a-zA-Z]/.test(withoutExt)) {
10367
+ return false;
10368
+ }
10369
+ const hasPhoneMarker = /[+()\s-]/.test(trimmed);
10370
+ const isPureDotSeparated = /^\d+(\.\d+)+$/.test(trimmed);
10371
+ if (isPureDotSeparated && !hasPhoneMarker) {
10372
+ return false;
10373
+ }
10374
+ const phoneRegex = /^(?:\+?\d{1,4}[\s.-]?)?(?:\(\d{1,4}\)|\d{1,4})[\s.-]?\d{1,4}[\s.-]?\d{1,4}[\s.-]?\d{0,4}(?:\s*(?:ext|x|extension)[\s.]*\d{1,6})?$/i;
10375
+ if (!phoneRegex.test(trimmed)) {
10376
+ return false;
10377
+ }
10378
+ return isPlausiblePhoneDigits(withoutExt);
10379
+ }
10380
+ function normalizePhoneNumber(phone) {
10381
+ const trimmed = preparePhoneInput(phone);
10382
+ const withoutExt = trimmed.replace(/\s*(ext|extension|x)\s*\d+$/i, "");
10383
+ const hasPlus = withoutExt.startsWith("+");
10384
+ const digitsOnly = withoutExt.replace(/\D/g, "");
10385
+ return hasPlus ? `+${digitsOnly}` : digitsOnly;
10386
+ }
10881
10387
 
10882
- // ../../node_modules/@sindresorhus/slugify/index.js
10883
- var decamelize = (string) => {
10884
- return string.replace(/([A-Z]{2,})(\d+)/g, "$1 $2").replace(/([a-z\d]+)([A-Z]{2,})/g, "$1 $2").replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-rt-z\d]+)/g, "$1 $2");
10885
- };
10886
- var removeMootSeparators = (string, separator) => {
10887
- const escapedSeparator = escapeStringRegexp(separator);
10888
- return string.replace(new RegExp(`${escapedSeparator}{2,}`, "g"), separator).replace(new RegExp(`^${escapedSeparator}|${escapedSeparator}$`, "g"), "");
10388
+ // ../../internal/utils/src/punycode.ts
10389
+ var maxInt = 2147483647;
10390
+ var base = 36;
10391
+ var tMin = 1;
10392
+ var tMax = 26;
10393
+ var skew = 38;
10394
+ var damp = 700;
10395
+ var initialBias = 72;
10396
+ var initialN = 128;
10397
+ var delimiter = "-";
10398
+ var regexPunycode = /^xn--/;
10399
+ var regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g;
10400
+ var errors = {
10401
+ overflow: "Overflow: input needs wider integers to process",
10402
+ "not-basic": "Illegal input >= 0x80 (not a basic code point)",
10403
+ "invalid-input": "Invalid input"
10889
10404
  };
10890
- var buildPatternSlug = (options) => {
10891
- let negationSetPattern = "a-z\\d";
10892
- negationSetPattern += options.lowercase ? "" : "A-Z";
10893
- if (options.preserveCharacters.length > 0) {
10894
- for (const character of options.preserveCharacters) {
10895
- if (character === options.separator) {
10896
- throw new Error(`The separator character \`${options.separator}\` cannot be included in preserved characters: ${options.preserveCharacters}`);
10897
- }
10898
- negationSetPattern += escapeStringRegexp(character);
10899
- }
10405
+ var baseMinusTMin = base - tMin;
10406
+ var floor = Math.floor;
10407
+ function error(type) {
10408
+ throw new RangeError(errors[type]);
10409
+ }
10410
+ function mapDomain(domain, callback) {
10411
+ const parts = domain.split("@");
10412
+ let result = "";
10413
+ if (parts.length > 1) {
10414
+ result = parts[0] + "@";
10415
+ domain = parts[1];
10900
10416
  }
10901
- return new RegExp(`[^${negationSetPattern}]+`, "g");
10902
- };
10903
- function slugify(string, options) {
10904
- if (typeof string !== "string") {
10905
- throw new TypeError(`Expected a string, got \`${typeof string}\``);
10417
+ domain = domain.replace(regexSeparators, ".");
10418
+ const labels = domain.split(".");
10419
+ const encoded = labels.map(callback).join(".");
10420
+ return result + encoded;
10421
+ }
10422
+ function basicToDigit(codePoint) {
10423
+ if (codePoint >= 48 && codePoint < 58) {
10424
+ return 26 + (codePoint - 48);
10906
10425
  }
10907
- options = __spreadValues({
10908
- separator: "-",
10909
- lowercase: true,
10910
- decamelize: true,
10911
- customReplacements: [],
10912
- preserveLeadingUnderscore: false,
10913
- preserveTrailingDash: false,
10914
- preserveCharacters: []
10915
- }, options);
10916
- const shouldPrependUnderscore = options.preserveLeadingUnderscore && string.startsWith("_");
10917
- const shouldAppendDash = options.preserveTrailingDash && string.endsWith("-");
10918
- const customReplacements = new Map([
10919
- ...overridable_replacements_default,
10920
- ...options.customReplacements
10921
- ]);
10922
- string = transliterate(string, { customReplacements });
10923
- if (options.decamelize) {
10924
- string = decamelize(string);
10426
+ if (codePoint >= 65 && codePoint < 91) {
10427
+ return codePoint - 65;
10925
10428
  }
10926
- const patternSlug = buildPatternSlug(options);
10927
- if (options.lowercase) {
10928
- string = string.toLowerCase();
10429
+ if (codePoint >= 97 && codePoint < 123) {
10430
+ return codePoint - 97;
10929
10431
  }
10930
- string = string.replace(/([a-zA-Z\d]+)'([ts])(\s|$)/g, "$1$2$3");
10931
- string = string.replace(patternSlug, options.separator);
10932
- string = string.replace(/\\/g, "");
10933
- if (options.separator) {
10934
- string = removeMootSeparators(string, options.separator);
10432
+ return base;
10433
+ }
10434
+ function adapt(delta, numPoints, firstTime) {
10435
+ let k4 = 0;
10436
+ delta = firstTime ? floor(delta / damp) : delta >> 1;
10437
+ delta += floor(delta / numPoints);
10438
+ for (
10439
+ ;
10440
+ /* no initialization */
10441
+ delta > baseMinusTMin * tMax >> 1;
10442
+ k4 += base
10443
+ ) {
10444
+ delta = floor(delta / baseMinusTMin);
10935
10445
  }
10936
- if (shouldPrependUnderscore) {
10937
- string = `_${string}`;
10446
+ return floor(k4 + (baseMinusTMin + 1) * delta / (delta + skew));
10447
+ }
10448
+ function decode(input) {
10449
+ const output = [];
10450
+ const inputLength = input.length;
10451
+ let i = 0;
10452
+ let n2 = initialN;
10453
+ let bias2 = initialBias;
10454
+ let basic = input.lastIndexOf(delimiter);
10455
+ if (basic < 0) {
10456
+ basic = 0;
10938
10457
  }
10939
- if (shouldAppendDash) {
10940
- string = `${string}-`;
10458
+ for (let j = 0; j < basic; ++j) {
10459
+ if (input.charCodeAt(j) >= 128) {
10460
+ error("not-basic");
10461
+ }
10462
+ output.push(input.charCodeAt(j));
10941
10463
  }
10942
- return string;
10464
+ for (let index = basic > 0 ? basic + 1 : 0; index < inputLength; ) {
10465
+ const oldi = i;
10466
+ for (let w = 1, k4 = base; ; k4 += base) {
10467
+ if (index >= inputLength) {
10468
+ error("invalid-input");
10469
+ }
10470
+ const digit = basicToDigit(input.charCodeAt(index++));
10471
+ if (digit >= base) {
10472
+ error("invalid-input");
10473
+ }
10474
+ if (digit > floor((maxInt - i) / w)) {
10475
+ error("overflow");
10476
+ }
10477
+ i += digit * w;
10478
+ const t = k4 <= bias2 ? tMin : k4 >= bias2 + tMax ? tMax : k4 - bias2;
10479
+ if (digit < t) {
10480
+ break;
10481
+ }
10482
+ const baseMinusT = base - t;
10483
+ if (w > floor(maxInt / baseMinusT)) {
10484
+ error("overflow");
10485
+ }
10486
+ w *= baseMinusT;
10487
+ }
10488
+ const out = output.length + 1;
10489
+ bias2 = adapt(i - oldi, out, oldi == 0);
10490
+ if (floor(i / out) > maxInt - n2) {
10491
+ error("overflow");
10492
+ }
10493
+ n2 += floor(i / out);
10494
+ i %= out;
10495
+ output.splice(i++, 0, n2);
10496
+ }
10497
+ return String.fromCodePoint(...output);
10498
+ }
10499
+ function toUnicode(input) {
10500
+ return mapDomain(input, function(string) {
10501
+ return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string;
10502
+ });
10943
10503
  }
10944
10504
 
10945
- // ../asset-parse/src/model.ts
10946
- var AssetModel = /* @__PURE__ */ ((AssetModel2) => {
10947
- AssetModel2["Addon"] = "addon";
10948
- AssetModel2["App"] = "app";
10949
- AssetModel2["Bot"] = "bot";
10950
- AssetModel2["BusinessProfile"] = "business-profile";
10951
- AssetModel2["Catalog"] = "catalog";
10952
- AssetModel2["Collection"] = "collection";
10953
- AssetModel2["Channel"] = "channel";
10954
- AssetModel2["Group"] = "group";
10955
- AssetModel2["Post"] = "post";
10956
- AssetModel2["Profile"] = "profile";
10957
- AssetModel2["Short"] = "short";
10958
- AssetModel2["Video"] = "video";
10959
- AssetModel2["Space"] = "space";
10960
- AssetModel2["Issue"] = "issue";
10961
- AssetModel2["PullRequest"] = "pull-request";
10962
- AssetModel2["Discussion"] = "discussion";
10963
- AssetModel2["Repository"] = "repository";
10964
- AssetModel2["Article"] = "Article";
10965
- AssetModel2["Comment"] = "comment";
10966
- AssetModel2["List"] = "list";
10967
- AssetModel2["Subreddit"] = "subreddit";
10968
- AssetModel2["Community"] = "community";
10969
- AssetModel2["MiniApp"] = "mini-app";
10970
- AssetModel2["Developer"] = "developer";
10971
- return AssetModel2;
10972
- })(AssetModel || {});
10973
- function isUrl(input) {
10505
+ // ../../internal/utils/src/url.ts
10506
+ function isEmail(input) {
10974
10507
  if (input.trim() === "") {
10975
10508
  return false;
10976
10509
  }
10977
- if (input.startsWith("/") || input.startsWith("#") || input.startsWith("?") || input.startsWith(".") || !input.includes(".")) {
10978
- return false;
10979
- }
10980
- return URL.canParse(input) || URL.canParse(`https://${input}`);
10510
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
10511
+ return emailRegex.test(input);
10981
10512
  }
10982
- function getNormalizedUrl(input) {
10513
+ function removeHttpProtocol(input) {
10514
+ return input.replace(/^https?:\/\//, "");
10515
+ }
10516
+ function stripDomainWildcardPrefix(domain) {
10517
+ const trimmedDomain = domain.trim();
10518
+ const strippedDomain = trimmedDomain.startsWith("*.") ? trimmedDomain.slice(2) : trimmedDomain;
10519
+ return strippedDomain.length > 0 ? strippedDomain : null;
10520
+ }
10521
+ function getDefangedUrl(input) {
10983
10522
  if (!isUrl(input)) {
10984
- throw new Error(`Invalid URL: ${input}`);
10523
+ console.warn(`[getDefangedUrl] Invalid URL: ${input}, returning input as-is`);
10524
+ return input;
10525
+ }
10526
+ return input.replace(/\./g, "[.]").replace(/(https:\/\/)/g, "hxxps://").replace(/(http:\/\/)/g, "hxxp://").replace(/:\/\//g, "[://]");
10527
+ }
10528
+ function getRefangedUrl(input) {
10529
+ return input.replace(/hxxps/gi, "https").replace(/hxxp/gi, "http").replace(/\[:\/{2}\]/g, "://").replace(/\[\.\]/g, ".");
10530
+ }
10531
+ function containsPunycode(url) {
10532
+ return url.indexOf("xn--") !== -1;
10533
+ }
10534
+ function toUnicode2(url) {
10535
+ return toUnicode(url);
10536
+ }
10537
+ function convertHttpsToHttp(url) {
10538
+ if (url.startsWith("https://")) {
10539
+ const httpUrl = new URL(url);
10540
+ httpUrl.protocol = "http:";
10541
+ return httpUrl.toString();
10542
+ }
10543
+ throw new Error(`URL is not HTTPS: ${url}`);
10544
+ }
10545
+ function generateCanonicalIPFSUrl(content) {
10546
+ if (!content) {
10547
+ return content;
10548
+ }
10549
+ if (content.includes("ipfs.io")) {
10550
+ return content;
10551
+ }
10552
+ if (content.startsWith("Qm") || content.startsWith("bafy")) {
10553
+ return `ipfs.io/ipfs/${content}`;
10554
+ }
10555
+ return content;
10556
+ }
10557
+ function isWalrusSite(content) {
10558
+ return content.includes(".walrus.site") || content.includes(".walrus.host") || content.includes(".wal.app") || content.includes(".wal.site");
10559
+ }
10560
+ function getFaviconUrl(content) {
10561
+ const normalizedUrl = getNormalizedUrl(content);
10562
+ return `https://icons.duckduckgo.com/ip3/${normalizedUrl.hostname}.ico`;
10563
+ }
10564
+ function sanitizeHttpUrl(value) {
10565
+ if (typeof value !== "string" || value.length === 0) {
10566
+ return null;
10985
10567
  }
10986
- let url;
10987
10568
  try {
10988
- url = new URL(input);
10569
+ const parsed = new URL(value);
10570
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
10571
+ return null;
10572
+ }
10573
+ return parsed.toString();
10989
10574
  } catch (e4) {
10990
- try {
10991
- url = new URL(`https://${input}`);
10992
- } catch (e5) {
10993
- throw new Error(`Invalid URL: ${input}`);
10575
+ return null;
10576
+ }
10577
+ }
10578
+ var URL_REGEX = /https?:\/\/[^\s"'<>\])]*/g;
10579
+
10580
+ // ../../internal/utils/src/email.ts
10581
+ var email_exports = {};
10582
+ __export(email_exports, {
10583
+ extractTextFromGmailPayload: () => extractTextFromGmailPayload,
10584
+ getDomainFromEmail: () => getDomainFromEmail,
10585
+ getNameFromEmail: () => getNameFromEmail
10586
+ });
10587
+ function getDomainFromEmail(email) {
10588
+ return email.split("@")[1];
10589
+ }
10590
+ function getNameFromEmail(email) {
10591
+ return email.split("@")[0];
10592
+ }
10593
+ function extractTextFromGmailPayload(payload) {
10594
+ var _a;
10595
+ if (!payload) return "";
10596
+ if ((_a = payload.body) == null ? void 0 : _a.data) {
10597
+ if (payload.mimeType === "text/plain" || payload.mimeType === "text/html") {
10598
+ return Buffer.from(payload.body.data, "base64url").toString("utf-8");
10599
+ }
10600
+ }
10601
+ if (payload.parts) {
10602
+ if (payload.mimeType === "multipart/alternative") {
10603
+ const plainTextPart = payload.parts.find((part) => part.mimeType === "text/plain");
10604
+ if (plainTextPart) {
10605
+ return extractTextFromGmailPayload(plainTextPart);
10606
+ }
10607
+ const htmlPart = payload.parts.find((part) => part.mimeType === "text/html");
10608
+ if (htmlPart) {
10609
+ return extractTextFromGmailPayload(htmlPart);
10610
+ }
10611
+ for (const part of payload.parts) {
10612
+ const text = extractTextFromGmailPayload(part);
10613
+ if (text) return text;
10614
+ }
10994
10615
  }
10616
+ return payload.parts.map((part) => extractTextFromGmailPayload(part)).join("\n");
10995
10617
  }
10996
- const normalizedUrl = normalizeUrl(url.toString(), {
10997
- defaultProtocol: "https"
10998
- });
10999
- try {
11000
- return new URL(normalizedUrl);
11001
- } catch (e4) {
11002
- throw new Error(`Invalid URL: ${input}`);
11003
- }
10618
+ return "";
11004
10619
  }
11005
- var ensureHttpsPrefix = (url) => {
11006
- if (!url.startsWith("http")) {
11007
- return `https://${url}`;
10620
+
10621
+ // ../../internal/utils/src/vercel.ts
10622
+ var vercel_exports = {};
10623
+ __export(vercel_exports, {
10624
+ checkVercelEnv: () => checkVercelEnv
10625
+ });
10626
+ var checkVercelEnv = ({ envs }) => {
10627
+ var _a;
10628
+ const vercelEnv = (_a = process.env.VERCEL_ENV) != null ? _a : "development";
10629
+ if (!envs.includes(vercelEnv)) {
10630
+ return {
10631
+ ok: false,
10632
+ message: `Vercel environment is ${vercelEnv}, but expected ${envs.join(" or ")}`
10633
+ };
11008
10634
  }
11009
- return url.replace(/^https?:\/{1,2}/, "https://");
10635
+ return { ok: true, message: "" };
11010
10636
  };
11011
- function getHostname(input) {
11012
- try {
11013
- return getNormalizedUrl(input).hostname;
11014
- } catch (e4) {
11015
- return null;
10637
+
10638
+ // ../../internal/utils/src/delay.ts
10639
+ var delay_exports = {};
10640
+ __export(delay_exports, {
10641
+ delay: () => delay
10642
+ });
10643
+ var delay = (ms) => {
10644
+ return new Promise((resolve) => setTimeout(resolve, ms));
10645
+ };
10646
+
10647
+ // ../../internal/utils/src/whois.ts
10648
+ var whois_exports = {};
10649
+ __export(whois_exports, {
10650
+ extractWhoisCountry: () => extractWhoisCountry,
10651
+ extractWhoisPayload: () => extractWhoisPayload,
10652
+ normalizeRegistrar: () => normalizeRegistrar
10653
+ });
10654
+ function extractWhoisPayload(raw) {
10655
+ var _a;
10656
+ const first = Array.isArray(raw) ? (_a = raw.find((entry) => entry !== null && typeof entry === "object")) != null ? _a : {} : raw;
10657
+ if (!first || typeof first !== "object") {
10658
+ return {};
11016
10659
  }
11017
- }
11018
- function getParentDomains(input) {
11019
- const domain = getHostname(input);
11020
- if (!domain) {
11021
- return [];
10660
+ const maybeData = first.data;
10661
+ if (maybeData && typeof maybeData === "object" && !Array.isArray(maybeData)) {
10662
+ return maybeData;
11022
10663
  }
11023
- const subdomain = getSubdomain(domain, { mixedInputs: false });
11024
- if (!subdomain) {
11025
- return [domain];
10664
+ return first;
10665
+ }
10666
+ var WHOIS_EMPTY_VALUES = /* @__PURE__ */ new Set(["", "none", "null"]);
10667
+ var WHOIS_COUNTRY_CODE_KEY_ALIASES = /* @__PURE__ */ new Set(["countrycode", "registrantcountrycode"]);
10668
+ var WHOIS_COUNTRY_KEY_ALIASES = /* @__PURE__ */ new Set([
10669
+ "country",
10670
+ "countryname",
10671
+ "registrantcountry",
10672
+ "registrantcountryname"
10673
+ ]);
10674
+ function normalizeWhoisKey(key) {
10675
+ return key.toLowerCase().replace(/[^a-z0-9]/g, "");
10676
+ }
10677
+ function normalizeRegistrar(value) {
10678
+ return value.toLowerCase().replace(/[^a-z0-9]/g, "");
10679
+ }
10680
+ function parseWhoisString(value) {
10681
+ if (typeof value !== "string") {
10682
+ return void 0;
11026
10683
  }
11027
- const domainWithSuffix = getDomain(domain, { mixedInputs: false });
11028
- if (!domainWithSuffix) {
11029
- return [];
10684
+ const trimmedValue = value.trim();
10685
+ if (WHOIS_EMPTY_VALUES.has(trimmedValue.toLowerCase())) {
10686
+ return void 0;
11030
10687
  }
11031
- const parentDomains = [domainWithSuffix];
11032
- const parentDomainParts = subdomain.split(".");
11033
- for (let i = parentDomainParts.length - 1; i >= 0; i--) {
11034
- const parentDomainPart = parentDomainParts.slice(i).join(".");
11035
- parentDomains.push(`${parentDomainPart}.${domainWithSuffix}`);
10688
+ return trimmedValue;
10689
+ }
10690
+ function extractWhoisFieldByAliases(payload, aliases) {
10691
+ for (const [key, value] of Object.entries(payload)) {
10692
+ if (!aliases.has(normalizeWhoisKey(key))) {
10693
+ continue;
10694
+ }
10695
+ const parsedValue = parseWhoisString(value);
10696
+ if (parsedValue) {
10697
+ return parsedValue;
10698
+ }
11036
10699
  }
11037
- return parentDomains.reverse();
10700
+ return void 0;
11038
10701
  }
11039
- function trimDomainToLevels(domain, options = { levels: 4 }) {
11040
- var _a;
11041
- const parsed = parse$1(domain);
11042
- const eTLDPlusOne = (_a = parsed.domain) != null ? _a : "";
11043
- const subdomains = domain.replace(/https?:\/\/(www\.)?/, "").split(".");
11044
- const eTLDPlusOneIndex = subdomains.findIndex(
11045
- (_, i) => subdomains.slice(i).join(".") === eTLDPlusOne
11046
- );
11047
- const trimmedSubdomains = subdomains.slice(Math.max(eTLDPlusOneIndex - (options.levels - 1), 0)).join(".");
11048
- return trimmedSubdomains;
10702
+ function extractWhoisCountry(payload) {
10703
+ const countryCode = extractWhoisFieldByAliases(payload, WHOIS_COUNTRY_CODE_KEY_ALIASES);
10704
+ const country = extractWhoisFieldByAliases(payload, WHOIS_COUNTRY_KEY_ALIASES);
10705
+ return {
10706
+ countryCode: countryCode != null ? countryCode : void 0,
10707
+ country: country != null ? country : void 0
10708
+ };
11049
10709
  }
11050
10710
 
11051
- // ../asset-parse/src/phone.ts
11052
- var phone_exports = {};
11053
- __export(phone_exports, {
11054
- PHONE_NUMBER_REGEX: () => PHONE_NUMBER_REGEX,
11055
- isPhoneNumber: () => isPhoneNumber,
11056
- normalizePhoneNumber: () => normalizePhoneNumber
10711
+ // ../../internal/utils/src/safe-preview.ts
10712
+ var safe_preview_exports = {};
10713
+ __export(safe_preview_exports, {
10714
+ buildSafePreviewUrl: () => buildSafePreviewUrl,
10715
+ normalizeSafeNavigationTarget: () => normalizeSafeNavigationTarget
11057
10716
  });
11058
- var PHONE_NUMBER_REGEX = /(?:\+?\d{1,4}[\s.-]?)?(?:\(\d{1,4}\)|\d{1,4})[\s.-]?\d{1,4}[\s.-]?\d{1,4}[\s.-]?\d{0,4}(?:\s*(?:ext|x|extension)[\s.]*\d{1,6})?/gi;
11059
- function preparePhoneInput(input) {
11060
- let s2 = input.trim();
11061
- s2 = s2.replace(/^\s*tel:\s*(?:\/\/)?\s*/i, "");
11062
- s2 = s2.trim();
11063
- s2 = s2.replace(/[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g, " ");
11064
- s2 = s2.replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212\uFE58\uFE63\uFF0D]/g, "-");
11065
- s2 = s2.replace(/\uFF0B/g, "+");
11066
- s2 = s2.replace(/\uFF08/g, "(");
11067
- s2 = s2.replace(/\uFF09/g, ")");
11068
- return s2.trim();
11069
- }
11070
- function isAllSameDigit(digits2) {
11071
- return /^(\d)\1+$/.test(digits2);
11072
- }
11073
- function isStrictlyMonotonicStep1(digits2) {
11074
- if (digits2.length < 8) {
11075
- return false;
11076
- }
11077
- let increasing = true;
11078
- let decreasing = true;
11079
- for (let i = 1; i < digits2.length; i++) {
11080
- const curr = digits2.charCodeAt(i) - 48;
11081
- const prev = digits2.charCodeAt(i - 1) - 48;
11082
- if (curr !== prev + 1) {
11083
- increasing = false;
11084
- }
11085
- if (curr !== prev - 1) {
11086
- decreasing = false;
11087
- }
10717
+ var SAFE_NAVIGATION_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
10718
+ var PREVIEW_PATH = "/preview";
10719
+ var URL_BASE = "https://app.chainpatrol.io";
10720
+ function normalizeSafeNavigationTarget(target) {
10721
+ const normalizedTarget = getNormalizedUrl(target);
10722
+ if (!SAFE_NAVIGATION_PROTOCOLS.has(normalizedTarget.protocol)) {
10723
+ throw new Error(`Unsupported URL protocol: ${normalizedTarget.protocol}`);
11088
10724
  }
11089
- return increasing || decreasing;
10725
+ return normalizedTarget;
11090
10726
  }
11091
- function isValidNanpNational10(d10) {
11092
- if (d10.length !== 10) {
11093
- return false;
10727
+ function buildSafePreviewUrl({
10728
+ target,
10729
+ assetId,
10730
+ policy
10731
+ }) {
10732
+ const normalizedTarget = normalizeSafeNavigationTarget(target);
10733
+ const previewUrl = new URL(PREVIEW_PATH, URL_BASE);
10734
+ previewUrl.searchParams.set("target", normalizedTarget.toString());
10735
+ if (Number.isInteger(assetId) && assetId && assetId >= 1) {
10736
+ previewUrl.searchParams.set("asset_id", String(assetId));
11094
10737
  }
11095
- const npaFirst = d10.charCodeAt(0) - 48;
11096
- const nxxFirst = d10.charCodeAt(3) - 48;
11097
- if (npaFirst < 2 || npaFirst > 9) {
11098
- return false;
10738
+ if (policy) {
10739
+ previewUrl.searchParams.set("policy", policy);
11099
10740
  }
11100
- if (nxxFirst < 2 || nxxFirst > 9) {
11101
- return false;
10741
+ return `${previewUrl.pathname}?${previewUrl.searchParams.toString()}`;
10742
+ }
10743
+
10744
+ // ../../internal/utils/src/parse.ts
10745
+ var parse_exports = {};
10746
+ __export(parse_exports, {
10747
+ parseTerms: () => parseTerms,
10748
+ stringifyTerms: () => stringifyTerms
10749
+ });
10750
+ function parseTerms(terms, {
10751
+ forceExact = false
10752
+ } = {}) {
10753
+ if (!terms) return [];
10754
+ return terms.split(",").map((term) => {
10755
+ const trimmed = term.trim();
10756
+ if (!trimmed) return null;
10757
+ const isWrappedExact = trimmed.startsWith("*") && trimmed.endsWith("*") && trimmed.length > 2;
10758
+ if (isWrappedExact) {
10759
+ return {
10760
+ value: trimmed.slice(1, -1).toLowerCase(),
10761
+ type: "exact"
10762
+ };
10763
+ } else {
10764
+ return {
10765
+ value: trimmed.toLowerCase(),
10766
+ type: forceExact ? "exact" : "loose"
10767
+ };
10768
+ }
10769
+ }).filter((term) => term !== null);
10770
+ }
10771
+ function stringifyTerms(parsedTerms) {
10772
+ return parsedTerms.map((term) => term.type === "exact" ? `*${term.value}*` : term.value).join(", ");
10773
+ }
10774
+
10775
+ // ../../internal/utils/src/brand-pattern.ts
10776
+ var brand_pattern_exports = {};
10777
+ __export(brand_pattern_exports, {
10778
+ anyPatternMatches: () => anyPatternMatches,
10779
+ compileBrandPattern: () => compileBrandPattern,
10780
+ countPatternMatches: () => countPatternMatches,
10781
+ findMatchingPatterns: () => findMatchingPatterns
10782
+ });
10783
+ var DEFAULT_MAX_MATCHES = 50;
10784
+ function compileBrandPattern(input) {
10785
+ var _a;
10786
+ try {
10787
+ return new RegExp(input.pattern, (_a = input.flags) != null ? _a : void 0);
10788
+ } catch (e4) {
10789
+ return null;
11102
10790
  }
11103
- return true;
11104
10791
  }
11105
- function isPlausiblePhoneDigits(withoutExt) {
11106
- const hasPlus = withoutExt.startsWith("+");
11107
- const d = withoutExt.replace(/\D/g, "");
11108
- if (d.length < 8 || d.length > 15) {
11109
- return false;
11110
- }
11111
- if (isAllSameDigit(d) || isStrictlyMonotonicStep1(d)) {
11112
- return false;
11113
- }
11114
- const onlyDigits = /^\d+$/.test(withoutExt);
11115
- if (hasPlus) {
11116
- if (d.length === 11 && d.startsWith("1")) {
11117
- return isValidNanpNational10(d.slice(1));
11118
- }
11119
- return true;
11120
- }
11121
- if (onlyDigits) {
11122
- if (d.length === 10) {
11123
- return isValidNanpNational10(d);
11124
- }
11125
- if (d.length === 11 && d.startsWith("1")) {
11126
- return isValidNanpNational10(d.slice(1));
11127
- }
11128
- if (d.length === 11 && d.startsWith("0")) {
10792
+ function anyPatternMatches(content, patterns, kind) {
10793
+ for (const input of patterns) {
10794
+ if (input.kind !== kind) continue;
10795
+ const regex = compileBrandPattern(input);
10796
+ if (!regex) continue;
10797
+ if (regex.test(content)) {
11129
10798
  return true;
11130
10799
  }
11131
- return false;
11132
- }
11133
- if (d.length === 10) {
11134
- return isValidNanpNational10(d);
11135
- }
11136
- if (d.length === 11 && d.startsWith("1")) {
11137
- return isValidNanpNational10(d.slice(1));
11138
- }
11139
- if (d.length === 11 && d.startsWith("0")) {
11140
- return true;
11141
- }
11142
- if (d.length >= 12 && d.length <= 15) {
11143
- return true;
11144
10800
  }
11145
10801
  return false;
11146
10802
  }
11147
- function isPhoneNumber(input) {
11148
- const trimmed = preparePhoneInput(input);
11149
- if (trimmed === "") {
11150
- return false;
11151
- }
11152
- if (!/^[+\d(]/.test(trimmed)) {
11153
- return false;
11154
- }
11155
- const withoutExt = trimmed.replace(/\s*(ext|extension|x)\s*\d+$/i, "");
11156
- if (/[a-zA-Z]/.test(withoutExt)) {
11157
- return false;
11158
- }
11159
- const hasPhoneMarker = /[+()\s-]/.test(trimmed);
11160
- const isPureDotSeparated = /^\d+(\.\d+)+$/.test(trimmed);
11161
- if (isPureDotSeparated && !hasPhoneMarker) {
11162
- return false;
11163
- }
11164
- const phoneRegex = /^(?:\+?\d{1,4}[\s.-]?)?(?:\(\d{1,4}\)|\d{1,4})[\s.-]?\d{1,4}[\s.-]?\d{1,4}[\s.-]?\d{0,4}(?:\s*(?:ext|x|extension)[\s.]*\d{1,6})?$/i;
11165
- if (!phoneRegex.test(trimmed)) {
11166
- return false;
10803
+ function findMatchingPatterns(content, patterns, kind) {
10804
+ const matched = [];
10805
+ for (const input of patterns) {
10806
+ if (input.kind !== kind) continue;
10807
+ const regex = compileBrandPattern(input);
10808
+ if (!regex) continue;
10809
+ if (regex.test(content)) {
10810
+ matched.push(input);
10811
+ }
11167
10812
  }
11168
- return isPlausiblePhoneDigits(withoutExt);
10813
+ return matched;
11169
10814
  }
11170
- function normalizePhoneNumber(phone) {
11171
- const trimmed = preparePhoneInput(phone);
11172
- const withoutExt = trimmed.replace(/\s*(ext|extension|x)\s*\d+$/i, "");
11173
- const hasPlus = withoutExt.startsWith("+");
11174
- const digitsOnly = withoutExt.replace(/\D/g, "");
11175
- return hasPlus ? `+${digitsOnly}` : digitsOnly;
10815
+ function countPatternMatches(content, pattern, maxMatches = DEFAULT_MAX_MATCHES) {
10816
+ const compiled = compileBrandPattern(pattern);
10817
+ if (!compiled) return 0;
10818
+ const flags = compiled.flags.includes("g") ? compiled.flags : `${compiled.flags}g`;
10819
+ const globalRegex = new RegExp(compiled.source, flags);
10820
+ let count = 0;
10821
+ let match2;
10822
+ while ((match2 = globalRegex.exec(content)) !== null) {
10823
+ count += 1;
10824
+ if (count >= maxMatches) break;
10825
+ if (match2[0].length === 0) globalRegex.lastIndex += 1;
10826
+ }
10827
+ return count;
11176
10828
  }
11177
10829
 
11178
- // ../../internal/utils/src/punycode.ts
11179
- var maxInt = 2147483647;
11180
- var base = 36;
11181
- var tMin = 1;
11182
- var tMax = 26;
11183
- var skew = 38;
11184
- var damp = 700;
11185
- var initialBias = 72;
11186
- var initialN = 128;
11187
- var delimiter = "-";
11188
- var regexPunycode = /^xn--/;
11189
- var regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g;
11190
- var errors = {
11191
- overflow: "Overflow: input needs wider integers to process",
11192
- "not-basic": "Illegal input >= 0x80 (not a basic code point)",
11193
- "invalid-input": "Invalid input"
10830
+ // ../../internal/utils/src/text.ts
10831
+ var text_exports = {};
10832
+ __export(text_exports, {
10833
+ HOMOGLYPH_MAPPINGS: () => HOMOGLYPH_MAPPINGS,
10834
+ LETTER_TO_HOMOGLYPH_MAPPINGS: () => LETTER_TO_HOMOGLYPH_MAPPINGS,
10835
+ generateHomoglyphSearchTerms: () => generateHomoglyphSearchTerms,
10836
+ normalizeHomoglyphs: () => normalizeHomoglyphs
10837
+ });
10838
+ var HOMOGLYPH_MAPPINGS = {
10839
+ "0": "o",
10840
+ "1": "i",
10841
+ "3": "e",
10842
+ "4": "a",
10843
+ "5": "s",
10844
+ "7": "t",
10845
+ "8": "b"
11194
10846
  };
11195
- var baseMinusTMin = base - tMin;
11196
- var floor = Math.floor;
11197
- function error(type) {
11198
- throw new RangeError(errors[type]);
10847
+ var LETTER_TO_HOMOGLYPH_MAPPINGS = {
10848
+ a: ["4", "\u0430"],
10849
+ b: ["8", "6"],
10850
+ c: ["\u0441"],
10851
+ e: ["3", "\u0435"],
10852
+ g: ["9"],
10853
+ i: ["1", "l", "\u0456"],
10854
+ l: ["1"],
10855
+ o: ["0", "\u043E"],
10856
+ s: ["5", "\u0455"],
10857
+ t: ["7"],
10858
+ x: ["\u0445"],
10859
+ z: ["2"]
10860
+ };
10861
+ var DEFAULT_MAX_HOMOGLYPH_VARIANTS = 20;
10862
+ function isCyrillic(char) {
10863
+ return char.charCodeAt(0) > 127;
11199
10864
  }
11200
- function mapDomain(domain, callback) {
11201
- const parts = domain.split("@");
11202
- let result = "";
11203
- if (parts.length > 1) {
11204
- result = parts[0] + "@";
11205
- domain = parts[1];
10865
+ function buildReplacementOps(term) {
10866
+ const ops = [];
10867
+ for (let i = 0; i < term.length; i++) {
10868
+ const homoglyphs = LETTER_TO_HOMOGLYPH_MAPPINGS[term[i]];
10869
+ if (!homoglyphs) continue;
10870
+ for (const replacement of homoglyphs) {
10871
+ ops.push({ index: i, replacement });
10872
+ }
11206
10873
  }
11207
- domain = domain.replace(regexSeparators, ".");
11208
- const labels = domain.split(".");
11209
- const encoded = labels.map(callback).join(".");
11210
- return result + encoded;
10874
+ return ops;
11211
10875
  }
11212
- function basicToDigit(codePoint) {
11213
- if (codePoint >= 48 && codePoint < 58) {
11214
- return 26 + (codePoint - 48);
11215
- }
11216
- if (codePoint >= 65 && codePoint < 91) {
11217
- return codePoint - 65;
11218
- }
11219
- if (codePoint >= 97 && codePoint < 123) {
11220
- return codePoint - 97;
10876
+ function applyOps(term, ops, selected) {
10877
+ const chars = Array.from(term);
10878
+ for (const idx of selected) {
10879
+ chars[ops[idx].index] = ops[idx].replacement;
11221
10880
  }
11222
- return base;
10881
+ return chars.join("");
11223
10882
  }
11224
- function adapt(delta, numPoints, firstTime) {
11225
- let k4 = 0;
11226
- delta = firstTime ? floor(delta / damp) : delta >> 1;
11227
- delta += floor(delta / numPoints);
11228
- for (
11229
- ;
11230
- /* no initialization */
11231
- delta > baseMinusTMin * tMax >> 1;
11232
- k4 += base
11233
- ) {
11234
- delta = floor(delta / baseMinusTMin);
10883
+ function generateCombinations(ops, opIndices, term, maxVariants, addFn, variants) {
10884
+ const generate = (startIdx, depth, selected, usedPositions) => {
10885
+ if (selected.length === depth) return addFn(applyOps(term, ops, selected));
10886
+ for (let i = startIdx; i < opIndices.length && variants.length < maxVariants; i++) {
10887
+ const opIdx = opIndices[i];
10888
+ if (usedPositions.has(ops[opIdx].index)) continue;
10889
+ selected.push(opIdx);
10890
+ usedPositions.add(ops[opIdx].index);
10891
+ if (generate(i + 1, depth, selected, usedPositions)) return true;
10892
+ selected.pop();
10893
+ usedPositions.delete(ops[opIdx].index);
10894
+ }
10895
+ return false;
10896
+ };
10897
+ for (let depth = 2; depth <= opIndices.length && variants.length < maxVariants; depth++) {
10898
+ if (generate(0, depth, [], /* @__PURE__ */ new Set())) break;
11235
10899
  }
11236
- return floor(k4 + (baseMinusTMin + 1) * delta / (delta + skew));
11237
10900
  }
11238
- function decode(input) {
11239
- const output = [];
11240
- const inputLength = input.length;
11241
- let i = 0;
11242
- let n2 = initialN;
11243
- let bias2 = initialBias;
11244
- let basic = input.lastIndexOf(delimiter);
11245
- if (basic < 0) {
11246
- basic = 0;
10901
+ function generateHomoglyphSearchTerms(term, maxVariants = DEFAULT_MAX_HOMOGLYPH_VARIANTS) {
10902
+ if (term.length === 0 || maxVariants <= 0) return [];
10903
+ const lowerTerm = term.toLowerCase();
10904
+ const seen = /* @__PURE__ */ new Set();
10905
+ const variants = [];
10906
+ const add = (v) => {
10907
+ if (v === lowerTerm || seen.has(v)) return false;
10908
+ seen.add(v);
10909
+ variants.push(v);
10910
+ return variants.length >= maxVariants;
10911
+ };
10912
+ const allOps = buildReplacementOps(lowerTerm);
10913
+ for (let i = 0; i < allOps.length && variants.length < maxVariants; i++) {
10914
+ add(applyOps(lowerTerm, allOps, [i]));
11247
10915
  }
11248
- for (let j = 0; j < basic; ++j) {
11249
- if (input.charCodeAt(j) >= 128) {
11250
- error("not-basic");
11251
- }
11252
- output.push(input.charCodeAt(j));
10916
+ if (variants.length < maxVariants) {
10917
+ const cyrillicComposite = lowerTerm.split("").map((char) => {
10918
+ var _a;
10919
+ const homoglyphs = LETTER_TO_HOMOGLYPH_MAPPINGS[char];
10920
+ return (_a = homoglyphs == null ? void 0 : homoglyphs.find((h) => isCyrillic(h))) != null ? _a : char;
10921
+ }).join("");
10922
+ add(cyrillicComposite);
10923
+ }
10924
+ const cyrillicOpIndices = allOps.map((op, i) => isCyrillic(op.replacement) ? i : -1).filter((i) => i >= 0);
10925
+ if (variants.length < maxVariants && cyrillicOpIndices.length >= 2) {
10926
+ generateCombinations(
10927
+ allOps,
10928
+ cyrillicOpIndices,
10929
+ lowerTerm,
10930
+ maxVariants,
10931
+ add,
10932
+ variants
10933
+ );
11253
10934
  }
11254
- for (let index = basic > 0 ? basic + 1 : 0; index < inputLength; ) {
11255
- const oldi = i;
11256
- for (let w = 1, k4 = base; ; k4 += base) {
11257
- if (index >= inputLength) {
11258
- error("invalid-input");
11259
- }
11260
- const digit = basicToDigit(input.charCodeAt(index++));
11261
- if (digit >= base) {
11262
- error("invalid-input");
11263
- }
11264
- if (digit > floor((maxInt - i) / w)) {
11265
- error("overflow");
11266
- }
11267
- i += digit * w;
11268
- const t = k4 <= bias2 ? tMin : k4 >= bias2 + tMax ? tMax : k4 - bias2;
11269
- if (digit < t) {
11270
- break;
11271
- }
11272
- const baseMinusT = base - t;
11273
- if (w > floor(maxInt / baseMinusT)) {
11274
- error("overflow");
11275
- }
11276
- w *= baseMinusT;
11277
- }
11278
- const out = output.length + 1;
11279
- bias2 = adapt(i - oldi, out, oldi == 0);
11280
- if (floor(i / out) > maxInt - n2) {
11281
- error("overflow");
11282
- }
11283
- n2 += floor(i / out);
11284
- i %= out;
11285
- output.splice(i++, 0, n2);
10935
+ if (variants.length < maxVariants) {
10936
+ const allOpIndices = allOps.map((_, i) => i);
10937
+ generateCombinations(allOps, allOpIndices, lowerTerm, maxVariants, add, variants);
11286
10938
  }
11287
- return String.fromCodePoint(...output);
10939
+ return variants;
11288
10940
  }
11289
- function toUnicode(input) {
11290
- return mapDomain(input, function(string) {
11291
- return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string;
11292
- });
10941
+ function normalizeHomoglyphs(text, customMappings = {}) {
10942
+ const mappings = __spreadValues(__spreadValues({}, HOMOGLYPH_MAPPINGS), customMappings);
10943
+ return text.toLowerCase().split("").map((char) => mappings[char] || char).join("");
11293
10944
  }
11294
10945
 
11295
- // ../../internal/utils/src/url.ts
11296
- function isEmail(input) {
11297
- if (input.trim() === "") {
11298
- return false;
10946
+ // ../../internal/utils/src/format.ts
10947
+ var format_exports = {};
10948
+ __export(format_exports, {
10949
+ formatCompactNumber: () => formatCompactNumber,
10950
+ formatFileSize: () => formatFileSize
10951
+ });
10952
+ function formatCompactNumber(num3, options = {}) {
10953
+ const { decimals = 1, fallback = "-" } = options;
10954
+ if (num3 === void 0 || num3 === null) {
10955
+ return fallback;
11299
10956
  }
11300
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
11301
- return emailRegex.test(input);
11302
- }
11303
- function removeHttpProtocol(input) {
11304
- return input.replace(/^https?:\/\//, "");
11305
- }
11306
- function stripDomainWildcardPrefix(domain) {
11307
- const trimmedDomain = domain.trim();
11308
- const strippedDomain = trimmedDomain.startsWith("*.") ? trimmedDomain.slice(2) : trimmedDomain;
11309
- return strippedDomain.length > 0 ? strippedDomain : null;
10957
+ if (num3 >= 1e9) {
10958
+ return `${(num3 / 1e9).toFixed(decimals)}B`;
10959
+ }
10960
+ if (num3 >= 1e6) {
10961
+ return `${(num3 / 1e6).toFixed(decimals)}M`;
10962
+ }
10963
+ if (num3 >= 1e3) {
10964
+ return `${(num3 / 1e3).toFixed(decimals)}K`;
10965
+ }
10966
+ return num3.toString();
11310
10967
  }
11311
- function getDefangedUrl(input) {
11312
- if (!isUrl(input)) {
11313
- console.warn(`[getDefangedUrl] Invalid URL: ${input}, returning input as-is`);
11314
- return input;
10968
+ function formatFileSize(bytes, options = {}) {
10969
+ const { decimals = 1, binary = true, showUnknown = true } = options;
10970
+ if (bytes === null || bytes === void 0 || bytes === "") {
10971
+ return showUnknown ? "Unknown" : "0 B";
11315
10972
  }
11316
- return input.replace(/\./g, "[.]").replace(/(https:\/\/)/g, "hxxps://").replace(/(http:\/\/)/g, "hxxp://").replace(/:\/\//g, "[://]");
10973
+ const size = typeof bytes === "string" ? parseInt(bytes, 10) : bytes;
10974
+ if (isNaN(size) || size < 0) {
10975
+ return showUnknown ? "Unknown" : "0 B";
10976
+ }
10977
+ if (size === 0) {
10978
+ return "0 B";
10979
+ }
10980
+ const unit = binary ? 1024 : 1e3;
10981
+ const units = binary ? ["B", "KB", "MB", "GB", "TB", "PB"] : ["B", "kB", "MB", "GB", "TB", "PB"];
10982
+ const unitIndex = Math.floor(Math.log(size) / Math.log(unit));
10983
+ const finalUnitIndex = Math.min(unitIndex, units.length - 1);
10984
+ const value = size / Math.pow(unit, finalUnitIndex);
10985
+ if (finalUnitIndex === 0) {
10986
+ return `${size} B`;
10987
+ }
10988
+ return `${value.toFixed(decimals)} ${units[finalUnitIndex]}`;
11317
10989
  }
11318
- function getRefangedUrl(input) {
11319
- return input.replace(/hxxps/gi, "https").replace(/hxxp/gi, "http").replace(/\[:\/{2}\]/g, "://").replace(/\[\.\]/g, ".");
10990
+
10991
+ // ../../internal/utils/src/social-profile-url.ts
10992
+ var social_profile_url_exports = {};
10993
+ __export(social_profile_url_exports, {
10994
+ LINKEDIN_PROFILE_URL_PATTERN: () => LINKEDIN_PROFILE_URL_PATTERN,
10995
+ TWITTER_PROFILE_URL_PATTERN: () => TWITTER_PROFILE_URL_PATTERN,
10996
+ isLinkedInProfileUrl: () => isLinkedInProfileUrl,
10997
+ isSupportedSocialProfileUrl: () => isSupportedSocialProfileUrl,
10998
+ isTwitterProfileUrl: () => isTwitterProfileUrl,
10999
+ parseLinkedInProfileUrl: () => parseLinkedInProfileUrl
11000
+ });
11001
+ var TWITTER_PROFILE_URL_PATTERN = /^https?:\/\/(?:www\.)?(?:twitter\.com|x\.com)\/[^/?#]+\/?(?:[?#].*)?$/i;
11002
+ var LINKEDIN_PROFILE_URL_PATTERN = /^https?:\/\/(?:[a-z]{2,3}\.)?linkedin\.com\/(in|company|school)\/([^/?#]+)/i;
11003
+ function isTwitterProfileUrl(url) {
11004
+ return TWITTER_PROFILE_URL_PATTERN.test(url);
11320
11005
  }
11321
- function containsPunycode(url) {
11322
- return url.indexOf("xn--") !== -1;
11006
+ function isLinkedInProfileUrl(url) {
11007
+ return LINKEDIN_PROFILE_URL_PATTERN.test(url);
11323
11008
  }
11324
- function toUnicode2(url) {
11325
- return toUnicode(url);
11009
+ function isSupportedSocialProfileUrl(url) {
11010
+ return isTwitterProfileUrl(url) || isLinkedInProfileUrl(url);
11326
11011
  }
11327
- function convertHttpsToHttp(url) {
11328
- if (url.startsWith("https://")) {
11329
- const httpUrl = new URL(url);
11330
- httpUrl.protocol = "http:";
11331
- return httpUrl.toString();
11332
- }
11333
- throw new Error(`URL is not HTTPS: ${url}`);
11012
+ function humanizeLinkedInHandle(handle) {
11013
+ const withoutTrailingDigits = handle.replace(/-[0-9a-f]{6,}$/i, "");
11014
+ return withoutTrailingDigits.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
11334
11015
  }
11335
- function generateCanonicalIPFSUrl(content) {
11336
- if (!content) {
11337
- return content;
11338
- }
11339
- if (content.includes("ipfs.io")) {
11340
- return content;
11016
+ function parseLinkedInProfileUrl(url) {
11017
+ var _a;
11018
+ const match2 = url.match(LINKEDIN_PROFILE_URL_PATTERN);
11019
+ if (!match2) return null;
11020
+ const pathSegment = (_a = match2[1]) == null ? void 0 : _a.toLowerCase();
11021
+ const rawHandle = match2[2];
11022
+ if (!pathSegment || !rawHandle) return null;
11023
+ let handle;
11024
+ try {
11025
+ handle = decodeURIComponent(rawHandle).trim();
11026
+ } catch (e4) {
11027
+ return null;
11341
11028
  }
11342
- if (content.startsWith("Qm") || content.startsWith("bafy")) {
11343
- return `ipfs.io/ipfs/${content}`;
11029
+ if (!handle) return null;
11030
+ const name = humanizeLinkedInHandle(handle) || handle;
11031
+ const profileUrl = `https://www.linkedin.com/${pathSegment}/${handle}`;
11032
+ return { pathSegment, handle, name, profileUrl };
11033
+ }
11034
+
11035
+ // ../../internal/validation/src/public/detection/configs-create.ts
11036
+ z.object({
11037
+ slug: z.string().min(1).optional().describe(
11038
+ "Organization slug. Defaults to the organization your API key is scoped to, so you only need this when authenticating with a key that spans organizations."
11039
+ ),
11040
+ source: z.nativeEnum(ThreatDetectionSourceKey).describe(
11041
+ "Detection source key, from `GET /detection/sources`. The source must support the `organization` scope; global-only sources cannot be configured per organization."
11042
+ ),
11043
+ status: z.nativeEnum(ThreatDetectionConfigStatus).default(ThreatDetectionConfigStatus.ENABLED).describe("Status to create the config with. Defaults to `ENABLED`."),
11044
+ title: z.string().trim().optional().describe("Optional label for this config"),
11045
+ description: z.string().trim().nullable().optional().describe("Optional human-readable description of what the config does"),
11046
+ cron: z.string().trim().nullable().optional().describe(
11047
+ "Optional custom CRON schedule. Only accepted for sources that run on a schedule; the source's default schedule is used when omitted."
11048
+ ),
11049
+ config: z.record(z.unknown()).optional().describe(
11050
+ "Source-specific configuration, validated against that source's `configSchema` from `GET /detection/sources`. When omitted the source's schema defaults are applied."
11051
+ ),
11052
+ brandId: z.number().int().positive().nullable().optional().describe(
11053
+ "Optional brand to scope this config to. The brand must belong to the same organization. Omit for an organization-wide config."
11054
+ )
11055
+ }).describe(
11056
+ `Create a threat detection config
11057
+
11058
+ Creates the config row that makes a detection source run for your organization. Sources that are disabled by default have no config row, so they cannot be enabled through \`/detection/configs/update\` until one exists.
11059
+
11060
+ A source can have several configs, each scanning with its own query, schedule or brand. Use \`title\` to tell them apart.`
11061
+ );
11062
+ z.object({
11063
+ config: z.object({
11064
+ id: z.number(),
11065
+ source: z.string(),
11066
+ status: z.nativeEnum(ThreatDetectionConfigStatus),
11067
+ title: z.string(),
11068
+ description: z.string().nullable(),
11069
+ cron: z.string().nullable(),
11070
+ config: z.record(z.unknown()),
11071
+ updatedAt: z.date(),
11072
+ brandId: z.number().nullable()
11073
+ })
11074
+ }).describe("Created detection config");
11075
+ z.object({
11076
+ slug: z.string().min(1).optional().describe(
11077
+ "Organization slug. Defaults to the organization your API key is scoped to, so you only need this when authenticating with a key that spans organizations."
11078
+ ),
11079
+ configId: z.number().int().positive().describe("ID of the config to delete, from `/detection/configs/list`")
11080
+ }).describe(
11081
+ `Delete a threat detection config
11082
+
11083
+ Deletes one detection config so it stops scanning. Deleting a config that shares a source with others leaves the others running.
11084
+
11085
+ Deleting the *last* config for a source that is enabled by default for your organization is not permanent: automation re-creates a default config for that source on its next run. To stop such a source durably, set \`status\` to \`DISABLED\` through \`/detection/configs/update\` instead, which automation will not override.`
11086
+ );
11087
+ z.object({
11088
+ success: z.boolean(),
11089
+ id: z.number().describe("ID of the deleted config")
11090
+ }).describe("Deleted detection config");
11091
+ z.object({
11092
+ slug: z.string().min(1),
11093
+ configId: z.number().int().positive(),
11094
+ status: z.nativeEnum(ThreatDetectionConfigStatus).optional(),
11095
+ title: z.string().trim().optional(),
11096
+ description: z.string().trim().nullable().optional(),
11097
+ cron: z.string().trim().nullable().optional(),
11098
+ config: z.record(z.unknown()).optional(),
11099
+ mergeConfig: z.boolean().default(false),
11100
+ brandId: z.number().int().positive().nullable().optional().describe(
11101
+ "Optional brand connection for this detection config. Pass null to clear the link. Only valid for org-scoped configs; the brand must belong to the same organization."
11102
+ )
11103
+ });
11104
+ z.object({
11105
+ config: z.object({
11106
+ id: z.number(),
11107
+ source: z.string(),
11108
+ status: z.nativeEnum(ThreatDetectionConfigStatus),
11109
+ title: z.string(),
11110
+ description: z.string().nullable(),
11111
+ cron: z.string().nullable(),
11112
+ config: z.record(z.unknown()),
11113
+ updatedAt: z.date(),
11114
+ brandId: z.number().nullable()
11115
+ })
11116
+ });
11117
+ z.object({
11118
+ slug: z.string().min(1),
11119
+ source: z.string().optional(),
11120
+ minResults: z.number().int().min(0).default(1),
11121
+ lookbackHours: z.number().int().min(1).default(24 * 7),
11122
+ runBeforeValidate: z.boolean().default(false),
11123
+ includeDisabled: z.boolean().default(false)
11124
+ });
11125
+ z.object({
11126
+ ok: z.boolean(),
11127
+ summary: z.object({
11128
+ checkedConfigs: z.number(),
11129
+ passingConfigs: z.number(),
11130
+ failingConfigs: z.number(),
11131
+ lookbackHours: z.number(),
11132
+ minResults: z.number()
11133
+ }),
11134
+ validations: z.array(
11135
+ z.object({
11136
+ configId: z.number(),
11137
+ source: z.string(),
11138
+ status: z.nativeEnum(ThreatDetectionConfigStatus),
11139
+ ran: z.boolean(),
11140
+ runOk: z.boolean(),
11141
+ runMessage: z.string().nullable(),
11142
+ recentResultCount: z.number(),
11143
+ valid: z.boolean()
11144
+ })
11145
+ )
11146
+ });
11147
+ z.object({
11148
+ slug: z.string().min(1),
11149
+ configId: z.number().int().positive().optional(),
11150
+ source: z.string().min(1).optional(),
11151
+ includeDisabled: z.boolean().default(false)
11152
+ });
11153
+ z.object({
11154
+ ranCount: z.number(),
11155
+ successCount: z.number(),
11156
+ failedCount: z.number(),
11157
+ results: z.array(
11158
+ z.object({
11159
+ configId: z.number(),
11160
+ source: z.string(),
11161
+ ok: z.boolean(),
11162
+ message: z.string().nullable(),
11163
+ assetsCount: z.number()
11164
+ })
11165
+ )
11166
+ });
11167
+ z.object({
11168
+ slug: z.string().min(1).optional().describe(
11169
+ "Organization slug. Defaults to the organization your API key is scoped to, so you only need this when authenticating with a key that spans organizations. Sources that do not apply to the organization's industry are omitted."
11170
+ )
11171
+ }).describe(
11172
+ `List available threat detection sources
11173
+
11174
+ Returns the catalog of detection sources ChainPatrol can run, including the scopes each source supports and the JSON Schema its \`config\` object must satisfy. Use this to discover valid \`source\` keys before creating or updating a detection config.`
11175
+ );
11176
+ var detectionSourceSchema = z.object({
11177
+ key: z.string().describe("Detection source key (e.g. google_search, certstream, dns_twist)"),
11178
+ label: z.string().describe("Human-readable source name"),
11179
+ description: z.string().describe("What this source detects"),
11180
+ scopes: z.array(z.nativeEnum(ThreatDetectionScope)).describe(
11181
+ "Scopes this source supports. A source without `organization` cannot be configured per-org and runs globally for all organizations."
11182
+ ),
11183
+ isPullBased: z.boolean().describe(
11184
+ "Whether the source runs on a schedule (pull-based). Push-based sources such as webhooks ignore `cron` and cannot be run on demand."
11185
+ ),
11186
+ brandScope: z.enum(["organization_only", "all_brands"]).describe(
11187
+ "Which brands this source fans out to. `organization_only` sources only use brands of type `ORGANIZATION`; `all_brands` sources use every brand in the organization."
11188
+ ),
11189
+ industries: z.array(z.string()).describe(
11190
+ "Industries this source applies to. Empty means it applies to every industry."
11191
+ ),
11192
+ protectedAssetTypes: z.array(z.string()).describe(
11193
+ "Asset types this source monitors. Empty when the source does not key off protected assets."
11194
+ ),
11195
+ configSchema: z.record(z.unknown()).nullable().describe(
11196
+ "JSON Schema for this source's `config` object, for use with `/detection/configs/update`. `null` when the source takes no configuration."
11197
+ )
11198
+ });
11199
+ z.object({
11200
+ sources: z.array(detectionSourceSchema).describe("Available detection sources")
11201
+ }).describe("Successful operation");
11202
+ var DetectionDriftThresholdsSchema = z.object({
11203
+ zeroResultsMaxHours: z.number().int().positive().default(72),
11204
+ noisyResultsPerDay: z.number().positive().default(100),
11205
+ noisyAllowedRatioThreshold: z.number().min(0).max(1).default(0.6),
11206
+ staleConfigDays: z.number().int().positive().default(30)
11207
+ });
11208
+ z.object({
11209
+ slug: z.string().min(1),
11210
+ lookbackHours: z.number().int().positive().default(168),
11211
+ startDate: z.date().optional(),
11212
+ endDate: z.date().optional(),
11213
+ source: z.string().min(1).optional(),
11214
+ configIds: z.array(z.number().int().positive()).optional(),
11215
+ includeDisabled: z.boolean().default(false),
11216
+ thresholds: DetectionDriftThresholdsSchema.optional()
11217
+ }).refine(
11218
+ (value) => !value.startDate && !value.endDate || Boolean(value.startDate) && Boolean(value.endDate),
11219
+ {
11220
+ message: "Provide both startDate and endDate when using explicit date range",
11221
+ path: ["startDate"]
11344
11222
  }
11345
- return content;
11346
- }
11347
- function isWalrusSite(content) {
11348
- return content.includes(".walrus.site") || content.includes(".walrus.host") || content.includes(".wal.app") || content.includes(".wal.site");
11349
- }
11350
- function getFaviconUrl(content) {
11351
- const normalizedUrl = getNormalizedUrl(content);
11352
- return `https://icons.duckduckgo.com/ip3/${normalizedUrl.hostname}.ico`;
11353
- }
11354
- function sanitizeHttpUrl(value) {
11355
- if (typeof value !== "string" || value.length === 0) {
11356
- return null;
11223
+ );
11224
+ var DetectionDriftSignalSchema = z.object({
11225
+ signal: z.enum(["zero_results_too_long", "noisy_source", "stale_query"]),
11226
+ configId: z.number().int().positive(),
11227
+ source: z.string(),
11228
+ title: z.string().nullable(),
11229
+ status: z.string(),
11230
+ severity: z.enum(["low", "medium", "high"]),
11231
+ details: z.record(z.unknown())
11232
+ });
11233
+ z.object({
11234
+ ok: z.boolean(),
11235
+ range: z.object({
11236
+ startDate: z.date(),
11237
+ endDate: z.date(),
11238
+ lookbackHours: z.number().int().positive()
11239
+ }),
11240
+ thresholds: DetectionDriftThresholdsSchema,
11241
+ summary: z.object({
11242
+ checkedConfigs: z.number().int().nonnegative(),
11243
+ signalCount: z.number().int().nonnegative(),
11244
+ zeroResultsCount: z.number().int().nonnegative(),
11245
+ noisyCount: z.number().int().nonnegative(),
11246
+ staleCount: z.number().int().nonnegative()
11247
+ }),
11248
+ signals: z.array(DetectionDriftSignalSchema)
11249
+ });
11250
+ var BucketsSchema = z.object({
11251
+ lt24h: z.number().int().nonnegative(),
11252
+ h24to72: z.number().int().nonnegative(),
11253
+ h72to168: z.number().int().nonnegative(),
11254
+ gte168h: z.number().int().nonnegative()
11255
+ });
11256
+ z.object({
11257
+ slug: z.string().min(1).optional(),
11258
+ all: z.boolean().default(false),
11259
+ windowHours: z.number().int().positive().default(168)
11260
+ });
11261
+ z.object({
11262
+ generatedAt: z.date(),
11263
+ scope: z.object({
11264
+ slug: z.string().nullable(),
11265
+ all: z.boolean()
11266
+ }),
11267
+ reviewQueue: z.object({
11268
+ totalPendingProposals: z.number().int().nonnegative(),
11269
+ distinctReports: z.number().int().nonnegative(),
11270
+ ageBuckets: BucketsSchema,
11271
+ slaBuckets: z.object({
11272
+ breached: z.number().int().nonnegative(),
11273
+ dueWithin24h: z.number().int().nonnegative(),
11274
+ dueWithin72h: z.number().int().nonnegative(),
11275
+ beyond72h: z.number().int().nonnegative(),
11276
+ missingSla: z.number().int().nonnegative()
11277
+ }),
11278
+ byOrg: z.array(
11279
+ z.object({
11280
+ slug: z.string(),
11281
+ pendingProposals: z.number().int().nonnegative()
11282
+ })
11283
+ )
11284
+ }),
11285
+ takedownQueue: z.object({
11286
+ totalOpen: z.number().int().nonnegative(),
11287
+ statusCounts: z.object({
11288
+ todo: z.number().int().nonnegative(),
11289
+ inProgress: z.number().int().nonnegative(),
11290
+ pendingInput: z.number().int().nonnegative()
11291
+ }),
11292
+ ageBuckets: BucketsSchema,
11293
+ staleInProgress: z.number().int().nonnegative(),
11294
+ byOrg: z.array(
11295
+ z.object({
11296
+ slug: z.string(),
11297
+ openTakedowns: z.number().int().nonnegative()
11298
+ })
11299
+ )
11300
+ })
11301
+ });
11302
+ var HealthcheckCategorySchema = z.enum([
11303
+ "detection",
11304
+ "reviewing",
11305
+ "blocklisting",
11306
+ "takedowns",
11307
+ "assets",
11308
+ "organization"
11309
+ ]);
11310
+ var HealthcheckSeveritySchema = z.enum(["ok", "warn", "fail"]);
11311
+ var HealthcheckFindingSchema = z.object({
11312
+ kind: z.string(),
11313
+ ref: z.string().nullable(),
11314
+ message: z.string(),
11315
+ severity: z.enum(["warn", "fail"])
11316
+ });
11317
+ z.object({
11318
+ id: z.string(),
11319
+ title: z.string(),
11320
+ category: HealthcheckCategorySchema,
11321
+ generatedAt: z.date(),
11322
+ scope: z.object({
11323
+ slug: z.string().nullable()
11324
+ }),
11325
+ ok: z.boolean(),
11326
+ severity: HealthcheckSeveritySchema,
11327
+ observed: z.record(z.union([z.number(), z.string(), z.boolean()]).nullable()),
11328
+ threshold: z.record(z.union([z.number(), z.string(), z.boolean()]).nullable()),
11329
+ findings: z.array(HealthcheckFindingSchema),
11330
+ suggestedAction: z.string().nullable(),
11331
+ appUrl: z.string().nullable()
11332
+ });
11333
+
11334
+ // ../../internal/validation/src/public/healthchecks/assets-dead-asset-spike.ts
11335
+ z.object({
11336
+ slug: z.string().min(1),
11337
+ windowHours: z.number().int().positive().default(24),
11338
+ baselineDays: z.number().int().positive().default(7),
11339
+ warnMultiplier: z.number().positive().default(2),
11340
+ failMultiplier: z.number().positive().default(4),
11341
+ minSpikeCount: z.number().int().min(1).default(10)
11342
+ });
11343
+ z.object({});
11344
+ var HealthcheckRegistryEntrySchema = z.object({
11345
+ id: z.string(),
11346
+ title: z.string(),
11347
+ description: z.string(),
11348
+ category: HealthcheckCategorySchema,
11349
+ implemented: z.boolean(),
11350
+ endpoint: z.string().nullable(),
11351
+ defaultThreshold: z.record(z.union([z.number(), z.string()])).optional(),
11352
+ notImplementedReason: z.string().optional()
11353
+ });
11354
+ z.object({
11355
+ checks: z.array(HealthcheckRegistryEntrySchema)
11356
+ });
11357
+ z.object({
11358
+ slug: z.string().min(1)
11359
+ });
11360
+ z.object({
11361
+ slug: z.string().min(1),
11362
+ warnThreshold: z.number().int().nonnegative().default(50),
11363
+ failThreshold: z.number().int().nonnegative().default(100)
11364
+ });
11365
+ z.object({
11366
+ slug: z.string().min(1),
11367
+ warnAgeHours: z.number().int().positive().default(24 * 7),
11368
+ failAgeHours: z.number().int().positive().default(24 * 14)
11369
+ });
11370
+ z.object({
11371
+ slug: z.string().min(1),
11372
+ warnAgeHours: z.number().int().nonnegative().default(24 * 30),
11373
+ failAgeHours: z.number().int().nonnegative().default(24 * 60)
11374
+ });
11375
+ z.object({
11376
+ slug: z.string().min(1),
11377
+ lookbackHours: z.number().int().positive().default(24 * 7),
11378
+ warnThreshold: z.number().int().nonnegative().default(3),
11379
+ failThreshold: z.number().int().nonnegative().default(10)
11380
+ });
11381
+ z.object({
11382
+ slug: z.string().min(1),
11383
+ warnThreshold: z.number().int().nonnegative().default(30),
11384
+ failThreshold: z.number().int().nonnegative().default(75)
11385
+ });
11386
+ z.object({
11387
+ slug: z.string().min(1),
11388
+ staleThresholdHours: z.number().int().positive().default(24 * 7),
11389
+ warnThreshold: z.number().int().nonnegative().default(1),
11390
+ failThreshold: z.number().int().nonnegative().default(5)
11391
+ });
11392
+ z.object({
11393
+ slug: z.string().min(1),
11394
+ warnThreshold: z.number().int().nonnegative().default(50),
11395
+ failThreshold: z.number().int().nonnegative().default(100)
11396
+ });
11397
+ var BreakdownBySchema = z.enum(["day", "type", "brand"]);
11398
+ z.object({
11399
+ slug: z.string().min(1),
11400
+ by: BreakdownBySchema,
11401
+ startDate: z.date().optional(),
11402
+ endDate: z.date().optional(),
11403
+ brandIds: z.array(z.number().int().positive()).optional()
11404
+ });
11405
+ z.object({
11406
+ by: BreakdownBySchema,
11407
+ points: z.array(
11408
+ z.object({
11409
+ key: z.string(),
11410
+ count: z.number(),
11411
+ date: z.string().optional(),
11412
+ type: z.string().optional(),
11413
+ brandId: z.number().optional(),
11414
+ brandSlug: z.string().optional(),
11415
+ brandName: z.string().optional()
11416
+ })
11417
+ )
11418
+ });
11419
+ z.object({
11420
+ slug: z.string().min(1),
11421
+ startDate: z.date(),
11422
+ endDate: z.date(),
11423
+ brandIds: z.array(z.number().int().positive()).optional()
11424
+ });
11425
+ z.object({
11426
+ metric: z.literal("new_threats"),
11427
+ found: z.number(),
11428
+ range: z.object({
11429
+ startDate: z.date(),
11430
+ endDate: z.date()
11431
+ })
11432
+ });
11433
+ z.object({
11434
+ slug: z.string().min(1),
11435
+ startDate: z.date().optional(),
11436
+ endDate: z.date().optional(),
11437
+ brandIds: z.array(z.number().int().positive()).optional()
11438
+ });
11439
+ z.object({
11440
+ metrics: z.object({
11441
+ reports: z.number(),
11442
+ newThreats: z.number(),
11443
+ threatsWatchlisted: z.number(),
11444
+ takedownsFiled: z.number(),
11445
+ takedownsCompleted: z.number(),
11446
+ domainThreats: z.number(),
11447
+ twitterThreats: z.number(),
11448
+ telegramThreats: z.number(),
11449
+ otherThreats: z.number()
11450
+ }),
11451
+ blockedByDay: z.array(
11452
+ z.object({
11453
+ date: z.string(),
11454
+ count: z.number()
11455
+ })
11456
+ ),
11457
+ blockedByType: z.array(
11458
+ z.object({
11459
+ type: z.string(),
11460
+ count: z.number()
11461
+ })
11462
+ )
11463
+ });
11464
+ var DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
11465
+ var utcDateSchema = (endOfDay) => z.preprocess((value) => {
11466
+ if (typeof value !== "string") {
11467
+ return value;
11357
11468
  }
11358
- try {
11359
- const parsed = new URL(value);
11360
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
11361
- return null;
11362
- }
11363
- return parsed.toString();
11364
- } catch (e4) {
11365
- return null;
11469
+ const parsed = DateTime.fromISO(value, { zone: "utc" });
11470
+ if (!parsed.isValid) {
11471
+ return new Date(Number.NaN);
11366
11472
  }
11367
- }
11368
- var URL_REGEX = /https?:\/\/[^\s"'<>\])]*/g;
11473
+ return endOfDay && DATE_ONLY_PATTERN.test(value) ? parsed.endOf("day").toJSDate() : parsed.toJSDate();
11474
+ }, z.coerce.date());
11475
+ z.object({
11476
+ slug: z.string().min(1).describe("Organization slug"),
11477
+ startDate: utcDateSchema(false).optional().describe(
11478
+ "Only include takedowns completed on or after this date. A date-only value (YYYY-MM-DD) starts at midnight UTC"
11479
+ ),
11480
+ endDate: utcDateSchema(true).optional().describe(
11481
+ "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"
11482
+ ),
11483
+ blockLabel: z.string().optional().describe(
11484
+ 'Only include assets blocked with this review label, e.g. "Brand Impersonation", "Employee Impersonation" or "Targeting Org Users"'
11485
+ ),
11486
+ brandType: z.nativeEnum(BrandType).optional().describe("Only include assets belonging to brands of this type"),
11487
+ countryCodes: z.array(z.string().length(2)).optional().describe("Only include assets scanned from these ISO 3166-1 alpha-2 countries"),
11488
+ brandIds: z.array(z.number().int().positive()).optional().describe("Only include assets belonging to these brands")
11489
+ });
11490
+ z.object({
11491
+ byAssetType: z.array(
11492
+ z.object({
11493
+ assetType: z.nativeEnum(AssetType).describe("Asset type the median is computed over"),
11494
+ medianTakedownMinutes: z.number(),
11495
+ medianTakedownHours: z.number(),
11496
+ medianTakedownDays: z.number(),
11497
+ count: z.number().describe("Number of completed takedowns behind the median")
11498
+ })
11499
+ ).describe(
11500
+ "Median time from takedown start to completion, one entry per asset type, ascending by median"
11501
+ )
11502
+ });
11503
+ z.object({
11504
+ slug: z.string().min(1).describe("Organization slug"),
11505
+ months: z.number().int().min(2).max(36).default(12).describe("Size of the trailing window in whole months, including the current month"),
11506
+ assetTypes: z.array(z.nativeEnum(AssetType)).max(5).optional().describe(
11507
+ "Break the trend down by these asset types, one series each. Omit for a single series pooled across every asset type"
11508
+ ),
11509
+ blockLabel: z.string().optional().describe(
11510
+ 'Only include assets blocked with this review label, e.g. "Brand Impersonation", "Employee Impersonation" or "Targeting Org Users"'
11511
+ ),
11512
+ brandType: z.nativeEnum(BrandType).optional().describe("Only include assets belonging to brands of this type"),
11513
+ countryCodes: z.array(z.string().length(2)).optional().describe("Only include assets scanned from these ISO 3166-1 alpha-2 countries"),
11514
+ brandIds: z.array(z.number().int().positive()).optional().describe("Only include assets belonging to these brands")
11515
+ });
11516
+ var MetricsTakedownTimeTrendPointSchema = z.object({
11517
+ period: z.string().describe("Month the takedowns completed in, as a yyyy-MM key"),
11518
+ medianTakedownMinutes: z.number().nullable().describe("Null when no takedowns completed in this month"),
11519
+ medianTakedownHours: z.number().nullable(),
11520
+ medianTakedownDays: z.number().nullable(),
11521
+ count: z.number().describe("Number of completed takedowns behind the median")
11522
+ });
11523
+ var MetricsTakedownTimeTrendChangeSchema = z.object({
11524
+ latest: MetricsTakedownTimeTrendPointSchema.nullable().describe(
11525
+ "Most recent month in the window that had completed takedowns"
11526
+ ),
11527
+ previous: MetricsTakedownTimeTrendPointSchema.nullable().describe(
11528
+ "Month with completed takedowns immediately before `latest`, skipping empty months"
11529
+ ),
11530
+ percentChange: z.number().nullable().describe(
11531
+ "Change in the median from `previous` to `latest`, as a percentage. Negative means takedowns got faster. Null when there is no comparable earlier month"
11532
+ ),
11533
+ direction: z.enum(["improved", "worsened", "unchanged"]).nullable().describe("Sign of `percentChange`, read as lower-is-better. Null when it is null")
11534
+ });
11535
+ z.object({
11536
+ months: z.number().describe("Size of the trailing window that was used"),
11537
+ periods: z.array(z.string()).describe("Every yyyy-MM key in the window, oldest first"),
11538
+ series: z.array(
11539
+ z.object({
11540
+ assetType: z.nativeEnum(AssetType).nullable().describe("Null for the series pooled across every asset type"),
11541
+ points: z.array(MetricsTakedownTimeTrendPointSchema).describe(
11542
+ "One point per month in the window, oldest first. Months with no completed takedowns carry a null median"
11543
+ ),
11544
+ change: MetricsTakedownTimeTrendChangeSchema.describe(
11545
+ "Month-over-month comparison for this series"
11546
+ )
11547
+ })
11548
+ ).describe(
11549
+ "One series per requested asset type, in the order requested, or a single pooled series when no asset types were given"
11550
+ )
11551
+ });
11552
+ z.object({
11553
+ slug: z.string().optional().describe(
11554
+ "Organization slug. Optional for organization-scoped API keys, which resolve the organization from the key itself. Required when your credentials can reach more than one organization."
11555
+ ),
11556
+ type: z.nativeEnum(AssetType).optional().describe("Filter by asset type (URL, ADDRESS, etc.)"),
11557
+ groupId: z.number().int().optional().describe(
11558
+ "Filter by group ID. Use -1 for ungrouped assets only. Omit for all assets."
11559
+ ),
11560
+ query: z.string().optional().describe("Search query to filter assets by content"),
11561
+ per_page: z.number().int().min(1).max(1e3).optional().default(100).describe("The number of assets to return per page (max 1000)"),
11562
+ next_page: z.string().optional().nullable().describe("Cursor for fetching the next page of results")
11563
+ }).describe(
11564
+ `List organization assets request body
11369
11565
 
11370
- // ../../internal/utils/src/email.ts
11371
- var email_exports = {};
11372
- __export(email_exports, {
11373
- extractTextFromGmailPayload: () => extractTextFromGmailPayload,
11374
- getDomainFromEmail: () => getDomainFromEmail,
11375
- getNameFromEmail: () => getNameFromEmail
11566
+ Returns all assets belonging to the organization identified by \`slug\`, or \u2014
11567
+ when \`slug\` is omitted \u2014 the organization associated with your API key.
11568
+ Supports filtering by type, group, and search query.`
11569
+ );
11570
+ var organizationAssetItemSchema = z.object({
11571
+ id: z.number().describe("Asset ID"),
11572
+ content: z.string().describe("Asset content (URL, address, handle, etc.)"),
11573
+ type: z.nativeEnum(AssetType).describe("Asset type"),
11574
+ status: z.nativeEnum(AssetStatus).describe("Asset status"),
11575
+ name: z.string().nullable().describe("Asset display name"),
11576
+ description: z.string().nullable().describe("Asset description"),
11577
+ group: z.object({
11578
+ id: z.number().describe("Group ID"),
11579
+ name: z.string().describe("Group name")
11580
+ }).nullable().describe("Asset group information"),
11581
+ livenessStatus: z.nativeEnum(LivenessStatus).nullable().describe(
11582
+ "Whether the asset is currently reachable (`ALIVE`), gone (`DEAD`), or hasn't been checked (`UNKNOWN`). `null` when liveness has never been evaluated."
11583
+ ),
11584
+ blockedAt: z.date().nullable().describe(
11585
+ "When the asset transitioned to BLOCKED status. `null` for non-blocked assets. Distinct from `updatedAt`."
11586
+ ),
11587
+ createdAt: z.date().describe("When the asset was created"),
11588
+ updatedAt: z.date().describe("When the asset was last updated")
11376
11589
  });
11377
- function getDomainFromEmail(email) {
11378
- return email.split("@")[1];
11379
- }
11380
- function getNameFromEmail(email) {
11381
- return email.split("@")[0];
11382
- }
11383
- function extractTextFromGmailPayload(payload) {
11384
- var _a;
11385
- if (!payload) return "";
11386
- if ((_a = payload.body) == null ? void 0 : _a.data) {
11387
- if (payload.mimeType === "text/plain" || payload.mimeType === "text/html") {
11388
- return Buffer.from(payload.body.data, "base64url").toString("utf-8");
11389
- }
11390
- }
11391
- if (payload.parts) {
11392
- if (payload.mimeType === "multipart/alternative") {
11393
- const plainTextPart = payload.parts.find((part) => part.mimeType === "text/plain");
11394
- if (plainTextPart) {
11395
- return extractTextFromGmailPayload(plainTextPart);
11396
- }
11397
- const htmlPart = payload.parts.find((part) => part.mimeType === "text/html");
11398
- if (htmlPart) {
11399
- return extractTextFromGmailPayload(htmlPart);
11400
- }
11401
- for (const part of payload.parts) {
11402
- const text = extractTextFromGmailPayload(part);
11403
- if (text) return text;
11404
- }
11405
- }
11406
- return payload.parts.map((part) => extractTextFromGmailPayload(part)).join("\n");
11407
- }
11408
- return "";
11409
- }
11590
+ z.object({
11591
+ assets: z.array(organizationAssetItemSchema).describe("List of assets"),
11592
+ next_page: z.string().nullable().optional().describe("Cursor for fetching the next page of results")
11593
+ }).describe("Successful operation");
11594
+ var addAssetItemSchema = z.object({
11595
+ content: z.string().describe("Asset content (URL, address, handle, etc.)"),
11596
+ name: z.string().optional().describe("Optional display name for the asset"),
11597
+ description: z.string().optional().describe("Optional description for the asset"),
11598
+ groupId: z.number().int().positive().optional().describe("Optional group ID to assign the asset to")
11599
+ });
11600
+ z.object({
11601
+ assets: z.array(addAssetItemSchema).min(1).max(1e3).describe("Array of assets to add (max 1000 per request)")
11602
+ }).describe(
11603
+ `Add assets to organization allowlist
11604
+
11605
+ Batch add multiple assets to your organization's allowlist.
11606
+ Each asset will be automatically parsed and classified.
11607
+ Assets will be auto-approved as ALLOWED status.`
11608
+ );
11609
+ var addAssetResultSchema = z.object({
11610
+ content: z.string().describe("Asset content"),
11611
+ success: z.boolean().describe("Whether the asset was added successfully"),
11612
+ id: z.number().optional().describe("Asset ID if successful"),
11613
+ error: z.string().optional().describe("Error message if failed")
11614
+ });
11615
+ z.object({
11616
+ results: z.array(addAssetResultSchema).describe("Results for each asset"),
11617
+ successCount: z.number().describe("Number of assets successfully added"),
11618
+ errorCount: z.number().describe("Number of assets that failed to add")
11619
+ }).describe("Batch add operation results");
11620
+ z.object({
11621
+ assetId: z.number().int().positive().describe("ID of the asset to update"),
11622
+ name: z.string().optional().describe("New display name for the asset"),
11623
+ description: z.string().nullable().optional().describe("New description for the asset"),
11624
+ groupId: z.number().int().positive().nullable().optional().describe("New group ID (null to ungroup)")
11625
+ }).describe(
11626
+ `Update an organization asset
11627
+
11628
+ Update the name, description, or group assignment of an asset.`
11629
+ );
11630
+ z.object({
11631
+ id: z.number().describe("Asset ID"),
11632
+ content: z.string().describe("Asset content"),
11633
+ name: z.string().nullable().describe("Asset display name"),
11634
+ description: z.string().nullable().describe("Asset description"),
11635
+ groupId: z.number().nullable().describe("Group ID")
11636
+ }).describe("Updated asset");
11637
+ z.object({
11638
+ assetId: z.number().int().positive().describe("ID of the asset to remove")
11639
+ }).describe(
11640
+ `Remove an asset from the organization
11641
+
11642
+ This removes the asset from the organization's allowlist.`
11643
+ );
11644
+ z.object({
11645
+ success: z.boolean().describe("Whether the asset was removed successfully"),
11646
+ id: z.number().describe("Asset ID that was removed")
11647
+ }).describe("Delete operation result");
11648
+ z.object({}).describe(
11649
+ `List organization asset groups
11650
+
11651
+ Returns all asset groups belonging to the organization associated with your API key.`
11652
+ );
11653
+ var assetGroupItemSchema = z.object({
11654
+ id: z.number().describe("Group ID"),
11655
+ name: z.string().describe("Group name"),
11656
+ assetCount: z.number().describe("Number of assets in this group")
11657
+ });
11658
+ z.object({
11659
+ groups: z.array(assetGroupItemSchema).describe("List of asset groups")
11660
+ }).describe("Successful operation");
11661
+ z.object({
11662
+ name: z.string().min(1).max(255).describe("Name for the new group")
11663
+ }).describe(
11664
+ `Create a new asset group
11665
+
11666
+ Creates a new asset group for organizing your organization's assets.`
11667
+ );
11668
+ z.object({
11669
+ id: z.number().describe("Created group ID"),
11670
+ name: z.string().describe("Group name")
11671
+ }).describe("Created group");
11672
+ z.object({
11673
+ groupId: z.number().int().positive().describe("ID of the group to update"),
11674
+ name: z.string().min(1).max(255).describe("New name for the group")
11675
+ }).describe(
11676
+ `Update an asset group
11677
+
11678
+ Rename an existing asset group.`
11679
+ );
11680
+ z.object({
11681
+ id: z.number().describe("Group ID"),
11682
+ name: z.string().describe("Updated group name")
11683
+ }).describe("Updated group");
11684
+ z.object({
11685
+ groupId: z.number().int().positive().describe("ID of the group to delete")
11686
+ }).describe(
11687
+ `Delete an asset group
11688
+
11689
+ Deletes an asset group. Assets in this group will become ungrouped.`
11690
+ );
11691
+ z.object({
11692
+ success: z.boolean().describe("Whether the group was deleted successfully"),
11693
+ id: z.number().describe("Group ID that was deleted"),
11694
+ unassignedAssetCount: z.number().describe("Number of assets that were unassigned from this group")
11695
+ }).describe("Delete operation result");
11696
+ z.object({}).describe(
11697
+ `List organization brands
11410
11698
 
11411
- // ../../internal/utils/src/vercel.ts
11412
- var vercel_exports = {};
11413
- __export(vercel_exports, {
11414
- checkVercelEnv: () => checkVercelEnv
11699
+ Returns all brands belonging to the organization associated with your API key,
11700
+ including sub-brands (\`ORGANIZATION\`), individual / employee brands
11701
+ (\`INDIVIDUAL\`), and product brands (\`PRODUCT\`). Soft-deleted brands are
11702
+ excluded.`
11703
+ );
11704
+ var brandLegalDocumentSchema = z.object({
11705
+ present: z.boolean().describe("Whether the brand has this document attached"),
11706
+ fileName: z.string().nullable().describe("Original filename of the uploaded document (null when not present)"),
11707
+ fileUrl: z.string().nullable().describe("Direct URL to view or download the document (null when not present)")
11415
11708
  });
11416
- var checkVercelEnv = ({ envs }) => {
11417
- var _a;
11418
- const vercelEnv = (_a = process.env.VERCEL_ENV) != null ? _a : "development";
11419
- if (!envs.includes(vercelEnv)) {
11420
- return {
11421
- ok: false,
11422
- message: `Vercel environment is ${vercelEnv}, but expected ${envs.join(" or ")}`
11423
- };
11424
- }
11425
- return { ok: true, message: "" };
11426
- };
11427
-
11428
- // ../../internal/utils/src/delay.ts
11429
- var delay_exports = {};
11430
- __export(delay_exports, {
11431
- delay: () => delay
11709
+ var brandTrademarkRegistrationSchema = z.object({
11710
+ id: z.number().describe("Trademark registration ID"),
11711
+ brandName: z.string().describe("Trademarked brand name as it appears on the registration"),
11712
+ trademarkOffice: z.string().describe("Issuing trademark office (e.g. `USPTO`, `EUIPO`)"),
11713
+ registrationNumber: z.string().describe("Registration number assigned by the office"),
11714
+ goodsAndServicesClass: z.string().describe("Nice Classification class(es) the registration covers"),
11715
+ rightsOwnerName: z.string().nullable().describe("Legal entity the trademark is registered to, if recorded"),
11716
+ registrationPageUrl: z.string().nullable().describe("Public URL on the trademark office's site, if recorded"),
11717
+ certificateFileName: z.string().nullable().describe(
11718
+ "Original filename of the uploaded certificate PDF (null when no certificate is attached)"
11719
+ ),
11720
+ certificateFileUrl: z.string().nullable().describe(
11721
+ "Direct URL to view or download the certificate PDF (null when no certificate is attached)"
11722
+ )
11432
11723
  });
11433
- var delay = (ms) => {
11434
- return new Promise((resolve) => setTimeout(resolve, ms));
11435
- };
11436
-
11437
- // ../../internal/utils/src/whois.ts
11438
- var whois_exports = {};
11439
- __export(whois_exports, {
11440
- extractWhoisCountry: () => extractWhoisCountry,
11441
- extractWhoisPayload: () => extractWhoisPayload,
11442
- normalizeRegistrar: () => normalizeRegistrar
11724
+ var brandItemSchema = z.object({
11725
+ id: z.number().describe("Brand ID"),
11726
+ slug: z.string().describe("Brand slug (stable, URL-safe identifier)"),
11727
+ name: z.string().describe("Display name"),
11728
+ type: z.nativeEnum(BrandType).describe(
11729
+ "Brand type: `ORGANIZATION` for parent brands, `INDIVIDUAL` for employee or person brands, `PRODUCT` for a specific product or service offering"
11730
+ ),
11731
+ description: z.string().nullable().describe("Free-form description, if set"),
11732
+ avatarUrl: z.string().nullable().describe("URL of the brand's avatar / logo image"),
11733
+ websiteUrl: z.string().nullable().describe("Official brand website URL"),
11734
+ twitterHandle: z.string().nullable().describe("Official Twitter / X handle (without @)"),
11735
+ brandColors: z.array(z.string()).describe("HEX color strings associated with the brand (e.g. `#FF0000`)"),
11736
+ includedTerms: z.array(z.string()).describe("Terms that should be included when matching this brand"),
11737
+ excludedTerms: z.array(z.string()).describe("Terms that should be excluded when matching this brand"),
11738
+ tickers: z.array(z.string()).describe("Ticker symbols associated with the brand (e.g. `$JUP`)"),
11739
+ brandGroupId: z.number().nullable().describe(
11740
+ "Group this brand belongs to (only set for `INDIVIDUAL` and `PRODUCT` brands)"
11741
+ ),
11742
+ createdAt: z.date().describe("When the brand was created"),
11743
+ useOrganizationDocs: z.boolean().describe(
11744
+ "When true, this brand inherits its Letter of Authorization and Power of Attorney from the organization rather than carrying its own. The `legalDocuments` block below always reflects the brand-level attachments \u2014 read `/user/orgs/{slug}` for the org-level fallbacks."
11745
+ ),
11746
+ legalDocuments: z.object({
11747
+ letterOfAuthorization: brandLegalDocumentSchema,
11748
+ powerOfAttorney: brandLegalDocumentSchema
11749
+ }).describe("Brand-level Letter of Authorization and Power of Attorney attachments"),
11750
+ trademarkRegistrations: z.array(brandTrademarkRegistrationSchema).describe(
11751
+ "Trademark registrations attached to this brand. An empty array means no trademarks are on file for the brand \u2014 use this to identify brands that still need them added."
11752
+ )
11443
11753
  });
11444
- function extractWhoisPayload(raw) {
11445
- var _a;
11446
- const first = Array.isArray(raw) ? (_a = raw.find((entry) => entry !== null && typeof entry === "object")) != null ? _a : {} : raw;
11447
- if (!first || typeof first !== "object") {
11448
- return {};
11449
- }
11450
- const maybeData = first.data;
11451
- if (maybeData && typeof maybeData === "object" && !Array.isArray(maybeData)) {
11452
- return maybeData;
11453
- }
11454
- return first;
11455
- }
11456
- var WHOIS_EMPTY_VALUES = /* @__PURE__ */ new Set(["", "none", "null"]);
11457
- var WHOIS_COUNTRY_CODE_KEY_ALIASES = /* @__PURE__ */ new Set(["countrycode", "registrantcountrycode"]);
11458
- var WHOIS_COUNTRY_KEY_ALIASES = /* @__PURE__ */ new Set([
11459
- "country",
11460
- "countryname",
11461
- "registrantcountry",
11462
- "registrantcountryname"
11463
- ]);
11464
- function normalizeWhoisKey(key) {
11465
- return key.toLowerCase().replace(/[^a-z0-9]/g, "");
11466
- }
11467
- function normalizeRegistrar(value) {
11468
- return value.toLowerCase().replace(/[^a-z0-9]/g, "");
11469
- }
11470
- function parseWhoisString(value) {
11471
- if (typeof value !== "string") {
11472
- return void 0;
11473
- }
11474
- const trimmedValue = value.trim();
11475
- if (WHOIS_EMPTY_VALUES.has(trimmedValue.toLowerCase())) {
11476
- return void 0;
11477
- }
11478
- return trimmedValue;
11479
- }
11480
- function extractWhoisFieldByAliases(payload, aliases) {
11481
- for (const [key, value] of Object.entries(payload)) {
11482
- if (!aliases.has(normalizeWhoisKey(key))) {
11483
- continue;
11484
- }
11485
- const parsedValue = parseWhoisString(value);
11486
- if (parsedValue) {
11487
- return parsedValue;
11488
- }
11489
- }
11490
- return void 0;
11491
- }
11492
- function extractWhoisCountry(payload) {
11493
- const countryCode = extractWhoisFieldByAliases(payload, WHOIS_COUNTRY_CODE_KEY_ALIASES);
11494
- const country = extractWhoisFieldByAliases(payload, WHOIS_COUNTRY_KEY_ALIASES);
11495
- return {
11496
- countryCode: countryCode != null ? countryCode : void 0,
11497
- country: country != null ? country : void 0
11498
- };
11499
- }
11500
-
11501
- // ../../internal/utils/src/safe-preview.ts
11502
- var safe_preview_exports = {};
11503
- __export(safe_preview_exports, {
11504
- buildSafePreviewUrl: () => buildSafePreviewUrl,
11505
- normalizeSafeNavigationTarget: () => normalizeSafeNavigationTarget
11754
+ z.object({
11755
+ brands: z.array(brandItemSchema).describe("List of brands")
11756
+ }).describe("Successful operation");
11757
+ var FILTERABLE_SUBSCRIPTION_STATUSES = [
11758
+ SubscriptionStatus.PROSPECT,
11759
+ SubscriptionStatus.POC,
11760
+ SubscriptionStatus.ACTIVE,
11761
+ SubscriptionStatus.INTEGRATION
11762
+ ];
11763
+ var UserOrgsSubscriptionStatusSchema = z.enum(
11764
+ FILTERABLE_SUBSCRIPTION_STATUSES
11765
+ );
11766
+ var takedownsServiceFilterSchema = z.object({
11767
+ active: z.boolean().optional(),
11768
+ automated: z.boolean().optional()
11769
+ }).optional();
11770
+ var singleServiceFilterSchema = z.object({
11771
+ active: z.boolean().optional()
11772
+ }).optional();
11773
+ var userOrgsServicesFilterObjectSchema = z.object({
11774
+ reporting: singleServiceFilterSchema,
11775
+ reviewing: singleServiceFilterSchema,
11776
+ protection: singleServiceFilterSchema,
11777
+ takedowns: takedownsServiceFilterSchema,
11778
+ detection: singleServiceFilterSchema,
11779
+ darkWebMonitoring: singleServiceFilterSchema
11506
11780
  });
11507
- var SAFE_NAVIGATION_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
11508
- var PREVIEW_PATH = "/preview";
11509
- var URL_BASE = "https://app.chainpatrol.io";
11510
- function normalizeSafeNavigationTarget(target) {
11511
- const normalizedTarget = getNormalizedUrl(target);
11512
- if (!SAFE_NAVIGATION_PROTOCOLS.has(normalizedTarget.protocol)) {
11513
- throw new Error(`Unsupported URL protocol: ${normalizedTarget.protocol}`);
11514
- }
11515
- return normalizedTarget;
11516
- }
11517
- function buildSafePreviewUrl({
11518
- target,
11519
- assetId,
11520
- policy
11521
- }) {
11522
- const normalizedTarget = normalizeSafeNavigationTarget(target);
11523
- const previewUrl = new URL(PREVIEW_PATH, URL_BASE);
11524
- previewUrl.searchParams.set("target", normalizedTarget.toString());
11525
- if (Number.isInteger(assetId) && assetId && assetId >= 1) {
11526
- previewUrl.searchParams.set("asset_id", String(assetId));
11527
- }
11528
- if (policy) {
11529
- previewUrl.searchParams.set("policy", policy);
11530
- }
11531
- return `${previewUrl.pathname}?${previewUrl.searchParams.toString()}`;
11532
- }
11533
-
11534
- // ../../internal/utils/src/parse.ts
11535
- var parse_exports = {};
11536
- __export(parse_exports, {
11537
- parseTerms: () => parseTerms,
11538
- stringifyTerms: () => stringifyTerms
11781
+ var userOrgsObligatoryAdminApprovalFilterSchema = z.object({
11782
+ active: z.boolean().optional(),
11783
+ assetTypes: z.array(z.nativeEnum(AssetType)).min(1).optional()
11784
+ }).optional();
11785
+ var PendingApprovalServiceSchema = z.enum(["protection", "takedowns"]);
11786
+ var userOrgsPendingServiceApprovalFilterSchema = z.object({
11787
+ active: z.boolean().optional(),
11788
+ services: z.array(PendingApprovalServiceSchema).min(1).optional()
11789
+ }).optional();
11790
+ z.object({
11791
+ query: z.string().default(""),
11792
+ subscriptionStatus: z.array(UserOrgsSubscriptionStatusSchema).min(1).optional(),
11793
+ services: userOrgsServicesFilterObjectSchema.optional(),
11794
+ obligatoryAdminApproval: userOrgsObligatoryAdminApprovalFilterSchema,
11795
+ pendingServiceApproval: userOrgsPendingServiceApprovalFilterSchema
11796
+ });
11797
+ var takedownsServiceSchema = z.object({
11798
+ active: z.boolean(),
11799
+ automated: z.boolean()
11800
+ });
11801
+ var singleServiceSchema = z.object({
11802
+ active: z.boolean()
11803
+ });
11804
+ var UserOrgObligatoryAdminApprovalSchema = z.object({
11805
+ active: z.boolean(),
11806
+ assetTypes: z.array(z.nativeEnum(AssetType))
11807
+ });
11808
+ var PendingServiceApprovalSchema = z.object({
11809
+ // Friendly service family, matching a key in the `services` object.
11810
+ service: PendingApprovalServiceSchema,
11811
+ // Whether the request is for the automated variant of the service
11812
+ // (e.g. "Automated Wallet Blocking" rather than "Wallet Blocking").
11813
+ automated: z.boolean(),
11814
+ // Raw `ServiceType` enum value, e.g. "isProtectionActive". Lets callers
11815
+ // distinguish the exact column without re-deriving it from `service` +
11816
+ // `automated`.
11817
+ serviceType: z.nativeEnum(ServiceType),
11818
+ // Human-readable service label, e.g. "Wallet Blocking".
11819
+ serviceName: z.string(),
11820
+ // When the enable request was submitted (ISO 8601, UTC).
11821
+ requestedAt: z.string()
11822
+ });
11823
+ var UserOrgIntegrationsSchema = z.object({
11824
+ slack: z.boolean(),
11825
+ discord: z.boolean(),
11826
+ telegram: z.object({
11827
+ connected: z.boolean(),
11828
+ groupCount: z.number()
11829
+ }),
11830
+ vercel: z.boolean(),
11831
+ intercom: z.boolean(),
11832
+ moderation: z.boolean()
11539
11833
  });
11540
- function parseTerms(terms, {
11541
- forceExact = false
11542
- } = {}) {
11543
- if (!terms) return [];
11544
- return terms.split(",").map((term) => {
11545
- const trimmed = term.trim();
11546
- if (!trimmed) return null;
11547
- const isWrappedExact = trimmed.startsWith("*") && trimmed.endsWith("*") && trimmed.length > 2;
11548
- if (isWrappedExact) {
11549
- return {
11550
- value: trimmed.slice(1, -1).toLowerCase(),
11551
- type: "exact"
11552
- };
11553
- } else {
11554
- return {
11555
- value: trimmed.toLowerCase(),
11556
- type: forceExact ? "exact" : "loose"
11557
- };
11558
- }
11559
- }).filter((term) => term !== null);
11560
- }
11561
- function stringifyTerms(parsedTerms) {
11562
- return parsedTerms.map((term) => term.type === "exact" ? `*${term.value}*` : term.value).join(", ");
11563
- }
11564
-
11565
- // ../../internal/utils/src/brand-pattern.ts
11566
- var brand_pattern_exports = {};
11567
- __export(brand_pattern_exports, {
11568
- anyPatternMatches: () => anyPatternMatches,
11569
- compileBrandPattern: () => compileBrandPattern,
11570
- countPatternMatches: () => countPatternMatches,
11571
- findMatchingPatterns: () => findMatchingPatterns
11834
+ var UserOrgLegalDocumentSchema = z.object({
11835
+ present: z.boolean().describe("Whether the organization has this document attached"),
11836
+ fileName: z.string().nullable().describe("Original filename of the uploaded document (null when not present)"),
11837
+ fileUrl: z.string().nullable().describe("Direct URL to view or download the document (null when not present)")
11572
11838
  });
11573
- var DEFAULT_MAX_MATCHES = 50;
11574
- function compileBrandPattern(input) {
11575
- var _a;
11576
- try {
11577
- return new RegExp(input.pattern, (_a = input.flags) != null ? _a : void 0);
11578
- } catch (e4) {
11579
- return null;
11580
- }
11581
- }
11582
- function anyPatternMatches(content, patterns, kind) {
11583
- for (const input of patterns) {
11584
- if (input.kind !== kind) continue;
11585
- const regex = compileBrandPattern(input);
11586
- if (!regex) continue;
11587
- if (regex.test(content)) {
11588
- return true;
11589
- }
11590
- }
11591
- return false;
11592
- }
11593
- function findMatchingPatterns(content, patterns, kind) {
11594
- const matched = [];
11595
- for (const input of patterns) {
11596
- if (input.kind !== kind) continue;
11597
- const regex = compileBrandPattern(input);
11598
- if (!regex) continue;
11599
- if (regex.test(content)) {
11600
- matched.push(input);
11601
- }
11602
- }
11603
- return matched;
11604
- }
11605
- function countPatternMatches(content, pattern, maxMatches = DEFAULT_MAX_MATCHES) {
11606
- const compiled = compileBrandPattern(pattern);
11607
- if (!compiled) return 0;
11608
- const flags = compiled.flags.includes("g") ? compiled.flags : `${compiled.flags}g`;
11609
- const globalRegex = new RegExp(compiled.source, flags);
11610
- let count = 0;
11611
- let match2;
11612
- while ((match2 = globalRegex.exec(content)) !== null) {
11613
- count += 1;
11614
- if (count >= maxMatches) break;
11615
- if (match2[0].length === 0) globalRegex.lastIndex += 1;
11616
- }
11617
- return count;
11618
- }
11619
-
11620
- // ../../internal/utils/src/text.ts
11621
- var text_exports = {};
11622
- __export(text_exports, {
11623
- HOMOGLYPH_MAPPINGS: () => HOMOGLYPH_MAPPINGS,
11624
- LETTER_TO_HOMOGLYPH_MAPPINGS: () => LETTER_TO_HOMOGLYPH_MAPPINGS,
11625
- generateHomoglyphSearchTerms: () => generateHomoglyphSearchTerms,
11626
- normalizeHomoglyphs: () => normalizeHomoglyphs
11839
+ var UserOrgLegalDocumentsSchema = z.object({
11840
+ letterOfAuthorization: UserOrgLegalDocumentSchema,
11841
+ powerOfAttorney: UserOrgLegalDocumentSchema
11627
11842
  });
11628
- var HOMOGLYPH_MAPPINGS = {
11629
- "0": "o",
11630
- "1": "i",
11631
- "3": "e",
11632
- "4": "a",
11633
- "5": "s",
11634
- "7": "t",
11635
- "8": "b"
11636
- };
11637
- var LETTER_TO_HOMOGLYPH_MAPPINGS = {
11638
- a: ["4", "\u0430"],
11639
- b: ["8", "6"],
11640
- c: ["\u0441"],
11641
- e: ["3", "\u0435"],
11642
- g: ["9"],
11643
- i: ["1", "l", "\u0456"],
11644
- l: ["1"],
11645
- o: ["0", "\u043E"],
11646
- s: ["5", "\u0455"],
11647
- t: ["7"],
11648
- x: ["\u0445"],
11649
- z: ["2"]
11650
- };
11651
- var DEFAULT_MAX_HOMOGLYPH_VARIANTS = 20;
11652
- function isCyrillic(char) {
11653
- return char.charCodeAt(0) > 127;
11654
- }
11655
- function buildReplacementOps(term) {
11656
- const ops = [];
11657
- for (let i = 0; i < term.length; i++) {
11658
- const homoglyphs = LETTER_TO_HOMOGLYPH_MAPPINGS[term[i]];
11659
- if (!homoglyphs) continue;
11660
- for (const replacement of homoglyphs) {
11661
- ops.push({ index: i, replacement });
11662
- }
11663
- }
11664
- return ops;
11665
- }
11666
- function applyOps(term, ops, selected) {
11667
- const chars = Array.from(term);
11668
- for (const idx of selected) {
11669
- chars[ops[idx].index] = ops[idx].replacement;
11670
- }
11671
- return chars.join("");
11672
- }
11673
- function generateCombinations(ops, opIndices, term, maxVariants, addFn, variants) {
11674
- const generate = (startIdx, depth, selected, usedPositions) => {
11675
- if (selected.length === depth) return addFn(applyOps(term, ops, selected));
11676
- for (let i = startIdx; i < opIndices.length && variants.length < maxVariants; i++) {
11677
- const opIdx = opIndices[i];
11678
- if (usedPositions.has(ops[opIdx].index)) continue;
11679
- selected.push(opIdx);
11680
- usedPositions.add(ops[opIdx].index);
11681
- if (generate(i + 1, depth, selected, usedPositions)) return true;
11682
- selected.pop();
11683
- usedPositions.delete(ops[opIdx].index);
11684
- }
11685
- return false;
11686
- };
11687
- for (let depth = 2; depth <= opIndices.length && variants.length < maxVariants; depth++) {
11688
- if (generate(0, depth, [], /* @__PURE__ */ new Set())) break;
11689
- }
11690
- }
11691
- function generateHomoglyphSearchTerms(term, maxVariants = DEFAULT_MAX_HOMOGLYPH_VARIANTS) {
11692
- if (term.length === 0 || maxVariants <= 0) return [];
11693
- const lowerTerm = term.toLowerCase();
11694
- const seen = /* @__PURE__ */ new Set();
11695
- const variants = [];
11696
- const add = (v) => {
11697
- if (v === lowerTerm || seen.has(v)) return false;
11698
- seen.add(v);
11699
- variants.push(v);
11700
- return variants.length >= maxVariants;
11701
- };
11702
- const allOps = buildReplacementOps(lowerTerm);
11703
- for (let i = 0; i < allOps.length && variants.length < maxVariants; i++) {
11704
- add(applyOps(lowerTerm, allOps, [i]));
11705
- }
11706
- if (variants.length < maxVariants) {
11707
- const cyrillicComposite = lowerTerm.split("").map((char) => {
11708
- var _a;
11709
- const homoglyphs = LETTER_TO_HOMOGLYPH_MAPPINGS[char];
11710
- return (_a = homoglyphs == null ? void 0 : homoglyphs.find((h) => isCyrillic(h))) != null ? _a : char;
11711
- }).join("");
11712
- add(cyrillicComposite);
11713
- }
11714
- const cyrillicOpIndices = allOps.map((op, i) => isCyrillic(op.replacement) ? i : -1).filter((i) => i >= 0);
11715
- if (variants.length < maxVariants && cyrillicOpIndices.length >= 2) {
11716
- generateCombinations(
11717
- allOps,
11718
- cyrillicOpIndices,
11719
- lowerTerm,
11720
- maxVariants,
11721
- add,
11722
- variants
11723
- );
11724
- }
11725
- if (variants.length < maxVariants) {
11726
- const allOpIndices = allOps.map((_, i) => i);
11727
- generateCombinations(allOps, allOpIndices, lowerTerm, maxVariants, add, variants);
11728
- }
11729
- return variants;
11730
- }
11731
- function normalizeHomoglyphs(text, customMappings = {}) {
11732
- const mappings = __spreadValues(__spreadValues({}, HOMOGLYPH_MAPPINGS), customMappings);
11733
- return text.toLowerCase().split("").map((char) => mappings[char] || char).join("");
11734
- }
11735
-
11736
- // ../../internal/utils/src/format.ts
11737
- var format_exports = {};
11738
- __export(format_exports, {
11739
- formatCompactNumber: () => formatCompactNumber,
11740
- formatFileSize: () => formatFileSize
11843
+ var UserOrgTrademarkRegistrationSchema = z.object({
11844
+ id: z.number().describe("Trademark registration ID"),
11845
+ brandName: z.string().describe("Trademarked brand name as it appears on the registration"),
11846
+ trademarkOffice: z.string().describe("Issuing trademark office (e.g. `USPTO`, `EUIPO`)"),
11847
+ registrationNumber: z.string().describe("Registration number assigned by the office"),
11848
+ goodsAndServicesClass: z.string().describe("Nice Classification class(es) the registration covers"),
11849
+ rightsOwnerName: z.string().nullable().describe("Legal entity the trademark is registered to, if recorded"),
11850
+ registrationPageUrl: z.string().nullable().describe("Public URL on the trademark office's site, if recorded"),
11851
+ certificateFileName: z.string().nullable().describe(
11852
+ "Original filename of the uploaded certificate PDF (null when no certificate is attached)"
11853
+ ),
11854
+ certificateFileUrl: z.string().nullable().describe(
11855
+ "Direct URL to view or download the certificate PDF (null when no certificate is attached)"
11856
+ )
11857
+ });
11858
+ var UserOrgBrandMetadataSchema = z.object({
11859
+ websiteUrl: z.string().nullable().describe("Public website URL of the brand (linked from the portal header)"),
11860
+ twitterHandle: z.string().nullable().describe(
11861
+ "Public Twitter/X handle of the brand, stored with the leading `@` (e.g. `@acme`)"
11862
+ ),
11863
+ securityContactEmail: z.string().nullable().describe(
11864
+ "Email address for security correspondence \u2014 used by takedown providers and researchers, distinct from the internal customer POC email"
11865
+ ),
11866
+ industry: z.string().nullable().describe('Free-form industry label (e.g. "DeFi", "CEX", "NFT", "Wallet")')
11867
+ });
11868
+ var UserOrgPortalCustomizationSchema = z.object({
11869
+ useCustomDetails: z.boolean().describe(
11870
+ "When true, the portal uses `name`/`slug`/`avatarUrl` from this object instead of the org's own name/slug/avatar"
11871
+ ),
11872
+ name: z.string().nullable().describe(
11873
+ "Custom display name shown on the portal (used only when `useCustomDetails=true`)"
11874
+ ),
11875
+ slug: z.string().nullable().describe(
11876
+ "Custom URL slug (`chainpatrol.io/<slug>`) \u2014 takes precedence over the org's own slug when set, regardless of `useCustomDetails`"
11877
+ ),
11878
+ avatarUrl: z.string().nullable().describe(
11879
+ "Custom avatar URL shown on the portal (used only when `useCustomDetails=true`)"
11880
+ ),
11881
+ bannerEnabled: z.boolean().describe(
11882
+ "When true, the portal renders `bannerContent` as a highlighted banner at the top of the page"
11883
+ ),
11884
+ bannerContent: z.string().nullable().describe(
11885
+ "Markdown body of the portal banner. Null (or empty) with `bannerEnabled=true` means the toggle is on but no content has been written yet"
11886
+ )
11887
+ });
11888
+ var UserOrgSchema = z.object({
11889
+ id: z.number(),
11890
+ name: z.string(),
11891
+ slug: z.string(),
11892
+ avatarUrl: z.string().nullable(),
11893
+ contactUrl: z.string().nullable(),
11894
+ subscriptionStatus: z.nativeEnum(SubscriptionStatus),
11895
+ portalVisibility: z.nativeEnum(OrganizationPortalVisibility).describe(
11896
+ "Visibility of the org's public security portal (chainpatrol.io/<slug>). `PUBLIC` is discoverable; `PRIVATE` renders only the report form (no metrics or listings); `DISABLED` returns a 404."
11897
+ ),
11898
+ reportVisibility: z.nativeEnum(ReportVisibility).describe(
11899
+ "Whether the report listings on the public portal are visible to visitors. `PUBLIC` shows the org's reports; `PRIVATE` hides the report list even when the portal is discoverable."
11900
+ ),
11901
+ metricsVisibility: z.nativeEnum(MetricsVisibility).describe(
11902
+ "Whether the metrics/threats-blocked stats render on the public portal. `PUBLIC` shows the metrics tab; `PRIVATE` hides it from anonymous visitors; `DISABLED` doesn't compute metrics at all."
11903
+ ),
11904
+ brandMetadata: UserOrgBrandMetadataSchema.describe(
11905
+ "Public brand-facing metadata (website, twitter, security contact, industry) shown on the portal and used by staff for outbound"
11906
+ ),
11907
+ portalCustomization: UserOrgPortalCustomizationSchema.describe(
11908
+ "Customer-configurable presentation of the public security portal \u2014 custom name/slug/avatar and the banner content"
11909
+ ),
11910
+ services: z.object({
11911
+ reporting: singleServiceSchema,
11912
+ reviewing: singleServiceSchema,
11913
+ protection: singleServiceSchema,
11914
+ takedowns: takedownsServiceSchema,
11915
+ detection: singleServiceSchema,
11916
+ darkWebMonitoring: singleServiceSchema
11917
+ }),
11918
+ integrations: UserOrgIntegrationsSchema,
11919
+ obligatoryAdminApproval: UserOrgObligatoryAdminApprovalSchema,
11920
+ pendingServiceApprovals: z.array(PendingServiceApprovalSchema),
11921
+ legalDocuments: UserOrgLegalDocumentsSchema.describe(
11922
+ "Org-level Letter of Authorization and Power of Attorney attachments"
11923
+ ),
11924
+ trademarkRegistrations: z.array(UserOrgTrademarkRegistrationSchema).describe(
11925
+ "Org-level trademark registrations attached to the organization. An empty array means no trademarks are on file \u2014 use this to identify customers who still need to add them."
11926
+ )
11741
11927
  });
11742
- function formatCompactNumber(num3, options = {}) {
11743
- const { decimals = 1, fallback = "-" } = options;
11744
- if (num3 === void 0 || num3 === null) {
11745
- return fallback;
11746
- }
11747
- if (num3 >= 1e9) {
11748
- return `${(num3 / 1e9).toFixed(decimals)}B`;
11749
- }
11750
- if (num3 >= 1e6) {
11751
- return `${(num3 / 1e6).toFixed(decimals)}M`;
11752
- }
11753
- if (num3 >= 1e3) {
11754
- return `${(num3 / 1e3).toFixed(decimals)}K`;
11755
- }
11756
- return num3.toString();
11757
- }
11758
- function formatFileSize(bytes, options = {}) {
11759
- const { decimals = 1, binary = true, showUnknown = true } = options;
11760
- if (bytes === null || bytes === void 0 || bytes === "") {
11761
- return showUnknown ? "Unknown" : "0 B";
11762
- }
11763
- const size = typeof bytes === "string" ? parseInt(bytes, 10) : bytes;
11764
- if (isNaN(size) || size < 0) {
11765
- return showUnknown ? "Unknown" : "0 B";
11766
- }
11767
- if (size === 0) {
11768
- return "0 B";
11769
- }
11770
- const unit = binary ? 1024 : 1e3;
11771
- const units = binary ? ["B", "KB", "MB", "GB", "TB", "PB"] : ["B", "kB", "MB", "GB", "TB", "PB"];
11772
- const unitIndex = Math.floor(Math.log(size) / Math.log(unit));
11773
- const finalUnitIndex = Math.min(unitIndex, units.length - 1);
11774
- const value = size / Math.pow(unit, finalUnitIndex);
11775
- if (finalUnitIndex === 0) {
11776
- return `${size} B`;
11777
- }
11778
- return `${value.toFixed(decimals)} ${units[finalUnitIndex]}`;
11779
- }
11780
-
11781
- // ../../internal/utils/src/social-profile-url.ts
11782
- var social_profile_url_exports = {};
11783
- __export(social_profile_url_exports, {
11784
- LINKEDIN_PROFILE_URL_PATTERN: () => LINKEDIN_PROFILE_URL_PATTERN,
11785
- TWITTER_PROFILE_URL_PATTERN: () => TWITTER_PROFILE_URL_PATTERN,
11786
- isLinkedInProfileUrl: () => isLinkedInProfileUrl,
11787
- isSupportedSocialProfileUrl: () => isSupportedSocialProfileUrl,
11788
- isTwitterProfileUrl: () => isTwitterProfileUrl,
11789
- parseLinkedInProfileUrl: () => parseLinkedInProfileUrl
11928
+ z.object({
11929
+ organizations: z.array(UserOrgSchema)
11790
11930
  });
11791
- var TWITTER_PROFILE_URL_PATTERN = /^https?:\/\/(?:www\.)?(?:twitter\.com|x\.com)\/[^/?#]+\/?(?:[?#].*)?$/i;
11792
- var LINKEDIN_PROFILE_URL_PATTERN = /^https?:\/\/(?:[a-z]{2,3}\.)?linkedin\.com\/(in|company|school)\/([^/?#]+)/i;
11793
- function isTwitterProfileUrl(url) {
11794
- return TWITTER_PROFILE_URL_PATTERN.test(url);
11795
- }
11796
- function isLinkedInProfileUrl(url) {
11797
- return LINKEDIN_PROFILE_URL_PATTERN.test(url);
11798
- }
11799
- function isSupportedSocialProfileUrl(url) {
11800
- return isTwitterProfileUrl(url) || isLinkedInProfileUrl(url);
11801
- }
11802
- function humanizeLinkedInHandle(handle) {
11803
- const withoutTrailingDigits = handle.replace(/-[0-9a-f]{6,}$/i, "");
11804
- return withoutTrailingDigits.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
11805
- }
11806
- function parseLinkedInProfileUrl(url) {
11807
- var _a;
11808
- const match2 = url.match(LINKEDIN_PROFILE_URL_PATTERN);
11809
- if (!match2) return null;
11810
- const pathSegment = (_a = match2[1]) == null ? void 0 : _a.toLowerCase();
11811
- const rawHandle = match2[2];
11812
- if (!pathSegment || !rawHandle) return null;
11813
- let handle;
11931
+
11932
+ // ../../internal/validation/src/public/organization/metrics-get.ts
11933
+ var organizationMetricsIncludeFieldSchema = z.enum([
11934
+ "reports",
11935
+ "newThreats",
11936
+ "threatsWatchlisted",
11937
+ "takedownsFiled",
11938
+ "takedownsCompleted",
11939
+ "domainThreats",
11940
+ "twitterThreats",
11941
+ "telegramThreats",
11942
+ "otherThreats",
11943
+ "blockedByType",
11944
+ "blockedByDay"
11945
+ ]);
11946
+ organizationMetricsIncludeFieldSchema.options;
11947
+ var ORGANIZATION_METRICS_MAX_SLUGS = 500;
11948
+ var organizationMetricsServicesFilterSchema = z.preprocess((value) => {
11949
+ if (typeof value !== "string") return value;
11814
11950
  try {
11815
- handle = decodeURIComponent(rawHandle).trim();
11951
+ return JSON.parse(value);
11816
11952
  } catch (e4) {
11817
- return null;
11953
+ return value;
11818
11954
  }
11819
- if (!handle) return null;
11820
- const name = humanizeLinkedInHandle(handle) || handle;
11821
- const profileUrl = `https://www.linkedin.com/${pathSegment}/${handle}`;
11822
- return { pathSegment, handle, name, profileUrl };
11823
- }
11824
-
11825
- // ../../internal/validation/src/public/report/create.ts
11955
+ }, userOrgsServicesFilterObjectSchema).optional();
11956
+ z.object({
11957
+ organizationSlug: z.string().optional().describe(
11958
+ "Organization slug. Required when authenticating with a user session (Bearer token) and `slugs`/`allMyOrgs` are not supplied; ignored when using an org-scoped API key (org is derived from the key). Mutually exclusive with `slugs` and `allMyOrgs`."
11959
+ ),
11960
+ slugs: z.array(z.string()).max(ORGANIZATION_METRICS_MAX_SLUGS).optional().describe(
11961
+ "Multi-org form. Each slug is auth-checked individually (org-scoped API keys may only pass their own org; sessions and user API keys must have membership or staff role per slug). When supplied with more than one slug, the response includes a `perOrg` breakdown plus `metrics` rolled up across all of them. Capped at " + String(ORGANIZATION_METRICS_MAX_SLUGS) + " slugs per call. Mutually exclusive with `organizationSlug` and `allMyOrgs`."
11962
+ ),
11963
+ allMyOrgs: z.preprocess((value) => {
11964
+ if (value === "true") return true;
11965
+ if (value === "false") return false;
11966
+ return value;
11967
+ }, z.boolean()).optional().describe(
11968
+ "Shortcut for 'every org the caller is authorized to read'. Reuses the same filter logic as `/user/orgs`: org-scoped API keys are rejected (they're pinned to one org \u2014 use the default form); user API keys / Bearer sessions resolve to the user's memberships (or every active org for staff). Combine with `subscriptionStatus` and `services` to narrow (e.g. only paying customers with takedowns enabled). The resolved org set is still capped at " + String(ORGANIZATION_METRICS_MAX_SLUGS) + " and a 413 is returned if exceeded. Mutually exclusive with `organizationSlug`, `slugs`, and `brandSlug`."
11969
+ ),
11970
+ subscriptionStatus: z.array(UserOrgsSubscriptionStatusSchema).min(1).optional().describe(
11971
+ "Only meaningful with `allMyOrgs: true`. Defaults to the same set `/user/orgs` uses (ACTIVE/POC/PROSPECT/INTEGRATION \u2014 INACTIVE is always excluded)."
11972
+ ),
11973
+ services: organizationMetricsServicesFilterSchema.describe(
11974
+ "Only meaningful with `allMyOrgs: true`. Same shape as `/user/orgs`'s `services` filter \u2014 every service accepts `{ active }`, and **only `takedowns` additionally accepts `automated`** (the one service where manual-vs-automated changes real platform behavior). E.g. `{ takedowns: { active: true, automated: false } }` for 'orgs with takedowns enabled but automation off'."
11975
+ ),
11976
+ brandSlug: z.string().optional(),
11977
+ startDate: z.coerce.date().optional(),
11978
+ endDate: z.coerce.date().optional(),
11979
+ include: z.array(organizationMetricsIncludeFieldSchema).optional().describe(
11980
+ "Subset of metrics to compute. When omitted or empty, every metric is computed (legacy behavior). Each value in `include` costs roughly one Prisma aggregate, so narrow the list when an agent only needs a couple of numbers \u2014 this is the main lever for keeping big-org calls inside the 30s function cap. Fields not in `include` come back as `null`."
11981
+ )
11982
+ }).refine(
11983
+ (value) => {
11984
+ const explicitForms = [
11985
+ Boolean(value.organizationSlug),
11986
+ Boolean(value.slugs && value.slugs.length > 0),
11987
+ Boolean(value.allMyOrgs)
11988
+ ].filter(Boolean).length;
11989
+ return explicitForms <= 1;
11990
+ },
11991
+ {
11992
+ message: "Pass at most one of `organizationSlug`, `slugs`, or `allMyOrgs`.",
11993
+ path: ["allMyOrgs"]
11994
+ }
11995
+ ).refine((value) => !(value.brandSlug && value.slugs && value.slugs.length > 1), {
11996
+ message: "`brandSlug` is only valid alongside a single organization, not `slugs`.",
11997
+ path: ["brandSlug"]
11998
+ }).refine((value) => !(value.brandSlug && value.allMyOrgs), {
11999
+ message: "`brandSlug` is only valid for a single org, not `allMyOrgs`.",
12000
+ path: ["brandSlug"]
12001
+ });
12002
+ var metricValue = z.number().nullable();
12003
+ var metricsObjectSchema = z.object({
12004
+ reports: metricValue,
12005
+ newThreats: metricValue,
12006
+ threatsWatchlisted: metricValue,
12007
+ takedownsFiled: metricValue,
12008
+ takedownsCompleted: metricValue,
12009
+ domainThreats: metricValue,
12010
+ twitterThreats: metricValue,
12011
+ telegramThreats: metricValue,
12012
+ otherThreats: metricValue
12013
+ });
12014
+ var blockedByTypeSchema = z.array(
12015
+ z.object({
12016
+ type: z.string(),
12017
+ count: z.number()
12018
+ })
12019
+ ).nullable();
12020
+ var blockedByDaySchema = z.array(
12021
+ z.object({
12022
+ date: z.string(),
12023
+ count: z.number()
12024
+ })
12025
+ ).nullable();
12026
+ z.object({
12027
+ /**
12028
+ * Aggregate metrics. For single-org callers this is just that org's
12029
+ * numbers; for multi-org callers (`slugs.length > 1` or `allMyOrgs`)
12030
+ * it is the sum across all queried orgs.
12031
+ */
12032
+ metrics: metricsObjectSchema,
12033
+ blockedByType: blockedByTypeSchema,
12034
+ blockedByDay: blockedByDaySchema,
12035
+ /**
12036
+ * Derived averages over the time window (and, in multi-org mode,
12037
+ * across orgs). `perDay = metrics / windowDays`. In multi-org mode
12038
+ * `perOrgPerDay = metrics / numOrgs / windowDays`; in single-org
12039
+ * mode it is `null`. Counts are floats here — the underlying
12040
+ * `metrics` fields stay integer counts.
12041
+ */
12042
+ averages: z.object({
12043
+ perDay: metricsObjectSchema.nullable(),
12044
+ perOrgPerDay: metricsObjectSchema.nullable(),
12045
+ windowDays: z.number().nullable()
12046
+ }),
12047
+ /**
12048
+ * Per-org breakdown. Only populated in multi-org mode; `null` for
12049
+ * single-org callers.
12050
+ */
12051
+ perOrg: z.record(
12052
+ z.string(),
12053
+ z.object({
12054
+ metrics: metricsObjectSchema,
12055
+ blockedByType: blockedByTypeSchema,
12056
+ blockedByDay: blockedByDaySchema
12057
+ })
12058
+ ).nullable(),
12059
+ /**
12060
+ * Echoes the actual orgs the response covers, in the order they
12061
+ * were resolved. Single-org responses always have length 1. The
12062
+ * `resolvedFrom` field distinguishes how the caller asked for the
12063
+ * scope (useful for agent reporting).
12064
+ */
12065
+ scope: z.object({
12066
+ mode: z.enum(["single", "multi"]),
12067
+ orgs: z.array(z.string()),
12068
+ resolvedFrom: z.enum(["api-key", "organizationSlug", "slugs", "allMyOrgs"])
12069
+ })
12070
+ });
11826
12071
  var BASE_64_PATTERN = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
11827
12072
  var PHONE_COUNTRY_CODE_ERROR_MESSAGE = "Phone numbers must include a country code in E.164 format (for example, +14155552671).";
11828
12073
  function isPhoneNumberMissingCountryCode(value) {
@@ -13143,20 +13388,20 @@ var convertA98ToXyz65_default = convertA98ToXyz65;
13143
13388
 
13144
13389
  // ../../node_modules/culori/src/a98/convertXyz65ToA98.js
13145
13390
  var gamma = (v) => Math.pow(Math.abs(v), 256 / 563) * Math.sign(v);
13146
- var convertXyz65ToA98 = ({ x, y, z: z50, alpha }) => {
13391
+ var convertXyz65ToA98 = ({ x, y, z: z55, alpha }) => {
13147
13392
  if (x === void 0) x = 0;
13148
13393
  if (y === void 0) y = 0;
13149
- if (z50 === void 0) z50 = 0;
13394
+ if (z55 === void 0) z55 = 0;
13150
13395
  let res = {
13151
13396
  mode: "a98",
13152
13397
  r: gamma(
13153
- x * 2.0415879038107465 - y * 0.5650069742788597 - 0.3447313507783297 * z50
13398
+ x * 2.0415879038107465 - y * 0.5650069742788597 - 0.3447313507783297 * z55
13154
13399
  ),
13155
13400
  g: gamma(
13156
- x * -0.9692436362808798 + y * 1.8759675015077206 + 0.0415550574071756 * z50
13401
+ x * -0.9692436362808798 + y * 1.8759675015077206 + 0.0415550574071756 * z55
13157
13402
  ),
13158
13403
  b: gamma(
13159
- x * 0.0134442806320312 - y * 0.1183623922310184 + 1.0151749943912058 * z50
13404
+ x * 0.0134442806320312 - y * 0.1183623922310184 + 1.0151749943912058 * z55
13160
13405
  )
13161
13406
  };
13162
13407
  if (alpha !== void 0) {
@@ -13223,14 +13468,14 @@ var convertLrgbToRgb = ({ r, g, b, alpha }, mode = "rgb") => {
13223
13468
  var convertLrgbToRgb_default = convertLrgbToRgb;
13224
13469
 
13225
13470
  // ../../node_modules/culori/src/xyz65/convertXyz65ToRgb.js
13226
- var convertXyz65ToRgb = ({ x, y, z: z50, alpha }) => {
13471
+ var convertXyz65ToRgb = ({ x, y, z: z55, alpha }) => {
13227
13472
  if (x === void 0) x = 0;
13228
13473
  if (y === void 0) y = 0;
13229
- if (z50 === void 0) z50 = 0;
13474
+ if (z55 === void 0) z55 = 0;
13230
13475
  let res = convertLrgbToRgb_default({
13231
- r: x * 3.2409699419045226 - y * 1.537383177570094 - 0.4986107602930034 * z50,
13232
- g: x * -0.9692436362808796 + y * 1.8759675015077204 + 0.0415550574071756 * z50,
13233
- b: x * 0.0556300796969936 - y * 0.2039769588889765 + 1.0569715142428784 * z50
13476
+ r: x * 3.2409699419045226 - y * 1.537383177570094 - 0.4986107602930034 * z55,
13477
+ g: x * -0.9692436362808796 + y * 1.8759675015077204 + 0.0415550574071756 * z55,
13478
+ b: x * 0.0556300796969936 - y * 0.2039769588889765 + 1.0569715142428784 * z55
13234
13479
  });
13235
13480
  if (alpha !== void 0) {
13236
13481
  res.alpha = alpha;
@@ -13480,13 +13725,13 @@ var convertLab65ToRgb_default = convertLab65ToRgb;
13480
13725
 
13481
13726
  // ../../node_modules/culori/src/lab65/convertXyz65ToLab65.js
13482
13727
  var f = (value) => value > e ? Math.cbrt(value) : (k * value + 16) / 116;
13483
- var convertXyz65ToLab65 = ({ x, y, z: z50, alpha }) => {
13728
+ var convertXyz65ToLab65 = ({ x, y, z: z55, alpha }) => {
13484
13729
  if (x === void 0) x = 0;
13485
13730
  if (y === void 0) y = 0;
13486
- if (z50 === void 0) z50 = 0;
13731
+ if (z55 === void 0) z55 = 0;
13487
13732
  let f0 = f(x / D65.X);
13488
13733
  let f1 = f(y / D65.Y);
13489
- let f22 = f(z50 / D65.Z);
13734
+ let f22 = f(z55 / D65.Z);
13490
13735
  let res = {
13491
13736
  mode: "lab65",
13492
13737
  l: 116 * f1 - 16,
@@ -14143,10 +14388,10 @@ var convertItpToXyz65_default = convertItpToXyz65;
14143
14388
 
14144
14389
  // ../../node_modules/culori/src/itp/convertXyz65ToItp.js
14145
14390
  var toAbs = (c2 = 0) => Math.max(c2 * YW, 0);
14146
- var convertXyz65ToItp = ({ x, y, z: z50, alpha }) => {
14391
+ var convertXyz65ToItp = ({ x, y, z: z55, alpha }) => {
14147
14392
  const absX = toAbs(x);
14148
14393
  const absY = toAbs(y);
14149
- const absZ = toAbs(z50);
14394
+ const absZ = toAbs(z55);
14150
14395
  const l2 = transferPqEncode(
14151
14396
  0.3592832590121217 * absX + 0.6976051147779502 * absY - 0.0358915932320289 * absZ
14152
14397
  );
@@ -14204,15 +14449,15 @@ var jabPqEncode = (v) => {
14204
14449
  return Math.pow((C1 + C2 * vn3) / (1 + C3 * vn3), p);
14205
14450
  };
14206
14451
  var abs = (v = 0) => Math.max(v * 203, 0);
14207
- var convertXyz65ToJab = ({ x, y, z: z50, alpha }) => {
14452
+ var convertXyz65ToJab = ({ x, y, z: z55, alpha }) => {
14208
14453
  x = abs(x);
14209
14454
  y = abs(y);
14210
- z50 = abs(z50);
14211
- let xp = 1.15 * x - 0.15 * z50;
14455
+ z55 = abs(z55);
14456
+ let xp = 1.15 * x - 0.15 * z55;
14212
14457
  let yp = 0.66 * y + 0.34 * x;
14213
- let l2 = jabPqEncode(0.41478972 * xp + 0.579999 * yp + 0.014648 * z50);
14214
- let m = jabPqEncode(-0.20151 * xp + 1.120649 * yp + 0.0531008 * z50);
14215
- let s2 = jabPqEncode(-0.0166008 * xp + 0.2648 * yp + 0.6684799 * z50);
14458
+ let l2 = jabPqEncode(0.41478972 * xp + 0.579999 * yp + 0.014648 * z55);
14459
+ let m = jabPqEncode(-0.20151 * xp + 1.120649 * yp + 0.0531008 * z55);
14460
+ let s2 = jabPqEncode(-0.0166008 * xp + 0.2648 * yp + 0.6684799 * z55);
14216
14461
  let i = (l2 + m) / 2;
14217
14462
  let res = {
14218
14463
  mode: "jab",
@@ -14398,14 +14643,14 @@ var convertLabToXyz50 = ({ l: l2, a, b, alpha }) => {
14398
14643
  var convertLabToXyz50_default = convertLabToXyz50;
14399
14644
 
14400
14645
  // ../../node_modules/culori/src/xyz50/convertXyz50ToRgb.js
14401
- var convertXyz50ToRgb = ({ x, y, z: z50, alpha }) => {
14646
+ var convertXyz50ToRgb = ({ x, y, z: z55, alpha }) => {
14402
14647
  if (x === void 0) x = 0;
14403
14648
  if (y === void 0) y = 0;
14404
- if (z50 === void 0) z50 = 0;
14649
+ if (z55 === void 0) z55 = 0;
14405
14650
  let res = convertLrgbToRgb_default({
14406
- r: x * 3.1341359569958707 - y * 1.6173863321612538 - 0.4906619460083532 * z50,
14407
- g: x * -0.978795502912089 + y * 1.916254567259524 + 0.03344273116131949 * z50,
14408
- b: x * 0.07195537988411677 - y * 0.2289768264158322 + 1.405386058324125 * z50
14651
+ r: x * 3.1341359569958707 - y * 1.6173863321612538 - 0.4906619460083532 * z55,
14652
+ g: x * -0.978795502912089 + y * 1.916254567259524 + 0.03344273116131949 * z55,
14653
+ b: x * 0.07195537988411677 - y * 0.2289768264158322 + 1.405386058324125 * z55
14409
14654
  });
14410
14655
  if (alpha !== void 0) {
14411
14656
  res.alpha = alpha;
@@ -14436,13 +14681,13 @@ var convertRgbToXyz50_default = convertRgbToXyz50;
14436
14681
 
14437
14682
  // ../../node_modules/culori/src/lab/convertXyz50ToLab.js
14438
14683
  var f2 = (value) => value > e3 ? Math.cbrt(value) : (k3 * value + 16) / 116;
14439
- var convertXyz50ToLab = ({ x, y, z: z50, alpha }) => {
14684
+ var convertXyz50ToLab = ({ x, y, z: z55, alpha }) => {
14440
14685
  if (x === void 0) x = 0;
14441
14686
  if (y === void 0) y = 0;
14442
- if (z50 === void 0) z50 = 0;
14687
+ if (z55 === void 0) z55 = 0;
14443
14688
  let f0 = f2(x / D50.X);
14444
14689
  let f1 = f2(y / D50.Y);
14445
- let f22 = f2(z50 / D50.Z);
14690
+ let f22 = f2(z55 / D50.Z);
14446
14691
  let res = {
14447
14692
  mode: "lab",
14448
14693
  l: 116 * f1 - 16,
@@ -14677,18 +14922,18 @@ var convertLchuvToLuv = ({ l: l2, c: c2, h, alpha }) => {
14677
14922
  var convertLchuvToLuv_default = convertLchuvToLuv;
14678
14923
 
14679
14924
  // ../../node_modules/culori/src/luv/convertXyz50ToLuv.js
14680
- var u_fn = (x, y, z50) => 4 * x / (x + 15 * y + 3 * z50);
14681
- var v_fn = (x, y, z50) => 9 * y / (x + 15 * y + 3 * z50);
14925
+ var u_fn = (x, y, z55) => 4 * x / (x + 15 * y + 3 * z55);
14926
+ var v_fn = (x, y, z55) => 9 * y / (x + 15 * y + 3 * z55);
14682
14927
  var un = u_fn(D50.X, D50.Y, D50.Z);
14683
14928
  var vn = v_fn(D50.X, D50.Y, D50.Z);
14684
14929
  var l_fn = (value) => value <= e3 ? k3 * value : 116 * Math.cbrt(value) - 16;
14685
- var convertXyz50ToLuv = ({ x, y, z: z50, alpha }) => {
14930
+ var convertXyz50ToLuv = ({ x, y, z: z55, alpha }) => {
14686
14931
  if (x === void 0) x = 0;
14687
14932
  if (y === void 0) y = 0;
14688
- if (z50 === void 0) z50 = 0;
14933
+ if (z55 === void 0) z55 = 0;
14689
14934
  let l2 = l_fn(y / D50.Y);
14690
- let u = u_fn(x, y, z50);
14691
- let v = v_fn(x, y, z50);
14935
+ let u = u_fn(x, y, z55);
14936
+ let v = v_fn(x, y, z55);
14692
14937
  if (!isFinite(u) || !isFinite(v)) {
14693
14938
  l2 = u = v = 0;
14694
14939
  } else {
@@ -14709,8 +14954,8 @@ var convertXyz50ToLuv = ({ x, y, z: z50, alpha }) => {
14709
14954
  var convertXyz50ToLuv_default = convertXyz50ToLuv;
14710
14955
 
14711
14956
  // ../../node_modules/culori/src/luv/convertLuvToXyz50.js
14712
- var u_fn2 = (x, y, z50) => 4 * x / (x + 15 * y + 3 * z50);
14713
- var v_fn2 = (x, y, z50) => 9 * y / (x + 15 * y + 3 * z50);
14957
+ var u_fn2 = (x, y, z55) => 4 * x / (x + 15 * y + 3 * z55);
14958
+ var v_fn2 = (x, y, z55) => 9 * y / (x + 15 * y + 3 * z55);
14714
14959
  var un2 = u_fn2(D50.X, D50.Y, D50.Z);
14715
14960
  var vn2 = v_fn2(D50.X, D50.Y, D50.Z);
14716
14961
  var convertLuvToXyz50 = ({ l: l2, u, v, alpha }) => {
@@ -14724,8 +14969,8 @@ var convertLuvToXyz50 = ({ l: l2, u, v, alpha }) => {
14724
14969
  let vp = v / (13 * l2) + vn2;
14725
14970
  let y = D50.Y * (l2 <= 8 ? l2 / k3 : Math.pow((l2 + 16) / 116, 3));
14726
14971
  let x = y * (9 * up) / (4 * vp);
14727
- let z50 = y * (12 - 3 * up - 20 * vp) / (4 * vp);
14728
- let res = { mode: "xyz50", x, y, z: z50 };
14972
+ let z55 = y * (12 - 3 * up - 20 * vp) / (4 * vp);
14973
+ let res = { mode: "xyz50", x, y, z: z55 };
14729
14974
  if (alpha !== void 0) {
14730
14975
  res.alpha = alpha;
14731
14976
  }
@@ -15342,15 +15587,15 @@ var convertP3ToXyz65 = (rgb2) => {
15342
15587
  var convertP3ToXyz65_default = convertP3ToXyz65;
15343
15588
 
15344
15589
  // ../../node_modules/culori/src/p3/convertXyz65ToP3.js
15345
- var convertXyz65ToP3 = ({ x, y, z: z50, alpha }) => {
15590
+ var convertXyz65ToP3 = ({ x, y, z: z55, alpha }) => {
15346
15591
  if (x === void 0) x = 0;
15347
15592
  if (y === void 0) y = 0;
15348
- if (z50 === void 0) z50 = 0;
15593
+ if (z55 === void 0) z55 = 0;
15349
15594
  let res = convertLrgbToRgb_default(
15350
15595
  {
15351
- r: x * 2.4934969119414263 - y * 0.9313836179191242 - 0.402710784450717 * z50,
15352
- g: x * -0.8294889695615749 + y * 1.7626640603183465 + 0.0236246858419436 * z50,
15353
- b: x * 0.0358458302437845 - y * 0.0761723892680418 + 0.9568845240076871 * z50
15596
+ r: x * 2.4934969119414263 - y * 0.9313836179191242 - 0.402710784450717 * z55,
15597
+ g: x * -0.8294889695615749 + y * 1.7626640603183465 + 0.0236246858419436 * z55,
15598
+ b: x * 0.0358458302437845 - y * 0.0761723892680418 + 0.9568845240076871 * z55
15354
15599
  },
15355
15600
  "p3"
15356
15601
  );
@@ -15385,19 +15630,19 @@ var gamma2 = (v) => {
15385
15630
  }
15386
15631
  return 16 * v;
15387
15632
  };
15388
- var convertXyz50ToProphoto = ({ x, y, z: z50, alpha }) => {
15633
+ var convertXyz50ToProphoto = ({ x, y, z: z55, alpha }) => {
15389
15634
  if (x === void 0) x = 0;
15390
15635
  if (y === void 0) y = 0;
15391
- if (z50 === void 0) z50 = 0;
15636
+ if (z55 === void 0) z55 = 0;
15392
15637
  let res = {
15393
15638
  mode: "prophoto",
15394
15639
  r: gamma2(
15395
- x * 1.3457868816471585 - y * 0.2555720873797946 - 0.0511018649755453 * z50
15640
+ x * 1.3457868816471585 - y * 0.2555720873797946 - 0.0511018649755453 * z55
15396
15641
  ),
15397
15642
  g: gamma2(
15398
- x * -0.5446307051249019 + y * 1.5082477428451466 + 0.0205274474364214 * z50
15643
+ x * -0.5446307051249019 + y * 1.5082477428451466 + 0.0205274474364214 * z55
15399
15644
  ),
15400
- b: gamma2(x * 0 + y * 0 + 1.2119675456389452 * z50)
15645
+ b: gamma2(x * 0 + y * 0 + 1.2119675456389452 * z55)
15401
15646
  };
15402
15647
  if (alpha !== void 0) {
15403
15648
  res.alpha = alpha;
@@ -15457,20 +15702,20 @@ var gamma3 = (v) => {
15457
15702
  }
15458
15703
  return 4.5 * v;
15459
15704
  };
15460
- var convertXyz65ToRec2020 = ({ x, y, z: z50, alpha }) => {
15705
+ var convertXyz65ToRec2020 = ({ x, y, z: z55, alpha }) => {
15461
15706
  if (x === void 0) x = 0;
15462
15707
  if (y === void 0) y = 0;
15463
- if (z50 === void 0) z50 = 0;
15708
+ if (z55 === void 0) z55 = 0;
15464
15709
  let res = {
15465
15710
  mode: "rec2020",
15466
15711
  r: gamma3(
15467
- x * 1.7166511879712683 - y * 0.3556707837763925 - 0.2533662813736599 * z50
15712
+ x * 1.7166511879712683 - y * 0.3556707837763925 - 0.2533662813736599 * z55
15468
15713
  ),
15469
15714
  g: gamma3(
15470
- x * -0.6666843518324893 + y * 1.6164812366349395 + 0.0157685458139111 * z50
15715
+ x * -0.6666843518324893 + y * 1.6164812366349395 + 0.0157685458139111 * z55
15471
15716
  ),
15472
15717
  b: gamma3(
15473
- x * 0.0176398574453108 - y * 0.0427706132578085 + 0.9421031212354739 * z50
15718
+ x * 0.0176398574453108 - y * 0.0427706132578085 + 0.9421031212354739 * z55
15474
15719
  )
15475
15720
  };
15476
15721
  if (alpha !== void 0) {
@@ -15623,15 +15868,15 @@ var definition_default26 = definition26;
15623
15868
 
15624
15869
  // ../../node_modules/culori/src/xyz65/convertXyz65ToXyz50.js
15625
15870
  var convertXyz65ToXyz50 = (xyz652) => {
15626
- let { x, y, z: z50, alpha } = xyz652;
15871
+ let { x, y, z: z55, alpha } = xyz652;
15627
15872
  if (x === void 0) x = 0;
15628
15873
  if (y === void 0) y = 0;
15629
- if (z50 === void 0) z50 = 0;
15874
+ if (z55 === void 0) z55 = 0;
15630
15875
  let res = {
15631
15876
  mode: "xyz50",
15632
- x: 1.0479298208405488 * x + 0.0229467933410191 * y - 0.0501922295431356 * z50,
15633
- y: 0.0296278156881593 * x + 0.990434484573249 * y - 0.0170738250293851 * z50,
15634
- z: -0.0092430581525912 * x + 0.0150551448965779 * y + 0.7518742899580008 * z50
15877
+ x: 1.0479298208405488 * x + 0.0229467933410191 * y - 0.0501922295431356 * z55,
15878
+ y: 0.0296278156881593 * x + 0.990434484573249 * y - 0.0170738250293851 * z55,
15879
+ z: -0.0092430581525912 * x + 0.0150551448965779 * y + 0.7518742899580008 * z55
15635
15880
  };
15636
15881
  if (alpha !== void 0) {
15637
15882
  res.alpha = alpha;
@@ -15642,15 +15887,15 @@ var convertXyz65ToXyz50_default = convertXyz65ToXyz50;
15642
15887
 
15643
15888
  // ../../node_modules/culori/src/xyz65/convertXyz50ToXyz65.js
15644
15889
  var convertXyz50ToXyz65 = (xyz502) => {
15645
- let { x, y, z: z50, alpha } = xyz502;
15890
+ let { x, y, z: z55, alpha } = xyz502;
15646
15891
  if (x === void 0) x = 0;
15647
15892
  if (y === void 0) y = 0;
15648
- if (z50 === void 0) z50 = 0;
15893
+ if (z55 === void 0) z55 = 0;
15649
15894
  let res = {
15650
15895
  mode: "xyz65",
15651
- x: 0.9554734527042182 * x - 0.0230985368742614 * y + 0.0632593086610217 * z50,
15652
- y: -0.0283697069632081 * x + 1.0099954580058226 * y + 0.021041398966943 * z50,
15653
- z: 0.0123140016883199 * x - 0.0205076964334779 * y + 1.3303659366080753 * z50
15896
+ x: 0.9554734527042182 * x - 0.0230985368742614 * y + 0.0632593086610217 * z55,
15897
+ y: -0.0283697069632081 * x + 1.0099954580058226 * y + 0.021041398966943 * z55,
15898
+ z: 0.0123140016883199 * x - 0.0205076964334779 * y + 1.3303659366080753 * z55
15654
15899
  };
15655
15900
  if (alpha !== void 0) {
15656
15901
  res.alpha = alpha;