@chainpatrol/sdk 1.4.0 → 1.6.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/api/types.ts","../../src/api/date-utils.ts","../../src/api/client.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export type ApiCredential =\n | { kind: \"api-key\"; value: string }\n | { kind: \"bearer\"; value: string };\n\nexport type CredentialProvider = () => ApiCredential | Promise<ApiCredential>;\n\nexport interface ChainPatrolApiClientOptions {\n baseUrl?: string;\n credential: CredentialProvider;\n timeoutMs?: number;\n}\n\nexport interface ConfigEntry {\n id: number;\n title: string;\n /**\n * Human-readable description of what the config does. `null` when unset\n * — most configs seeded before this field existed do not have one.\n */\n description: string | null;\n status: string;\n cron: string | null;\n config: Record<string, unknown>;\n /**\n * Optional brand connection. Present only for org-scoped configs when the\n * config targets a specific brand.\n */\n brandId?: number | null;\n brand?: {\n id: number;\n name: string;\n slug: string;\n } | null;\n /** When the config was first created (ISO 8601, UTC). */\n createdAt: string;\n /**\n * When the config was last updated (ISO 8601, UTC). Pair with the drift\n * healthcheck to spot silent configs untouched in months.\n */\n updatedAt: string;\n /**\n * When the most recent `ThreatDetectionResult` for this config was created\n * (ISO 8601, UTC). Null when the config has never produced a hit. A config\n * with no recent `lastResultAt` is going silent regardless of `updatedAt`.\n */\n lastResultAt: string | null;\n}\n\nexport interface DetectionSource {\n source: string;\n scope: \"global\" | \"organization\";\n configs: ConfigEntry[];\n}\n\nexport interface ApiClient {\n assetCheck: (input: AssetCheckInput) => Promise<AssetCheckResult>;\n assetSearch: (input: AssetSearchInput) => Promise<AssetSearchResult>;\n listAssets: (input: AssetListInput) => Promise<AssetListResult>;\n listDetectionConfigs: (slug: string) => Promise<DetectionSource[]>;\n updateDetectionConfig: (\n input: DetectionConfigUpdateInput,\n ) => Promise<DetectionConfigUpdateResult>;\n runDetectionConfigs: (\n input: DetectionConfigRunInput,\n ) => Promise<DetectionConfigRunResult>;\n validateDetectionConfigs: (\n input: DetectionConfigValidateInput,\n ) => Promise<DetectionConfigValidateResult>;\n getDetectionDrift: (input: DetectionDriftInput) => Promise<DetectionDriftResult>;\n listDetections: (input: DetectionListInput) => Promise<DetectionListResult>;\n getOperationsQueuesSnapshot: (\n input: OperationsQueuesSnapshotInput,\n ) => Promise<OperationsQueuesSnapshotResult>;\n getMetricsSummary: (input: MetricsSummaryInput) => Promise<MetricsSummaryResult>;\n getMetricsFound: (input: MetricsFoundInput) => Promise<MetricsFoundResult>;\n getMetricsBreakdown: (input: MetricsBreakdownInput) => Promise<MetricsBreakdownResult>;\n createReport: (input: ReportCreateInput) => Promise<ReportCreateResult>;\n listOrganizationReports: (\n input: OrganizationReportsListInput,\n ) => Promise<OrganizationReportsListResult>;\n searchReports: (input: ReportsSearchInput) => Promise<ReportsSearchResult>;\n listTakedowns: (input: TakedownsListInput) => Promise<TakedownsListResult>;\n listThreats: (input: ThreatsListInput) => Promise<ThreatsListResult>;\n getOrganizationMetrics: (\n input: OrganizationMetricsInput,\n ) => Promise<OrganizationMetricsResult>;\n listOrganizationAssets: (\n input: OrganizationAssetsListInput,\n ) => Promise<OrganizationAssetsListResult>;\n listOrganizationAssetGroups: () => Promise<OrganizationAssetGroupsListResult>;\n listOrganizationBrands: () => Promise<OrganizationBrandsListResult>;\n listHealthchecks: () => Promise<HealthchecksListResult>;\n runHealthcheck: (\n endpoint: string,\n input: Record<string, unknown>,\n ) => Promise<HealthcheckResult>;\n getUserOrgs: (input: UserOrgsInput) => Promise<UserOrgsResult>;\n getUserOrg: (input: UserOrgGetInput) => Promise<UserOrgGetResult>;\n getCurrentUser: () => Promise<UserMeResult>;\n validateApiKey: () => Promise<ValidateApiKeyResult>;\n}\n\nexport interface AssetCheckInput {\n content: string;\n}\n\nexport type AssetCheckStatus = \"ALLOWED\" | \"BLOCKED\" | \"UNKNOWN\";\n\nexport interface AssetCheckSourceEntry {\n source: string;\n status: AssetCheckStatus;\n}\n\nexport interface AssetCheckResult {\n status: AssetCheckStatus;\n source: string;\n reason?: string;\n sources: AssetCheckSourceEntry[];\n message?: string;\n code?: string;\n watchStatus?: \"ENABLED\" | \"DISABLED\";\n}\n\nexport interface AssetSearchInput {\n content?: string;\n assetId?: number;\n assetIds?: number[];\n}\n\nexport interface AssetSearchResultItem {\n asset: {\n id: number;\n content: string;\n type: string;\n status: string;\n watchStatus: string;\n /**\n * Whether the asset is currently reachable (`\"ALIVE\"`), gone\n * (`\"DEAD\"`), or unchecked (`\"UNKNOWN\"`). Null when never evaluated.\n */\n livenessStatus: LivenessStatus | null;\n /**\n * When the asset transitioned to BLOCKED (ISO 8601, UTC). Null for\n * non-blocked assets or blocks predating the field.\n */\n blockedAt: string | null;\n createdAt: string;\n updatedAt: string;\n } | null;\n reports: Array<{\n id: number;\n title: string | null;\n status: string;\n createdAt: string;\n }>;\n takedown: {\n id: number;\n status: string;\n createdAt: string;\n updatedAt: string;\n tasks: Array<{\n id: number;\n type: string;\n status: string;\n retractionStatus: string;\n externalId: string | null;\n submittedAt: string | null;\n retractedAt: string | null;\n lastResponseAt: string | null;\n createdAt: string;\n updatedAt: string;\n takedownProvider: { name: string } | null;\n }>;\n } | null;\n blockedBy: Array<{\n consumer: string;\n name: string | null;\n consumedAt: string;\n }>;\n}\n\nexport interface AssetSearchResult extends AssetSearchResultItem {\n results?: AssetSearchResultItem[];\n}\n\nexport interface AssetListInput {\n type: string;\n status?: string;\n startDate?: string;\n endDate?: string;\n perPage?: number;\n nextPage?: string;\n}\n\nexport interface AssetListItem {\n /** Asset ID — reference in follow-up calls (was previously stripped from the response). */\n id: number;\n content: string;\n type: string;\n status: string;\n watchStatus: string;\n /**\n * Whether the asset is currently reachable (`\"ALIVE\"`), gone\n * (`\"DEAD\"`), or unchecked (`\"UNKNOWN\"`). Null when never evaluated.\n */\n livenessStatus: LivenessStatus | null;\n /**\n * When the asset transitioned to BLOCKED (ISO 8601, UTC). Null for\n * non-blocked assets.\n */\n blockedAt: string | null;\n updatedAt: string;\n}\n\nexport interface AssetListResult {\n assets: AssetListItem[];\n next_page: string | null;\n}\n\nexport interface DetectionConfigUpdateInput {\n slug: string;\n configId: number;\n status?: \"ENABLED\" | \"DISABLED\";\n title?: string;\n description?: string | null;\n cron?: string | null;\n config?: Record<string, unknown>;\n mergeConfig?: boolean;\n}\n\nexport interface DetectionConfigUpdateResult {\n config: {\n id: number;\n source: string;\n status: string;\n title: string;\n description: string | null;\n cron: string | null;\n config: Record<string, unknown>;\n updatedAt: string;\n };\n}\n\nexport interface DetectionConfigRunInput {\n slug: string;\n configId?: number;\n source?: string;\n includeDisabled?: boolean;\n}\n\nexport interface DetectionConfigRunResult {\n ranCount: number;\n successCount: number;\n failedCount: number;\n results: Array<{\n configId: number;\n source: string;\n ok: boolean;\n message: string | null;\n assetsCount: number;\n }>;\n}\n\nexport interface DetectionConfigValidateInput {\n slug: string;\n source?: string;\n minResults?: number;\n lookbackHours?: number;\n runBeforeValidate?: boolean;\n includeDisabled?: boolean;\n}\n\nexport interface DetectionConfigValidateResult {\n ok: boolean;\n summary: {\n checkedConfigs: number;\n passingConfigs: number;\n failingConfigs: number;\n lookbackHours: number;\n minResults: number;\n };\n validations: Array<{\n configId: number;\n source: string;\n status: string;\n ran: boolean;\n runOk: boolean;\n runMessage: string | null;\n recentResultCount: number;\n valid: boolean;\n }>;\n}\n\nexport interface DetectionDriftInput {\n slug: string;\n lookbackHours?: number;\n startDate?: string;\n endDate?: string;\n source?: string;\n configIds?: number[];\n includeDisabled?: boolean;\n thresholds?: {\n zeroResultsMaxHours?: number;\n noisyResultsPerDay?: number;\n noisyAllowedRatioThreshold?: number;\n staleConfigDays?: number;\n };\n}\n\nexport interface DetectionDriftResult {\n ok: boolean;\n range: {\n startDate: string;\n endDate: string;\n lookbackHours: number;\n };\n thresholds: {\n zeroResultsMaxHours: number;\n noisyResultsPerDay: number;\n noisyAllowedRatioThreshold: number;\n staleConfigDays: number;\n };\n summary: {\n checkedConfigs: number;\n signalCount: number;\n zeroResultsCount: number;\n noisyCount: number;\n staleCount: number;\n };\n signals: Array<{\n signal: \"zero_results_too_long\" | \"noisy_source\" | \"stale_query\";\n configId: number;\n source: string;\n title: string | null;\n status: string;\n severity: \"low\" | \"medium\" | \"high\";\n details: Record<string, unknown>;\n }>;\n}\n\nexport interface OperationsQueuesSnapshotInput {\n slug?: string;\n all?: boolean;\n windowHours?: number;\n}\n\nexport interface OperationsQueuesSnapshotResult {\n generatedAt: string;\n scope: {\n slug: string | null;\n all: boolean;\n };\n reviewQueue: {\n totalPendingProposals: number;\n distinctReports: number;\n ageBuckets: {\n lt24h: number;\n h24to72: number;\n h72to168: number;\n gte168h: number;\n };\n slaBuckets: {\n breached: number;\n dueWithin24h: number;\n dueWithin72h: number;\n beyond72h: number;\n missingSla: number;\n };\n byOrg: Array<{ slug: string; pendingProposals: number }>;\n };\n takedownQueue: {\n totalOpen: number;\n statusCounts: {\n todo: number;\n inProgress: number;\n pendingInput: number;\n };\n ageBuckets: {\n lt24h: number;\n h24to72: number;\n h72to168: number;\n gte168h: number;\n };\n staleInProgress: number;\n byOrg: Array<{ slug: string; openTakedowns: number }>;\n };\n}\n\nexport interface MetricsSummaryInput {\n slug: string;\n startDate?: string;\n endDate?: string;\n brandIds?: number[];\n}\n\nexport interface MetricsSummaryResult {\n metrics: {\n reports: number;\n newThreats: number;\n threatsWatchlisted: number;\n takedownsFiled: number;\n takedownsCompleted: number;\n domainThreats: number;\n twitterThreats: number;\n telegramThreats: number;\n otherThreats: number;\n };\n blockedByDay: Array<{ date: string; count: number }>;\n blockedByType: Array<{ type: string; count: number }>;\n}\n\nexport interface MetricsFoundInput {\n slug: string;\n startDate: string;\n endDate: string;\n brandIds?: number[];\n}\n\nexport interface MetricsFoundResult {\n metric: \"new_threats\";\n found: number;\n range: {\n startDate: string;\n endDate: string;\n };\n}\n\nexport interface MetricsBreakdownInput {\n slug: string;\n by: \"day\" | \"type\" | \"brand\";\n startDate?: string;\n endDate?: string;\n brandIds?: number[];\n}\n\nexport interface MetricsBreakdownResult {\n by: \"day\" | \"type\" | \"brand\";\n points: Array<{\n key: string;\n count: number;\n date?: string;\n type?: string;\n brandId?: number;\n brandSlug?: string;\n brandName?: string;\n }>;\n}\n\nexport interface ReportAssetInput {\n content: string;\n status?: \"BLOCKED\" | \"ALLOWED\" | \"UNKNOWN\";\n brandSlug?: string;\n}\n\nexport interface ReportCreateInput {\n organizationSlug?: string;\n title?: string;\n description?: string;\n contactInfo?: string;\n attachmentUrls?: string[];\n externalSubmissionLink?: string;\n userAgent?: string;\n referrer?: string;\n assets: ReportAssetInput[];\n rawAssetsInput?: string;\n externalReporter?: {\n avatarUrl?: string;\n platformIdentifier: string;\n platform: string;\n displayName: string;\n };\n}\n\nexport interface ReportCreateResult {\n id: number;\n createdAt: string;\n organization: {\n id: number;\n slug: string;\n name: string;\n } | null;\n}\n\nexport const REPORT_REVIEW_DECISIONS = [\"APPROVE\", \"REJECT\", \"SKIP\", \"ESCALATE\"] as const;\nexport type ReportReviewDecision = (typeof REPORT_REVIEW_DECISIONS)[number];\n\nexport const REPORT_STATUSES = [\"TODO\", \"IN_PROGRESS\", \"CLOSED\"] as const;\nexport type ReportStatus = (typeof REPORT_STATUSES)[number];\n\nexport const ACTOR_KINDS = [\"human\", \"automation\"] as const;\nexport type ActorKind = (typeof ACTOR_KINDS)[number];\n\nexport interface OrganizationReportsListInput {\n slug: string;\n limit?: number;\n cursor?: number;\n status?: string;\n searchQuery?: string;\n reporterQuery?: string;\n reportedByCustomer?: boolean;\n /** @deprecated Prefer `reporterKind: \"human\"`. */\n excludeAutomation?: boolean;\n /** Filter by whether the report was submitted by a human or automation. */\n reporterKind?: ActorKind;\n /** Filter by whether the report was approved by a human or automation. */\n reviewerKind?: ActorKind;\n onlyRejected?: boolean;\n reviewStatuses?: ReportReviewDecision[];\n assetTypes?: string[];\n brandIds?: number[];\n countryCodes?: string[];\n reviewedByUserId?: number;\n startDate?: string;\n endDate?: string;\n updatedAtStartDate?: string;\n updatedAtEndDate?: string;\n /**\n * Filter to reports waiting on the organization's own approval — the reports\n * a customer admin still has to sign off on before the assets in them can be\n * blocked. `true` returns only those reports; `false` returns only reports\n * that are not waiting on them.\n *\n * When \"Obligatory Organization Admin Approval\" is on for the organization,\n * that means every report with a pending proposal whose asset type is in the\n * approval scope (all asset types when the scope has not been narrowed), plus\n * anything ChainPatrol staff escalated to the organization. When the setting\n * is off, only reports staff escalated to the organization are returned.\n * Reports the organization submitted itself are never included — staff can\n * action those without customer sign-off.\n */\n needsCustomerReview?: boolean;\n}\n\nexport interface OrganizationReportAssetScanEnrichment {\n id: number;\n type: string;\n output: unknown;\n status: string;\n}\n\nexport interface OrganizationReportAssetScan {\n id: number;\n status: string;\n output: unknown;\n createdAt: string;\n enrichments: OrganizationReportAssetScanEnrichment[];\n}\n\nexport interface OrganizationReportAttachment {\n id: number;\n url: string;\n}\n\nexport interface OrganizationReportsListResult {\n reports: Array<{\n id: number;\n title: string;\n description: string;\n /** Whether the report's images render inline or are hidden by default. */\n imageDisplay: string;\n /** When the report was starred/favorited (ISO 8601, UTC). Null when not favorited. */\n favoritedAt: string | null;\n status: string | null;\n reportedByCustomer: boolean;\n /**\n * SLA deadline for this report (ISO 8601, UTC). Null when no SLA\n * applies (e.g. staff-created reports).\n */\n slaDueAt: string | null;\n /**\n * URL to the original external source of the report when submitted\n * from a third-party surface (Discord/Twitter link, forwarded webform).\n * Null for reports created directly in ChainPatrol.\n */\n externalSubmissionLink: string | null;\n /**\n * ID of the canonical report this one duplicates. Null when the\n * report is not a duplicate.\n */\n duplicateOfId: number | null;\n createdAt: string;\n updatedAt: string;\n attachments: OrganizationReportAttachment[];\n proposals: Array<{\n reviewStatus: string;\n asset: {\n id: number;\n type: string;\n content: string;\n status: string;\n /**\n * Per-scan enrichment data. Large (Apple App Store enrichments run\n * 50–200 KB each) — the agent42 tool strips these by default when\n * relaying results. Present in the raw handler response.\n */\n scans: OrganizationReportAssetScan[];\n };\n }>;\n reporter: {\n id: number;\n role: string;\n fullName: string;\n avatarUrl: string | null;\n } | null;\n externalReporter: {\n id: number;\n displayName: string | null;\n avatarUrl: string | null;\n platform: string;\n } | null;\n }>;\n nextCursor: number | null;\n totalCount: number;\n}\n\nexport const DETECTION_CONFIDENCE_LEVELS = [\"none\", \"low\", \"medium\", \"high\"] as const;\nexport type DetectionConfidence = (typeof DETECTION_CONFIDENCE_LEVELS)[number];\nexport type DetectionReportStatus = \"REPORTED\" | \"NOT_REPORTED\";\n\nexport const DETECTION_REPORTED_FILTERS = [\"reported\", \"not_reported\"] as const;\nexport type DetectionReportedFilter = (typeof DETECTION_REPORTED_FILTERS)[number];\n\nexport const LIVENESS_FILTER_VALUES = [\"ALIVE\", \"DEAD\", \"UNKNOWN\"] as const;\nexport type LivenessFilterValue = (typeof LIVENESS_FILTER_VALUES)[number];\n\nexport const WATCHLIST_FILTER_VALUES = [\"ENABLED\", \"DISABLED\"] as const;\nexport type WatchlistFilterValue = (typeof WATCHLIST_FILTER_VALUES)[number];\n\nexport interface DetectionListInput {\n slug: string;\n cursor?: number;\n limit?: number;\n query?: string;\n startDate?: string;\n endDate?: string;\n sources?: string[];\n confidence?: DetectionConfidence[];\n assetStatus?: string[];\n assetType?: string[];\n brandIds?: number[];\n liveness?: LivenessFilterValue[];\n watchlist?: WatchlistFilterValue[];\n reported?: DetectionReportedFilter[];\n countryCodes?: string[];\n onlyDeleted?: boolean;\n}\n\nexport interface DetectionBrand {\n id: number;\n name: string;\n slug: string;\n}\n\nexport interface DetectionListItem {\n id: number;\n threatContent: string;\n source: string;\n createdAt: string;\n confidence: DetectionConfidence;\n /**\n * Raw model score (0–1). `confidence` buckets this into low/medium/high\n * using the org's thresholds; use `score` when the buckets are too coarse.\n */\n score: number;\n /**\n * Free-text explanation of why the detection fired (e.g. \"matches\n * brand-name typo squat\", \"TLS cert issued by known lookalike CA\").\n */\n reason: string;\n /**\n * ID of the `ThreatDetectionConfig` that produced this hit. Pair with\n * `listDetectionConfigs` to drill back into the config.\n */\n configId: number;\n /**\n * When the detection was reported (ISO 8601, UTC). Null when the\n * detection has not been reported yet.\n */\n reportedAt: string | null;\n /**\n * Brands the detection was associated with. Empty when the detection\n * was not linked to any brand at classification time.\n */\n brands: DetectionBrand[];\n reportStatus: DetectionReportStatus;\n asset: {\n id: number;\n content: string;\n type: string;\n status: string;\n };\n}\n\nexport interface DetectionListResult {\n detections: DetectionListItem[];\n nextCursor?: number;\n}\n\nexport interface ThreatsListInput {\n query?: string;\n startDate?: string;\n endDate?: string;\n assetType?: string[];\n sorting?: Array<{ key: string; direction: \"asc\" | \"desc\" }>;\n perPage?: number;\n nextPage?: string;\n}\n\nexport interface ThreatItem {\n id: number;\n content: string;\n type: string;\n /**\n * Liveness of the blocked threat. `\"ALIVE\"` still reachable, `\"DEAD\"`\n * gone, `\"UNKNOWN\"` unchecked. Null when never evaluated.\n */\n livenessStatus: LivenessStatus | null;\n blockedAt: string;\n}\n\nexport interface ThreatsListResult {\n threats: ThreatItem[];\n next_page: string | null;\n}\n\nexport interface OrganizationAssetsListInput {\n type?: string;\n groupId?: number;\n query?: string;\n perPage?: number;\n nextPage?: string;\n}\n\nexport interface OrganizationAssetItem {\n id: number;\n content: string;\n type: string;\n status: string;\n name: string | null;\n description: string | null;\n group: { id: number; name: string } | null;\n /**\n * Whether the asset is currently reachable (`\"ALIVE\"`), gone\n * (`\"DEAD\"`), or unchecked (`\"UNKNOWN\"`). Null when never evaluated.\n */\n livenessStatus: LivenessStatus | null;\n /**\n * When the asset transitioned to BLOCKED (ISO 8601, UTC). Null for\n * non-blocked assets.\n */\n blockedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface OrganizationAssetsListResult {\n assets: OrganizationAssetItem[];\n next_page: string | null;\n}\n\nexport interface AssetGroupItem {\n id: number;\n name: string;\n assetCount: number;\n}\n\nexport interface OrganizationAssetGroupsListResult {\n groups: AssetGroupItem[];\n}\n\nexport type BrandType = \"ORGANIZATION\" | \"INDIVIDUAL\";\n\nexport interface BrandLegalDocument {\n present: boolean;\n fileName: string | null;\n fileUrl: string | null;\n}\n\nexport interface BrandLegalDocuments {\n letterOfAuthorization: BrandLegalDocument;\n powerOfAttorney: BrandLegalDocument;\n}\n\nexport interface BrandTrademarkRegistrationItem {\n id: number;\n brandName: string;\n trademarkOffice: string;\n registrationNumber: string;\n goodsAndServicesClass: string;\n rightsOwnerName: string | null;\n registrationPageUrl: string | null;\n certificateFileName: string | null;\n certificateFileUrl: string | null;\n}\n\nexport interface BrandItem {\n id: number;\n slug: string;\n name: string;\n type: BrandType;\n description: string | null;\n avatarUrl: string | null;\n websiteUrl: string | null;\n twitterHandle: string | null;\n brandColors: string[];\n includedTerms: string[];\n excludedTerms: string[];\n tickers: string[];\n brandGroupId: number | null;\n createdAt: string;\n useOrganizationDocs: boolean;\n legalDocuments: BrandLegalDocuments;\n trademarkRegistrations: BrandTrademarkRegistrationItem[];\n}\n\nexport interface OrganizationBrandsListResult {\n brands: BrandItem[];\n}\n\nexport interface ReportsSearchInput {\n assetContents: string[];\n /**\n * Organization slug. Optional for organization-scoped API keys, which resolve\n * the organization from the key itself. Required when your credentials can\n * reach more than one organization — including the bearer token issued by\n * `chainpatrol login`.\n */\n slug?: string;\n reportedByCustomer?: boolean;\n /**\n * Maximum number of reports to return, newest first. Defaults to 50, maximum\n * 100. Compare with `totalCount` to tell whether results were truncated.\n */\n limit?: number;\n}\n\nexport interface ReportsSearchResultItem {\n id: number;\n /**\n * Report title. Null for external / anonymous reports without one.\n */\n title: string | null;\n status: string;\n reportedByCustomer: boolean;\n /** When the report was created (ISO 8601, UTC). */\n createdAt: string;\n assets: string[];\n}\n\nexport interface ReportsSearchResult {\n reports: ReportsSearchResultItem[];\n /**\n * Total number of reports matching the search, ignoring `limit`. Greater than\n * `reports.length` means the results were truncated.\n */\n totalCount: number;\n}\n\nexport interface UserMeResult {\n user: {\n id: number;\n name: string;\n avatarUrl: string | null;\n email: string;\n role: string;\n protectionConfig: {\n linkMonitoring: boolean;\n socialMediaScanning: boolean;\n historyScanning: boolean;\n } | null;\n };\n}\n\nexport interface ValidateApiKeyResult {\n status: \"success\";\n message: string;\n}\n\nexport const TAKEDOWN_STATUSES = [\n \"TODO\",\n \"IN_PROGRESS\",\n \"COMPLETED\",\n \"CANCELLED\",\n \"PENDING_RETRACTION\",\n \"RETRACTION_SENT\",\n \"RETRACTED\",\n \"PENDING_INPUT\",\n] as const;\nexport type TakedownStatus = (typeof TAKEDOWN_STATUSES)[number];\n\nexport const LIVENESS_STATUSES = [\"UNKNOWN\", \"ALIVE\", \"DEAD\"] as const;\nexport type LivenessStatus = (typeof LIVENESS_STATUSES)[number];\n\nexport const TAKEDOWN_SORT_KEYS = [\n \"updatedAt\",\n \"createdAt\",\n \"takedownStatus\",\n \"takedownUpdatedAt\",\n \"assigneeId\",\n \"brandId\",\n] as const;\nexport type TakedownSortKey = (typeof TAKEDOWN_SORT_KEYS)[number];\n\nexport interface TakedownsListInput {\n organizationSlug?: string;\n query?: string;\n startDate?: string;\n endDate?: string;\n assetType?: string[];\n takedownStatus?: TakedownStatus[];\n livenessStatus?: LivenessStatus[];\n brandIds?: number[];\n assigneeIds?: number[];\n startedAtStartDate?: string;\n startedAtEndDate?: string;\n hideAutomatedTakedowns?: boolean;\n hideAutomatedLivenessChecks?: boolean;\n sorting?: Array<{ key: TakedownSortKey; direction: \"asc\" | \"desc\" }>;\n perPage?: number;\n nextPage?: string;\n}\n\nexport interface TakedownItem {\n id: number;\n status: TakedownStatus;\n /**\n * Provider's own reference for this takedown (e.g. CleanDNS report ID,\n * registrar ticket). Reconcile with the vendor's dashboard. `null` when\n * no vendor has picked it up yet.\n */\n externalId: string | null;\n /**\n * Manually set by staff to exclude the takedown from median-time metrics\n * when its filing was delayed for reasons unrelated to platform\n * performance.\n */\n hasFilingDelay: boolean;\n /**\n * Manually set by staff to exclude the takedown from median-time metrics\n * when the liveness-check step was delayed for reasons unrelated to\n * platform performance.\n */\n hasLivenessCheckDelay: boolean;\n createdAt: string;\n updatedAt: string;\n asset: {\n id: number;\n content: string;\n type: string;\n livenessStatus: LivenessStatus | null;\n /**\n * When the asset transitioned to BLOCKED (ISO 8601, UTC). Null if the\n * asset was never blocked (rare for takedown rows).\n */\n blockedAt: string | null;\n };\n assignee: {\n id: number;\n fullName: string | null;\n } | null;\n brand: {\n id: number;\n name: string;\n slug: string | null;\n } | null;\n /**\n * Domain registrar assigned to this takedown (e.g. Namecheap, GoDaddy).\n * Null when unresolved. Distinct from per-task `takedownProvider` — this\n * is the takedown-level assignment for the domain itself.\n */\n domainRegistrar: TakedownProviderRef | null;\n /**\n * Hosting provider assigned to this takedown (e.g. Cloudflare, AWS).\n * Answers \"who hosts this?\" without a follow-up call. Null when unresolved.\n */\n hostingProvider: TakedownProviderRef | null;\n /**\n * Top-level-domain registrar assigned to this takedown (e.g. Verisign).\n * Null when unresolved.\n */\n tldRegistrar: TakedownProviderRef | null;\n}\n\nexport interface TakedownProviderRef {\n id: number;\n name: string;\n}\n\nexport interface TakedownsListResult {\n takedowns: TakedownItem[];\n next_page: string | null;\n}\n\nexport const ORGANIZATION_METRICS_INCLUDE_FIELDS = [\n \"reports\",\n \"newThreats\",\n \"threatsWatchlisted\",\n \"takedownsFiled\",\n \"takedownsCompleted\",\n \"domainThreats\",\n \"twitterThreats\",\n \"telegramThreats\",\n \"otherThreats\",\n \"blockedByType\",\n \"blockedByDay\",\n] as const;\n\nexport type OrganizationMetricsIncludeField =\n (typeof ORGANIZATION_METRICS_INCLUDE_FIELDS)[number];\n\nexport interface OrganizationMetricsServicesFilter {\n reporting?: { active?: boolean };\n reviewing?: { active?: boolean };\n protection?: { active?: boolean };\n takedowns?: { active?: boolean; automated?: boolean };\n detection?: { active?: boolean };\n darkWebMonitoring?: { active?: boolean };\n}\n\nexport interface OrganizationMetricsInput {\n organizationSlug?: string;\n slugs?: string[];\n allMyOrgs?: boolean;\n subscriptionStatus?: string[];\n services?: OrganizationMetricsServicesFilter;\n brandSlug?: string;\n startDate?: string;\n endDate?: string;\n include?: OrganizationMetricsIncludeField[];\n}\n\nexport interface OrganizationMetricsResultMetrics {\n reports: number | null;\n newThreats: number | null;\n threatsWatchlisted: number | null;\n takedownsFiled: number | null;\n takedownsCompleted: number | null;\n domainThreats: number | null;\n twitterThreats: number | null;\n telegramThreats: number | null;\n otherThreats: number | null;\n}\n\nexport interface OrganizationMetricsResult {\n metrics: OrganizationMetricsResultMetrics;\n blockedByType: Array<{ type: string; count: number }> | null;\n blockedByDay: Array<{ date: string; count: number }> | null;\n averages: {\n perDay: OrganizationMetricsResultMetrics | null;\n perOrgPerDay: OrganizationMetricsResultMetrics | null;\n windowDays: number | null;\n };\n perOrg: Record<\n string,\n {\n metrics: OrganizationMetricsResultMetrics;\n blockedByType: Array<{ type: string; count: number }> | null;\n blockedByDay: Array<{ date: string; count: number }> | null;\n }\n > | null;\n scope: {\n mode: \"single\" | \"multi\";\n orgs: string[];\n resolvedFrom: \"api-key\" | \"organizationSlug\" | \"slugs\" | \"allMyOrgs\";\n };\n}\n\nexport type HealthcheckCategory =\n | \"detection\"\n | \"reviewing\"\n | \"blocklisting\"\n | \"takedowns\"\n | \"assets\"\n | \"organization\";\n\nexport type HealthcheckSeverity = \"ok\" | \"warn\" | \"fail\";\n\nexport interface HealthcheckFinding {\n kind: string;\n ref: string | null;\n message: string;\n severity: \"warn\" | \"fail\";\n}\n\nexport interface HealthcheckResult {\n id: string;\n title: string;\n category: HealthcheckCategory;\n generatedAt: string;\n scope: { slug: string | null };\n ok: boolean;\n severity: HealthcheckSeverity;\n observed: Record<string, number | string | boolean | null>;\n threshold: Record<string, number | string | boolean | null>;\n findings: HealthcheckFinding[];\n suggestedAction: string | null;\n appUrl: string | null;\n}\n\nexport interface HealthcheckRegistryEntry {\n id: string;\n title: string;\n description: string;\n category: HealthcheckCategory;\n implemented: boolean;\n endpoint: string | null;\n defaultThreshold?: Record<string, number | string>;\n notImplementedReason?: string;\n}\n\nexport interface HealthchecksListResult {\n checks: HealthcheckRegistryEntry[];\n}\n\nexport type UserOrgsSubscriptionStatus = \"PROSPECT\" | \"POC\" | \"ACTIVE\" | \"INTEGRATION\";\n\nexport type PendingApprovalService = \"protection\" | \"takedowns\";\n\nexport interface PendingServiceApproval {\n service: PendingApprovalService;\n automated: boolean;\n serviceType: string;\n serviceName: string;\n requestedAt: string;\n}\n\nexport interface UserOrgsServiceFilters {\n reporting?: { active?: boolean };\n reviewing?: { active?: boolean };\n protection?: { active?: boolean };\n takedowns?: { active?: boolean; automated?: boolean };\n detection?: { active?: boolean };\n darkWebMonitoring?: { active?: boolean };\n}\n\nexport interface UserOrgsObligatoryAdminApprovalFilter {\n active?: boolean;\n assetTypes?: string[];\n}\n\nexport interface UserOrgsPendingServiceApprovalFilter {\n active?: boolean;\n services?: PendingApprovalService[];\n}\n\nexport interface UserOrgsInput {\n query?: string;\n subscriptionStatus?: UserOrgsSubscriptionStatus[];\n services?: UserOrgsServiceFilters;\n obligatoryAdminApproval?: UserOrgsObligatoryAdminApprovalFilter;\n pendingServiceApproval?: UserOrgsPendingServiceApprovalFilter;\n}\n\nexport interface UserOrgIntegrations {\n slack: boolean;\n discord: boolean;\n telegram: { connected: boolean; groupCount: number };\n vercel: boolean;\n intercom: boolean;\n moderation: boolean;\n}\n\nexport interface UserOrgLegalDocument {\n present: boolean;\n fileName: string | null;\n fileUrl: string | null;\n}\n\nexport interface UserOrgLegalDocuments {\n letterOfAuthorization: UserOrgLegalDocument;\n powerOfAttorney: UserOrgLegalDocument;\n}\n\nexport interface UserOrgTrademarkRegistration {\n id: number;\n brandName: string;\n trademarkOffice: string;\n registrationNumber: string;\n goodsAndServicesClass: string;\n rightsOwnerName: string | null;\n registrationPageUrl: string | null;\n certificateFileName: string | null;\n certificateFileUrl: string | null;\n}\n\nexport type OrganizationPortalVisibility = \"PUBLIC\" | \"PRIVATE\" | \"DISABLED\";\n\nexport type OrganizationReportVisibility = \"PUBLIC\" | \"PRIVATE\";\n\nexport type OrganizationMetricsVisibility = \"PUBLIC\" | \"PRIVATE\" | \"DISABLED\";\n\nexport interface UserOrgBrandMetadata {\n /** Public website URL of the brand (linked from the portal header). */\n websiteUrl: string | null;\n /** Public Twitter/X handle of the brand, stored with the leading `@` (e.g. `@acme`). */\n twitterHandle: string | null;\n /**\n * Email address for security correspondence — used by takedown providers\n * and researchers, distinct from the internal customer POC email.\n */\n securityContactEmail: string | null;\n /** Free-form industry label (e.g. `\"DeFi\"`, `\"CEX\"`, `\"NFT\"`, `\"Wallet\"`). */\n industry: string | null;\n}\n\nexport interface UserOrgPortalCustomization {\n /**\n * When `true`, the portal uses `name` / `slug` / `avatarUrl` from this\n * object instead of the org's own name / slug / avatar.\n */\n useCustomDetails: boolean;\n /** Custom display name shown on the portal (used only when `useCustomDetails=true`). */\n name: string | null;\n /**\n * Custom URL slug (`chainpatrol.io/<slug>`) — takes precedence over the\n * org's own slug when set, regardless of `useCustomDetails`.\n */\n slug: string | null;\n /** Custom avatar URL shown on the portal (used only when `useCustomDetails=true`). */\n avatarUrl: string | null;\n /** When `true`, the portal renders `bannerContent` as a highlighted banner. */\n bannerEnabled: boolean;\n /**\n * Markdown body of the portal banner. Null (or empty) with\n * `bannerEnabled=true` means the toggle is on but no content has been\n * written yet.\n */\n bannerContent: string | null;\n}\n\nexport interface UserOrg {\n id: number;\n name: string;\n slug: string;\n avatarUrl: string | null;\n contactUrl: string | null;\n subscriptionStatus: \"PROSPECT\" | \"POC\" | \"ACTIVE\" | \"INTEGRATION\" | \"INACTIVE\";\n /**\n * Visibility of the org's public security portal (chainpatrol.io/<slug>).\n * - `PUBLIC` — portal is fully discoverable (metrics, listings, report form).\n * - `PRIVATE` — only the report form is rendered; no metrics or listings.\n * - `DISABLED` — the portal returns a 404.\n */\n portalVisibility: OrganizationPortalVisibility;\n /**\n * Whether the report listings on the public portal are visible to\n * visitors. `PUBLIC` shows the org's reports; `PRIVATE` hides the report\n * list even when the portal is discoverable.\n */\n reportVisibility: OrganizationReportVisibility;\n /**\n * Whether the metrics / threats-blocked stats render on the public portal.\n * - `PUBLIC` — metrics tab is visible.\n * - `PRIVATE` — metrics tab is hidden from anonymous visitors.\n * - `DISABLED` — metrics are not computed for this org.\n */\n metricsVisibility: OrganizationMetricsVisibility;\n /**\n * Public brand-facing metadata (website, twitter, security contact,\n * industry) shown on the portal and used by staff for outbound.\n */\n brandMetadata: UserOrgBrandMetadata;\n /**\n * Customer-configurable presentation of the public security portal —\n * custom name / slug / avatar and the banner content.\n */\n portalCustomization: UserOrgPortalCustomization;\n services: {\n reporting: { active: boolean };\n reviewing: { active: boolean };\n protection: { active: boolean };\n takedowns: { active: boolean; automated: boolean };\n detection: { active: boolean };\n darkWebMonitoring: { active: boolean };\n };\n integrations: UserOrgIntegrations;\n obligatoryAdminApproval: {\n active: boolean;\n assetTypes: string[];\n };\n pendingServiceApprovals: PendingServiceApproval[];\n legalDocuments: UserOrgLegalDocuments;\n trademarkRegistrations: UserOrgTrademarkRegistration[];\n}\n\nexport interface UserOrgsResult {\n organizations: UserOrg[];\n}\n\nexport interface UserOrgGetInput {\n slug: string;\n}\n\nexport interface UserOrgGetResult {\n organization: UserOrg;\n}\n","const ISO_DATE_REGEX =\n /^(\\d{4})-(\\d{2})-(\\d{2})(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\n\nexport function parseIsoDate(value: string | undefined): Date | undefined {\n if (!value) return undefined;\n const m = ISO_DATE_REGEX.exec(value);\n if (!m) {\n throw new Error(`Invalid ISO date: '${value}'. Use YYYY-MM-DD or full ISO 8601.`);\n }\n // Normalize offset-less datetimes to UTC (matches Luxon's { zone: \"utc\" } behavior).\n // Date-only strings are already UTC per ECMAScript spec.\n const hasTime = m[4] !== undefined;\n const hasOffset = m[7] !== undefined;\n const normalized = hasTime && !hasOffset ? value + \"Z\" : value;\n const date = new Date(normalized);\n if (Number.isNaN(date.getTime())) {\n throw new Error(`Invalid ISO date: '${value}'. Use YYYY-MM-DD or full ISO 8601.`);\n }\n // Reject impossible calendar dates that Date rolls forward (e.g. Feb 31 → Mar 3)\n if (\n date.getUTCFullYear() !== Number(m[1]) ||\n date.getUTCMonth() + 1 !== Number(m[2]) ||\n date.getUTCDate() !== Number(m[3])\n ) {\n throw new Error(`Invalid ISO date: '${value}'. Use YYYY-MM-DD or full ISO 8601.`);\n }\n return date;\n}\n\nexport function parseIsoDateString(value: string | undefined): string | undefined {\n return parseIsoDate(value)?.toISOString();\n}\n","import { parseIsoDate, parseIsoDateString } from \"./date-utils\";\nimport type {\n ApiClient,\n ApiCredential,\n AssetCheckInput,\n AssetCheckResult,\n AssetListInput,\n AssetListResult,\n AssetSearchInput,\n AssetSearchResult,\n ChainPatrolApiClientOptions,\n CredentialProvider,\n DetectionConfigRunInput,\n DetectionConfigRunResult,\n DetectionConfigUpdateInput,\n DetectionConfigUpdateResult,\n DetectionConfigValidateInput,\n DetectionConfigValidateResult,\n DetectionDriftInput,\n DetectionDriftResult,\n DetectionListInput,\n DetectionListResult,\n DetectionSource,\n HealthcheckResult,\n HealthchecksListResult,\n MetricsBreakdownInput,\n MetricsBreakdownResult,\n MetricsFoundInput,\n MetricsFoundResult,\n MetricsSummaryInput,\n MetricsSummaryResult,\n OperationsQueuesSnapshotInput,\n OperationsQueuesSnapshotResult,\n OrganizationAssetsListInput,\n OrganizationAssetsListResult,\n OrganizationAssetGroupsListResult,\n OrganizationBrandsListResult,\n OrganizationMetricsInput,\n OrganizationMetricsResult,\n OrganizationReportsListInput,\n OrganizationReportsListResult,\n ReportCreateInput,\n ReportCreateResult,\n ReportsSearchInput,\n ReportsSearchResult,\n TakedownsListInput,\n TakedownsListResult,\n ThreatsListInput,\n ThreatsListResult,\n UserMeResult,\n UserOrgGetInput,\n UserOrgGetResult,\n UserOrgsInput,\n UserOrgsResult,\n ValidateApiKeyResult,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://app.chainpatrol.io\";\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nfunction trimTrailingSlashes(url: string): string {\n return url.replace(/\\/+$/, \"\");\n}\n\n/**\n * Query params are strings, and `requestGet` drops `undefined`, so booleans and\n * numbers have to be stringified without turning \"unset\" into a value.\n * `String(false)` is `\"false\"`, which the API distinguishes from an absent\n * param — passing `false` filters, passing nothing does not.\n */\nfunction optionalBooleanParam(value: boolean | undefined): string | undefined {\n return value === undefined ? undefined : String(value);\n}\n\nfunction optionalNumberParam(value: number | undefined): string | undefined {\n return value === undefined ? undefined : String(value);\n}\n\nexport function staticApiKey(key: string): CredentialProvider {\n return () => ({ kind: \"api-key\", value: key });\n}\n\nexport function staticBearerToken(token: string): CredentialProvider {\n return () => ({ kind: \"bearer\", value: token });\n}\n\nexport class ChainPatrolApiClient implements ApiClient {\n private readonly baseUrl: string;\n private readonly credential: CredentialProvider;\n private readonly timeoutMs: number;\n\n constructor(options: ChainPatrolApiClientOptions) {\n this.baseUrl = trimTrailingSlashes(options.baseUrl ?? DEFAULT_BASE_URL);\n this.credential = options.credential;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n private async buildAuthHeaders(): Promise<Record<string, string>> {\n const credential = await this.credential();\n const headers: Record<string, string> = {};\n if (credential.kind === \"api-key\") {\n headers[\"x-api-key\"] = credential.value;\n } else {\n headers[\"Authorization\"] = `Bearer ${credential.value}`;\n }\n return headers;\n }\n\n private async requestGet<T>(\n path: string,\n query: Record<string, string | string[] | undefined>,\n ): Promise<T> {\n const headers = await this.buildAuthHeaders();\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== undefined && item !== \"\") {\n search.append(key, item);\n }\n }\n continue;\n }\n if (value !== \"\") {\n search.set(key, value);\n }\n }\n const queryString = search.toString();\n const url = `${this.baseUrl}/api/v2${path}${queryString ? `?${queryString}` : \"\"}`;\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"GET\",\n headers,\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n throw this.wrapFetchError(err);\n }\n\n return this.handleResponse<T>(res);\n }\n\n private async request<T>(path: string, body: unknown): Promise<T> {\n const headers = await this.buildAuthHeaders();\n headers[\"Content-Type\"] = \"application/json\";\n\n let res: Response;\n try {\n res = await fetch(`${this.baseUrl}/api/v2${path}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n throw this.wrapFetchError(err);\n }\n\n return this.handleResponse<T>(res);\n }\n\n private wrapFetchError(err: unknown): Error {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n return new Error(\"Request timed out. Check your network connection and try again.\");\n }\n if (\n err instanceof TypeError &&\n (err as NodeJS.ErrnoException).code === \"ECONNREFUSED\"\n ) {\n return new Error(`Cannot connect to ${this.baseUrl}. Is the server running?`);\n }\n return new Error(\"Network error. Check your internet connection and try again.\");\n }\n\n private async handleResponse<T>(res: Response): Promise<T> {\n if (!res.ok) {\n let errorMessageFromResponse: string | null = null;\n try {\n const errorBody = (await res.json()) as { message?: string };\n errorMessageFromResponse = errorBody.message ?? null;\n } catch {\n // Response body may not be JSON; ignore parse failures\n }\n\n if (res.status === 401) {\n throw new Error(errorMessageFromResponse ?? \"Authentication failed.\");\n }\n if (res.status === 403) {\n throw new Error(\n errorMessageFromResponse ??\n \"You don't have permission to access this resource.\",\n );\n }\n if (res.status === 404) {\n throw new Error(errorMessageFromResponse ?? \"Resource not found.\");\n }\n if (res.status === 422) {\n throw new Error(errorMessageFromResponse ?? \"Request validation failed.\");\n }\n if (res.status >= 500) {\n throw new Error(\n \"ChainPatrol API is temporarily unavailable. Please try again later.\",\n );\n }\n throw new Error(errorMessageFromResponse ?? `Request failed (${res.status}).`);\n }\n\n return (await res.json()) as T;\n }\n\n assetCheck(input: AssetCheckInput) {\n return this.request<AssetCheckResult>(\"/asset/check\", input);\n }\n\n assetSearch(input: AssetSearchInput) {\n return this.request<AssetSearchResult>(\"/asset/search\", input);\n }\n\n listDetectionConfigs(slug: string) {\n return this.request<DetectionSource[]>(\"/detection/configs/list\", { slug });\n }\n\n updateDetectionConfig(input: DetectionConfigUpdateInput) {\n return this.request<DetectionConfigUpdateResult>(\"/detection/configs/update\", input);\n }\n\n runDetectionConfigs(input: DetectionConfigRunInput) {\n return this.request<DetectionConfigRunResult>(\"/detection/configs/run\", input);\n }\n\n validateDetectionConfigs(input: DetectionConfigValidateInput) {\n return this.request<DetectionConfigValidateResult>(\n \"/detection/configs/validate\",\n input,\n );\n }\n\n getDetectionDrift(input: DetectionDriftInput) {\n return this.request<DetectionDriftResult>(\"/detection/drift\", {\n ...input,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n });\n }\n\n getOperationsQueuesSnapshot(input: OperationsQueuesSnapshotInput) {\n return this.request<OperationsQueuesSnapshotResult>(\n \"/operations/queues/snapshot\",\n input,\n );\n }\n\n getMetricsSummary(input: MetricsSummaryInput) {\n return this.request<MetricsSummaryResult>(\"/metrics/summary\", {\n ...input,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n });\n }\n\n getMetricsFound(input: MetricsFoundInput) {\n return this.request<MetricsFoundResult>(\"/metrics/found\", {\n ...input,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n });\n }\n\n getMetricsBreakdown(input: MetricsBreakdownInput) {\n return this.request<MetricsBreakdownResult>(\"/metrics/breakdown\", {\n ...input,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n });\n }\n\n createReport(input: ReportCreateInput) {\n return this.request<ReportCreateResult>(\"/report/create\", input);\n }\n\n listOrganizationReports(input: OrganizationReportsListInput) {\n return this.requestGet<OrganizationReportsListResult>(\"/organization/reports\", {\n slug: input.slug,\n limit: String(input.limit ?? 10),\n cursor: optionalNumberParam(input.cursor),\n status: input.status,\n searchQuery: input.searchQuery,\n reporterQuery: input.reporterQuery,\n reportedByCustomer: optionalBooleanParam(input.reportedByCustomer),\n excludeAutomation: optionalBooleanParam(input.excludeAutomation),\n reporterKind: input.reporterKind,\n reviewerKind: input.reviewerKind,\n onlyRejected: optionalBooleanParam(input.onlyRejected),\n reviewStatuses: input.reviewStatuses?.length ? input.reviewStatuses : undefined,\n assetTypes: input.assetTypes?.length ? input.assetTypes : undefined,\n brandIds: input.brandIds?.length ? input.brandIds.map(String) : undefined,\n countryCodes: input.countryCodes?.length ? input.countryCodes : undefined,\n reviewedByUserId: optionalNumberParam(input.reviewedByUserId),\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n updatedAtStartDate: parseIsoDateString(input.updatedAtStartDate),\n updatedAtEndDate: parseIsoDateString(input.updatedAtEndDate),\n needsCustomerReview: optionalBooleanParam(input.needsCustomerReview),\n });\n }\n\n listTakedowns(input: TakedownsListInput) {\n return this.request<TakedownsListResult>(\"/takedowns/list\", {\n organizationSlug: input.organizationSlug,\n query: input.query,\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n assetType: input.assetType,\n takedownStatus: input.takedownStatus,\n livenessStatus: input.livenessStatus,\n brandIds: input.brandIds?.length ? input.brandIds : undefined,\n assigneeIds: input.assigneeIds?.length ? input.assigneeIds : undefined,\n startedAtStartDate: parseIsoDateString(input.startedAtStartDate),\n startedAtEndDate: parseIsoDateString(input.startedAtEndDate),\n hideAutomatedTakedowns: input.hideAutomatedTakedowns,\n hideAutomatedLivenessChecks: input.hideAutomatedLivenessChecks,\n sorting: input.sorting,\n per_page: input.perPage,\n next_page: input.nextPage,\n });\n }\n\n getOrganizationMetrics(input: OrganizationMetricsInput) {\n return this.requestGet<OrganizationMetricsResult>(\"/organization/metrics\", {\n organizationSlug: input.organizationSlug,\n slugs: input.slugs,\n allMyOrgs: input.allMyOrgs ? \"true\" : undefined,\n subscriptionStatus: input.subscriptionStatus,\n services: input.services ? JSON.stringify(input.services) : undefined,\n brandSlug: input.brandSlug,\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n include: input.include,\n });\n }\n\n listHealthchecks() {\n return this.request<HealthchecksListResult>(\"/healthchecks/list\", {});\n }\n\n runHealthcheck(endpoint: string, input: Record<string, unknown>) {\n return this.request<HealthcheckResult>(endpoint, input);\n }\n\n getUserOrgs(input: UserOrgsInput) {\n return this.request<UserOrgsResult>(\"/user/orgs\", input);\n }\n\n getUserOrg(input: UserOrgGetInput) {\n return this.requestGet<UserOrgGetResult>(\n `/user/orgs/${encodeURIComponent(input.slug)}`,\n {},\n );\n }\n\n listAssets(input: AssetListInput) {\n return this.request<AssetListResult>(\"/asset/list\", {\n type: input.type,\n status: input.status,\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n per_page: input.perPage,\n next_page: input.nextPage,\n });\n }\n\n listThreats(input: ThreatsListInput) {\n return this.request<ThreatsListResult>(\"/threats/list\", {\n query: input.query,\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n assetType: input.assetType,\n sorting: input.sorting,\n per_page: input.perPage,\n next_page: input.nextPage,\n });\n }\n\n listDetections(input: DetectionListInput) {\n const filters: Array<{\n property: string;\n operator: \"in\" | \"notIn\";\n value: unknown[];\n }> = [];\n if (input.sources?.length) {\n filters.push({ property: \"source\", operator: \"in\", value: input.sources });\n }\n if (input.confidence?.length) {\n filters.push({ property: \"confidence\", operator: \"in\", value: input.confidence });\n }\n if (input.assetStatus?.length) {\n filters.push({\n property: \"assetStatus\",\n operator: \"in\",\n value: input.assetStatus,\n });\n }\n if (input.assetType?.length) {\n filters.push({ property: \"assetType\", operator: \"in\", value: input.assetType });\n }\n if (input.brandIds?.length) {\n filters.push({ property: \"brand\", operator: \"in\", value: input.brandIds });\n }\n if (input.liveness?.length) {\n filters.push({ property: \"liveness\", operator: \"in\", value: input.liveness });\n }\n if (input.watchlist?.length) {\n filters.push({ property: \"watchlist\", operator: \"in\", value: input.watchlist });\n }\n if (input.reported?.length) {\n filters.push({ property: \"reported\", operator: \"in\", value: input.reported });\n }\n if (input.countryCodes?.length) {\n filters.push({\n property: \"countryCode\",\n operator: \"in\",\n value: input.countryCodes,\n });\n }\n if (input.onlyDeleted) {\n filters.push({ property: \"deleted\", operator: \"in\", value: [\"deleted\"] });\n }\n return this.request<DetectionListResult>(\"/detection/list\", {\n slug: input.slug,\n cursor: input.cursor,\n limit: input.limit,\n query: input.query,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n filters: filters.length > 0 ? filters : undefined,\n });\n }\n\n searchReports(input: ReportsSearchInput) {\n return this.request<ReportsSearchResult>(\"/reports/search\", input);\n }\n\n listOrganizationAssets(input: OrganizationAssetsListInput) {\n return this.requestGet<OrganizationAssetsListResult>(\"/organization/assets\", {\n type: input.type,\n groupId: input.groupId !== undefined ? String(input.groupId) : undefined,\n query: input.query,\n per_page: input.perPage !== undefined ? String(input.perPage) : undefined,\n next_page: input.nextPage,\n });\n }\n\n listOrganizationAssetGroups() {\n return this.requestGet<OrganizationAssetGroupsListResult>(\n \"/organization/asset-groups\",\n {},\n );\n }\n\n listOrganizationBrands() {\n return this.requestGet<OrganizationBrandsListResult>(\"/organization/brands\", {});\n }\n\n getCurrentUser() {\n return this.request<UserMeResult>(\"/user/me\", {});\n }\n\n validateApiKey() {\n return this.requestGet<ValidateApiKeyResult>(\"/validate\", {});\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/api/types.ts","../../src/api/date-utils.ts","../../src/api/client.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export type ApiCredential =\n | { kind: \"api-key\"; value: string }\n | { kind: \"bearer\"; value: string };\n\nexport type CredentialProvider = () => ApiCredential | Promise<ApiCredential>;\n\nexport interface ChainPatrolApiClientOptions {\n baseUrl?: string;\n credential: CredentialProvider;\n timeoutMs?: number;\n}\n\nexport interface ConfigEntry {\n id: number;\n title: string;\n /**\n * Human-readable description of what the config does. `null` when unset\n * — most configs seeded before this field existed do not have one.\n */\n description: string | null;\n status: string;\n cron: string | null;\n config: Record<string, unknown>;\n /**\n * Optional brand connection. Present only for org-scoped configs when the\n * config targets a specific brand.\n */\n brandId?: number | null;\n brand?: {\n id: number;\n name: string;\n slug: string;\n } | null;\n /** When the config was first created (ISO 8601, UTC). */\n createdAt: string;\n /**\n * When the config was last updated (ISO 8601, UTC). Pair with the drift\n * healthcheck to spot silent configs untouched in months.\n */\n updatedAt: string;\n /**\n * When the most recent `ThreatDetectionResult` for this config was created\n * (ISO 8601, UTC). Null when the config has never produced a hit. A config\n * with no recent `lastResultAt` is going silent regardless of `updatedAt`.\n */\n lastResultAt: string | null;\n}\n\nexport interface DetectionSource {\n source: string;\n scope: \"global\" | \"organization\";\n configs: ConfigEntry[];\n}\n\nexport interface ApiClient {\n assetCheck: (input: AssetCheckInput) => Promise<AssetCheckResult>;\n assetSearch: (input: AssetSearchInput) => Promise<AssetSearchResult>;\n listAssets: (input: AssetListInput) => Promise<AssetListResult>;\n listDetectionConfigs: (slug: string) => Promise<DetectionSource[]>;\n updateDetectionConfig: (\n input: DetectionConfigUpdateInput,\n ) => Promise<DetectionConfigUpdateResult>;\n runDetectionConfigs: (\n input: DetectionConfigRunInput,\n ) => Promise<DetectionConfigRunResult>;\n validateDetectionConfigs: (\n input: DetectionConfigValidateInput,\n ) => Promise<DetectionConfigValidateResult>;\n getDetectionDrift: (input: DetectionDriftInput) => Promise<DetectionDriftResult>;\n listDetections: (input: DetectionListInput) => Promise<DetectionListResult>;\n getOperationsQueuesSnapshot: (\n input: OperationsQueuesSnapshotInput,\n ) => Promise<OperationsQueuesSnapshotResult>;\n getMetricsSummary: (input: MetricsSummaryInput) => Promise<MetricsSummaryResult>;\n getMetricsFound: (input: MetricsFoundInput) => Promise<MetricsFoundResult>;\n getMetricsBreakdown: (input: MetricsBreakdownInput) => Promise<MetricsBreakdownResult>;\n createReport: (input: ReportCreateInput) => Promise<ReportCreateResult>;\n listOrganizationReports: (\n input: OrganizationReportsListInput,\n ) => Promise<OrganizationReportsListResult>;\n reviewOrganizationProposal: (\n input: OrganizationProposalsReviewInput,\n ) => Promise<OrganizationProposalsReviewResult>;\n searchReports: (input: ReportsSearchInput) => Promise<ReportsSearchResult>;\n listTakedowns: (input: TakedownsListInput) => Promise<TakedownsListResult>;\n listThreats: (input: ThreatsListInput) => Promise<ThreatsListResult>;\n getOrganizationMetrics: (\n input: OrganizationMetricsInput,\n ) => Promise<OrganizationMetricsResult>;\n listOrganizationAssets: (\n input: OrganizationAssetsListInput,\n ) => Promise<OrganizationAssetsListResult>;\n listOrganizationAssetGroups: () => Promise<OrganizationAssetGroupsListResult>;\n listOrganizationBrands: () => Promise<OrganizationBrandsListResult>;\n listHealthchecks: () => Promise<HealthchecksListResult>;\n runHealthcheck: (\n endpoint: string,\n input: Record<string, unknown>,\n ) => Promise<HealthcheckResult>;\n getUserOrgs: (input: UserOrgsInput) => Promise<UserOrgsResult>;\n getUserOrg: (input: UserOrgGetInput) => Promise<UserOrgGetResult>;\n getCurrentUser: () => Promise<UserMeResult>;\n validateApiKey: () => Promise<ValidateApiKeyResult>;\n}\n\nexport interface AssetCheckInput {\n content: string;\n}\n\nexport type AssetCheckStatus = \"ALLOWED\" | \"BLOCKED\" | \"UNKNOWN\";\n\nexport interface AssetCheckSourceEntry {\n source: string;\n status: AssetCheckStatus;\n}\n\nexport interface AssetCheckResult {\n status: AssetCheckStatus;\n source: string;\n reason?: string;\n sources: AssetCheckSourceEntry[];\n message?: string;\n code?: string;\n watchStatus?: \"ENABLED\" | \"DISABLED\";\n}\n\nexport interface AssetSearchInput {\n content?: string;\n assetId?: number;\n assetIds?: number[];\n}\n\nexport interface AssetSearchResultItem {\n asset: {\n id: number;\n content: string;\n type: string;\n status: string;\n watchStatus: string;\n /**\n * Whether the asset is currently reachable (`\"ALIVE\"`), gone\n * (`\"DEAD\"`), or unchecked (`\"UNKNOWN\"`). Null when never evaluated.\n */\n livenessStatus: LivenessStatus | null;\n /**\n * When the asset transitioned to BLOCKED (ISO 8601, UTC). Null for\n * non-blocked assets or blocks predating the field.\n */\n blockedAt: string | null;\n createdAt: string;\n updatedAt: string;\n } | null;\n reports: Array<{\n id: number;\n title: string | null;\n status: string;\n createdAt: string;\n }>;\n takedown: {\n id: number;\n status: string;\n createdAt: string;\n updatedAt: string;\n tasks: Array<{\n id: number;\n type: string;\n status: string;\n retractionStatus: string;\n externalId: string | null;\n submittedAt: string | null;\n retractedAt: string | null;\n lastResponseAt: string | null;\n createdAt: string;\n updatedAt: string;\n takedownProvider: { name: string } | null;\n }>;\n } | null;\n blockedBy: Array<{\n consumer: string;\n name: string | null;\n consumedAt: string;\n }>;\n}\n\nexport interface AssetSearchResult extends AssetSearchResultItem {\n results?: AssetSearchResultItem[];\n}\n\nexport interface AssetListInput {\n type: string;\n status?: string;\n startDate?: string;\n endDate?: string;\n perPage?: number;\n nextPage?: string;\n}\n\nexport interface AssetListItem {\n /** Asset ID — reference in follow-up calls (was previously stripped from the response). */\n id: number;\n content: string;\n type: string;\n status: string;\n watchStatus: string;\n /**\n * Whether the asset is currently reachable (`\"ALIVE\"`), gone\n * (`\"DEAD\"`), or unchecked (`\"UNKNOWN\"`). Null when never evaluated.\n */\n livenessStatus: LivenessStatus | null;\n /**\n * When the asset transitioned to BLOCKED (ISO 8601, UTC). Null for\n * non-blocked assets.\n */\n blockedAt: string | null;\n updatedAt: string;\n}\n\nexport interface AssetListResult {\n assets: AssetListItem[];\n next_page: string | null;\n}\n\nexport interface DetectionConfigUpdateInput {\n slug: string;\n configId: number;\n status?: \"ENABLED\" | \"DISABLED\";\n title?: string;\n description?: string | null;\n cron?: string | null;\n config?: Record<string, unknown>;\n mergeConfig?: boolean;\n}\n\nexport interface DetectionConfigUpdateResult {\n config: {\n id: number;\n source: string;\n status: string;\n title: string;\n description: string | null;\n cron: string | null;\n config: Record<string, unknown>;\n updatedAt: string;\n };\n}\n\nexport interface DetectionConfigRunInput {\n slug: string;\n configId?: number;\n source?: string;\n includeDisabled?: boolean;\n}\n\nexport interface DetectionConfigRunResult {\n ranCount: number;\n successCount: number;\n failedCount: number;\n results: Array<{\n configId: number;\n source: string;\n ok: boolean;\n message: string | null;\n assetsCount: number;\n }>;\n}\n\nexport interface DetectionConfigValidateInput {\n slug: string;\n source?: string;\n minResults?: number;\n lookbackHours?: number;\n runBeforeValidate?: boolean;\n includeDisabled?: boolean;\n}\n\nexport interface DetectionConfigValidateResult {\n ok: boolean;\n summary: {\n checkedConfigs: number;\n passingConfigs: number;\n failingConfigs: number;\n lookbackHours: number;\n minResults: number;\n };\n validations: Array<{\n configId: number;\n source: string;\n status: string;\n ran: boolean;\n runOk: boolean;\n runMessage: string | null;\n recentResultCount: number;\n valid: boolean;\n }>;\n}\n\nexport interface DetectionDriftInput {\n slug: string;\n lookbackHours?: number;\n startDate?: string;\n endDate?: string;\n source?: string;\n configIds?: number[];\n includeDisabled?: boolean;\n thresholds?: {\n zeroResultsMaxHours?: number;\n noisyResultsPerDay?: number;\n noisyAllowedRatioThreshold?: number;\n staleConfigDays?: number;\n };\n}\n\nexport interface DetectionDriftResult {\n ok: boolean;\n range: {\n startDate: string;\n endDate: string;\n lookbackHours: number;\n };\n thresholds: {\n zeroResultsMaxHours: number;\n noisyResultsPerDay: number;\n noisyAllowedRatioThreshold: number;\n staleConfigDays: number;\n };\n summary: {\n checkedConfigs: number;\n signalCount: number;\n zeroResultsCount: number;\n noisyCount: number;\n staleCount: number;\n };\n signals: Array<{\n signal: \"zero_results_too_long\" | \"noisy_source\" | \"stale_query\";\n configId: number;\n source: string;\n title: string | null;\n status: string;\n severity: \"low\" | \"medium\" | \"high\";\n details: Record<string, unknown>;\n }>;\n}\n\nexport interface OperationsQueuesSnapshotInput {\n slug?: string;\n all?: boolean;\n windowHours?: number;\n}\n\nexport interface OperationsQueuesSnapshotResult {\n generatedAt: string;\n scope: {\n slug: string | null;\n all: boolean;\n };\n reviewQueue: {\n totalPendingProposals: number;\n distinctReports: number;\n ageBuckets: {\n lt24h: number;\n h24to72: number;\n h72to168: number;\n gte168h: number;\n };\n slaBuckets: {\n breached: number;\n dueWithin24h: number;\n dueWithin72h: number;\n beyond72h: number;\n missingSla: number;\n };\n byOrg: Array<{ slug: string; pendingProposals: number }>;\n };\n takedownQueue: {\n totalOpen: number;\n statusCounts: {\n todo: number;\n inProgress: number;\n pendingInput: number;\n };\n ageBuckets: {\n lt24h: number;\n h24to72: number;\n h72to168: number;\n gte168h: number;\n };\n staleInProgress: number;\n byOrg: Array<{ slug: string; openTakedowns: number }>;\n };\n}\n\nexport interface MetricsSummaryInput {\n slug: string;\n startDate?: string;\n endDate?: string;\n brandIds?: number[];\n}\n\nexport interface MetricsSummaryResult {\n metrics: {\n reports: number;\n newThreats: number;\n threatsWatchlisted: number;\n takedownsFiled: number;\n takedownsCompleted: number;\n domainThreats: number;\n twitterThreats: number;\n telegramThreats: number;\n otherThreats: number;\n };\n blockedByDay: Array<{ date: string; count: number }>;\n blockedByType: Array<{ type: string; count: number }>;\n}\n\nexport interface MetricsFoundInput {\n slug: string;\n startDate: string;\n endDate: string;\n brandIds?: number[];\n}\n\nexport interface MetricsFoundResult {\n metric: \"new_threats\";\n found: number;\n range: {\n startDate: string;\n endDate: string;\n };\n}\n\nexport interface MetricsBreakdownInput {\n slug: string;\n by: \"day\" | \"type\" | \"brand\";\n startDate?: string;\n endDate?: string;\n brandIds?: number[];\n}\n\nexport interface MetricsBreakdownResult {\n by: \"day\" | \"type\" | \"brand\";\n points: Array<{\n key: string;\n count: number;\n date?: string;\n type?: string;\n brandId?: number;\n brandSlug?: string;\n brandName?: string;\n }>;\n}\n\nexport interface ReportAssetInput {\n content: string;\n status?: \"BLOCKED\" | \"ALLOWED\" | \"UNKNOWN\";\n brandSlug?: string;\n}\n\nexport interface ReportCreateInput {\n organizationSlug?: string;\n title?: string;\n description?: string;\n contactInfo?: string;\n attachmentUrls?: string[];\n externalSubmissionLink?: string;\n userAgent?: string;\n referrer?: string;\n assets: ReportAssetInput[];\n rawAssetsInput?: string;\n externalReporter?: {\n avatarUrl?: string;\n platformIdentifier: string;\n platform: string;\n displayName: string;\n };\n}\n\nexport interface ReportCreateResult {\n id: number;\n createdAt: string;\n organization: {\n id: number;\n slug: string;\n name: string;\n } | null;\n}\n\nexport const REPORT_REVIEW_DECISIONS = [\"APPROVE\", \"REJECT\", \"SKIP\", \"ESCALATE\"] as const;\nexport type ReportReviewDecision = (typeof REPORT_REVIEW_DECISIONS)[number];\n\nexport const REPORT_STATUSES = [\"TODO\", \"IN_PROGRESS\", \"CLOSED\"] as const;\nexport type ReportStatus = (typeof REPORT_STATUSES)[number];\n\nexport const ACTOR_KINDS = [\"human\", \"automation\"] as const;\nexport type ActorKind = (typeof ACTOR_KINDS)[number];\n\nexport interface OrganizationReportsListInput {\n slug: string;\n limit?: number;\n cursor?: number;\n status?: string;\n searchQuery?: string;\n reporterQuery?: string;\n reportedByCustomer?: boolean;\n /** @deprecated Prefer `reporterKind: \"human\"`. */\n excludeAutomation?: boolean;\n /** Filter by whether the report was submitted by a human or automation. */\n reporterKind?: ActorKind;\n /** Filter by whether the report was approved by a human or automation. */\n reviewerKind?: ActorKind;\n onlyRejected?: boolean;\n reviewStatuses?: ReportReviewDecision[];\n assetTypes?: string[];\n brandIds?: number[];\n countryCodes?: string[];\n reviewedByUserId?: number;\n startDate?: string;\n endDate?: string;\n updatedAtStartDate?: string;\n updatedAtEndDate?: string;\n /**\n * Filter to reports waiting on the organization's own approval — the reports\n * a customer admin still has to sign off on before the assets in them can be\n * blocked. `true` returns only those reports; `false` returns only reports\n * that are not waiting on them.\n *\n * This is the same queue the organization's Review page shows. A report counts\n * when it has at least one pending proposal that is the organization's to\n * action: one ChainPatrol staff escalated to them and they have not answered\n * yet, or one on a report the organization submitted itself.\n *\n * \"Obligatory Organization Admin Approval\" does not widen the filter. That\n * setting says an asset type will eventually need admin sign-off, not that\n * every pending proposal is waiting on the admin right now — an untriaged\n * proposal is still ChainPatrol's to review, and it reaches the organization\n * only once staff escalate it.\n */\n needsCustomerReview?: boolean;\n}\n\nexport interface OrganizationReportAssetScanEnrichment {\n id: number;\n type: string;\n output: unknown;\n status: string;\n}\n\nexport interface OrganizationReportAssetScan {\n id: number;\n status: string;\n output: unknown;\n createdAt: string;\n enrichments: OrganizationReportAssetScanEnrichment[];\n}\n\nexport interface OrganizationReportAttachment {\n id: number;\n url: string;\n}\n\nexport interface OrganizationReportsListResult {\n reports: Array<{\n id: number;\n title: string;\n description: string;\n /** Whether the report's images render inline or are hidden by default. */\n imageDisplay: string;\n /** When the report was starred/favorited (ISO 8601, UTC). Null when not favorited. */\n favoritedAt: string | null;\n status: string | null;\n reportedByCustomer: boolean;\n /**\n * SLA deadline for this report (ISO 8601, UTC). Null when no SLA\n * applies (e.g. staff-created reports).\n */\n slaDueAt: string | null;\n /**\n * URL to the original external source of the report when submitted\n * from a third-party surface (Discord/Twitter link, forwarded webform).\n * Null for reports created directly in ChainPatrol.\n */\n externalSubmissionLink: string | null;\n /**\n * ID of the canonical report this one duplicates. Null when the\n * report is not a duplicate.\n */\n duplicateOfId: number | null;\n createdAt: string;\n updatedAt: string;\n attachments: OrganizationReportAttachment[];\n proposals: Array<{\n /**\n * Pass to `reviewOrganizationProposal` to approve, reject, or watchlist\n * this proposal.\n */\n id: number;\n reviewStatus: string;\n asset: {\n id: number;\n type: string;\n content: string;\n status: string;\n /**\n * Per-scan enrichment data. Large (Apple App Store enrichments run\n * 50–200 KB each) — the agent42 tool strips these by default when\n * relaying results. Present in the raw handler response.\n */\n scans: OrganizationReportAssetScan[];\n };\n }>;\n reporter: {\n id: number;\n role: string;\n fullName: string;\n avatarUrl: string | null;\n } | null;\n externalReporter: {\n id: number;\n displayName: string | null;\n avatarUrl: string | null;\n platform: string;\n } | null;\n }>;\n nextCursor: number | null;\n totalCount: number;\n}\n\n/**\n * Reject reasons the Review page offers. These feed ChainPatrol's\n * detection-tuning breakdown, so pick the closest one rather than relying on\n * `note`.\n */\nexport const PROPOSAL_REJECT_REASONS = [\n \"irrelevant\",\n \"no_malicious_activity\",\n \"insufficient_evidence\",\n \"not_targeting_org\",\n \"decayed\",\n] as const;\nexport type ProposalRejectReason = (typeof PROPOSAL_REJECT_REASONS)[number];\n\n/**\n * Reasons for parking an asset on the watchlist. `OTHER` requires a `note`,\n * which is then treated as the reason.\n */\nexport const PROPOSAL_WATCHLIST_REASONS = [\n \"DEAD\",\n \"PARKING\",\n \"NOT_ENOUGH_EVIDENCE\",\n \"OTHER\",\n] as const;\nexport type ProposalWatchlistReason = (typeof PROPOSAL_WATCHLIST_REASONS)[number];\n\nexport type CustomerReviewDecision = \"APPROVE\" | \"REJECT\" | \"WATCHLIST\";\n\nexport interface OrganizationProposalsReviewInput {\n /** From `proposals[].id` on `listOrganizationReports`. */\n proposalId: number;\n /**\n * From `proposals[].asset.id` on the same proposal. Required, and must match\n * the proposal's current asset — a mismatch returns 409. Proves the request was\n * built from a proposal you read rather than a guessed or stale ID.\n */\n assetId: number;\n /**\n * Optional for organization-scoped API keys. Required when your credentials\n * can reach more than one organization.\n */\n slug?: string;\n /**\n * `WATCHLIST` rejects the proposal and parks the asset so it is re-evaluated\n * if it comes back alive.\n */\n decision: CustomerReviewDecision;\n /** Required when `decision` is `APPROVE`. */\n label?: string;\n /**\n * Optional for most labels, but required for `Brand Impersonation` and\n * `Employee Impersonation`, which name a specific impersonation target.\n */\n brandId?: number;\n /** Required when `decision` is `REJECT`. */\n rejectReason?: ProposalRejectReason;\n /** Required when `decision` is `WATCHLIST`. */\n watchlistReason?: ProposalWatchlistReason;\n /** Free-text detail. Required when `watchlistReason` is `OTHER`. */\n note?: string;\n}\n\nexport interface OrganizationProposalsReviewResult {\n proposal: {\n id: number;\n reviewStatus: string;\n asset: {\n id: number;\n type: string;\n content: string;\n status: string;\n };\n };\n review: {\n id: number;\n /** A `WATCHLIST` request is recorded as `REJECT` with the asset parked. */\n decision: string;\n label: string;\n brandId: number | null;\n comment: string;\n createdAt: string;\n };\n watchlisted: boolean;\n}\n\nexport const DETECTION_CONFIDENCE_LEVELS = [\"none\", \"low\", \"medium\", \"high\"] as const;\nexport type DetectionConfidence = (typeof DETECTION_CONFIDENCE_LEVELS)[number];\nexport type DetectionReportStatus = \"REPORTED\" | \"NOT_REPORTED\";\n\nexport const DETECTION_REPORTED_FILTERS = [\"reported\", \"not_reported\"] as const;\nexport type DetectionReportedFilter = (typeof DETECTION_REPORTED_FILTERS)[number];\n\nexport const LIVENESS_FILTER_VALUES = [\"ALIVE\", \"DEAD\", \"UNKNOWN\"] as const;\nexport type LivenessFilterValue = (typeof LIVENESS_FILTER_VALUES)[number];\n\nexport const WATCHLIST_FILTER_VALUES = [\"ENABLED\", \"DISABLED\"] as const;\nexport type WatchlistFilterValue = (typeof WATCHLIST_FILTER_VALUES)[number];\n\nexport interface DetectionListInput {\n slug: string;\n cursor?: number;\n limit?: number;\n query?: string;\n startDate?: string;\n endDate?: string;\n sources?: string[];\n confidence?: DetectionConfidence[];\n assetStatus?: string[];\n assetType?: string[];\n brandIds?: number[];\n liveness?: LivenessFilterValue[];\n watchlist?: WatchlistFilterValue[];\n reported?: DetectionReportedFilter[];\n countryCodes?: string[];\n onlyDeleted?: boolean;\n}\n\nexport interface DetectionBrand {\n id: number;\n name: string;\n slug: string;\n}\n\nexport interface DetectionListItem {\n id: number;\n threatContent: string;\n source: string;\n createdAt: string;\n confidence: DetectionConfidence;\n /**\n * Raw model score (0–1). `confidence` buckets this into low/medium/high\n * using the org's thresholds; use `score` when the buckets are too coarse.\n */\n score: number;\n /**\n * Free-text explanation of why the detection fired (e.g. \"matches\n * brand-name typo squat\", \"TLS cert issued by known lookalike CA\").\n */\n reason: string;\n /**\n * ID of the `ThreatDetectionConfig` that produced this hit. Pair with\n * `listDetectionConfigs` to drill back into the config.\n */\n configId: number;\n /**\n * When the detection was reported (ISO 8601, UTC). Null when the\n * detection has not been reported yet.\n */\n reportedAt: string | null;\n /**\n * Brands the detection was associated with. Empty when the detection\n * was not linked to any brand at classification time.\n */\n brands: DetectionBrand[];\n reportStatus: DetectionReportStatus;\n asset: {\n id: number;\n content: string;\n type: string;\n status: string;\n };\n}\n\nexport interface DetectionListResult {\n detections: DetectionListItem[];\n nextCursor?: number;\n}\n\nexport interface ThreatsListInput {\n query?: string;\n startDate?: string;\n endDate?: string;\n assetType?: string[];\n sorting?: Array<{ key: string; direction: \"asc\" | \"desc\" }>;\n perPage?: number;\n nextPage?: string;\n}\n\nexport interface ThreatItem {\n id: number;\n content: string;\n type: string;\n /**\n * Liveness of the blocked threat. `\"ALIVE\"` still reachable, `\"DEAD\"`\n * gone, `\"UNKNOWN\"` unchecked. Null when never evaluated.\n */\n livenessStatus: LivenessStatus | null;\n blockedAt: string;\n}\n\nexport interface ThreatsListResult {\n threats: ThreatItem[];\n next_page: string | null;\n}\n\nexport interface OrganizationAssetsListInput {\n type?: string;\n groupId?: number;\n query?: string;\n perPage?: number;\n nextPage?: string;\n}\n\nexport interface OrganizationAssetItem {\n id: number;\n content: string;\n type: string;\n status: string;\n name: string | null;\n description: string | null;\n group: { id: number; name: string } | null;\n /**\n * Whether the asset is currently reachable (`\"ALIVE\"`), gone\n * (`\"DEAD\"`), or unchecked (`\"UNKNOWN\"`). Null when never evaluated.\n */\n livenessStatus: LivenessStatus | null;\n /**\n * When the asset transitioned to BLOCKED (ISO 8601, UTC). Null for\n * non-blocked assets.\n */\n blockedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface OrganizationAssetsListResult {\n assets: OrganizationAssetItem[];\n next_page: string | null;\n}\n\nexport interface AssetGroupItem {\n id: number;\n name: string;\n assetCount: number;\n}\n\nexport interface OrganizationAssetGroupsListResult {\n groups: AssetGroupItem[];\n}\n\nexport type BrandType = \"ORGANIZATION\" | \"INDIVIDUAL\" | \"PRODUCT\";\n\nexport interface BrandLegalDocument {\n present: boolean;\n fileName: string | null;\n fileUrl: string | null;\n}\n\nexport interface BrandLegalDocuments {\n letterOfAuthorization: BrandLegalDocument;\n powerOfAttorney: BrandLegalDocument;\n}\n\nexport interface BrandTrademarkRegistrationItem {\n id: number;\n brandName: string;\n trademarkOffice: string;\n registrationNumber: string;\n goodsAndServicesClass: string;\n rightsOwnerName: string | null;\n registrationPageUrl: string | null;\n certificateFileName: string | null;\n certificateFileUrl: string | null;\n}\n\nexport interface BrandItem {\n id: number;\n slug: string;\n name: string;\n type: BrandType;\n description: string | null;\n avatarUrl: string | null;\n websiteUrl: string | null;\n twitterHandle: string | null;\n brandColors: string[];\n includedTerms: string[];\n excludedTerms: string[];\n tickers: string[];\n brandGroupId: number | null;\n createdAt: string;\n useOrganizationDocs: boolean;\n legalDocuments: BrandLegalDocuments;\n trademarkRegistrations: BrandTrademarkRegistrationItem[];\n}\n\nexport interface OrganizationBrandsListResult {\n brands: BrandItem[];\n}\n\nexport interface ReportsSearchInput {\n assetContents: string[];\n /**\n * Organization slug. Optional for organization-scoped API keys, which resolve\n * the organization from the key itself. Required when your credentials can\n * reach more than one organization — including the bearer token issued by\n * `chainpatrol login`.\n */\n slug?: string;\n reportedByCustomer?: boolean;\n /**\n * Maximum number of reports to return, newest first. Defaults to 50, maximum\n * 100. Compare with `totalCount` to tell whether results were truncated.\n */\n limit?: number;\n}\n\nexport interface ReportsSearchResultItem {\n id: number;\n /**\n * Report title. Null for external / anonymous reports without one.\n */\n title: string | null;\n status: string;\n reportedByCustomer: boolean;\n /** When the report was created (ISO 8601, UTC). */\n createdAt: string;\n assets: string[];\n}\n\nexport interface ReportsSearchResult {\n reports: ReportsSearchResultItem[];\n /**\n * Total number of reports matching the search, ignoring `limit`. Greater than\n * `reports.length` means the results were truncated.\n */\n totalCount: number;\n}\n\nexport interface UserMeResult {\n user: {\n id: number;\n name: string;\n avatarUrl: string | null;\n email: string;\n role: string;\n protectionConfig: {\n linkMonitoring: boolean;\n socialMediaScanning: boolean;\n historyScanning: boolean;\n } | null;\n };\n}\n\nexport interface ValidateApiKeyResult {\n status: \"success\";\n message: string;\n}\n\nexport const TAKEDOWN_STATUSES = [\n \"TODO\",\n \"IN_PROGRESS\",\n \"COMPLETED\",\n \"CANCELLED\",\n \"PENDING_RETRACTION\",\n \"RETRACTION_SENT\",\n \"RETRACTED\",\n \"PENDING_INPUT\",\n] as const;\nexport type TakedownStatus = (typeof TAKEDOWN_STATUSES)[number];\n\nexport const LIVENESS_STATUSES = [\"UNKNOWN\", \"ALIVE\", \"DEAD\"] as const;\nexport type LivenessStatus = (typeof LIVENESS_STATUSES)[number];\n\nexport const TAKEDOWN_SORT_KEYS = [\n \"updatedAt\",\n \"createdAt\",\n \"takedownStatus\",\n \"takedownUpdatedAt\",\n \"assigneeId\",\n \"brandId\",\n] as const;\nexport type TakedownSortKey = (typeof TAKEDOWN_SORT_KEYS)[number];\n\nexport interface TakedownsListInput {\n organizationSlug?: string;\n query?: string;\n startDate?: string;\n endDate?: string;\n assetType?: string[];\n takedownStatus?: TakedownStatus[];\n livenessStatus?: LivenessStatus[];\n brandIds?: number[];\n assigneeIds?: number[];\n startedAtStartDate?: string;\n startedAtEndDate?: string;\n hideAutomatedTakedowns?: boolean;\n hideAutomatedLivenessChecks?: boolean;\n sorting?: Array<{ key: TakedownSortKey; direction: \"asc\" | \"desc\" }>;\n perPage?: number;\n nextPage?: string;\n}\n\nexport interface TakedownItem {\n id: number;\n status: TakedownStatus;\n /**\n * Provider's own reference for this takedown (e.g. CleanDNS report ID,\n * registrar ticket). Reconcile with the vendor's dashboard. `null` when\n * no vendor has picked it up yet.\n */\n externalId: string | null;\n /**\n * Manually set by staff to exclude the takedown from median-time metrics\n * when its filing was delayed for reasons unrelated to platform\n * performance.\n */\n hasFilingDelay: boolean;\n /**\n * Manually set by staff to exclude the takedown from median-time metrics\n * when the liveness-check step was delayed for reasons unrelated to\n * platform performance.\n */\n hasLivenessCheckDelay: boolean;\n createdAt: string;\n updatedAt: string;\n asset: {\n id: number;\n content: string;\n type: string;\n livenessStatus: LivenessStatus | null;\n /**\n * When the asset transitioned to BLOCKED (ISO 8601, UTC). Null if the\n * asset was never blocked (rare for takedown rows).\n */\n blockedAt: string | null;\n };\n assignee: {\n id: number;\n fullName: string | null;\n } | null;\n brand: {\n id: number;\n name: string;\n slug: string | null;\n } | null;\n /**\n * Domain registrar assigned to this takedown (e.g. Namecheap, GoDaddy).\n * Null when unresolved. Distinct from per-task `takedownProvider` — this\n * is the takedown-level assignment for the domain itself.\n */\n domainRegistrar: TakedownProviderRef | null;\n /**\n * Hosting provider assigned to this takedown (e.g. Cloudflare, AWS).\n * Answers \"who hosts this?\" without a follow-up call. Null when unresolved.\n */\n hostingProvider: TakedownProviderRef | null;\n /**\n * Top-level-domain registrar assigned to this takedown (e.g. Verisign).\n * Null when unresolved.\n */\n tldRegistrar: TakedownProviderRef | null;\n}\n\nexport interface TakedownProviderRef {\n id: number;\n name: string;\n}\n\nexport interface TakedownsListResult {\n takedowns: TakedownItem[];\n next_page: string | null;\n}\n\nexport const ORGANIZATION_METRICS_INCLUDE_FIELDS = [\n \"reports\",\n \"newThreats\",\n \"threatsWatchlisted\",\n \"takedownsFiled\",\n \"takedownsCompleted\",\n \"domainThreats\",\n \"twitterThreats\",\n \"telegramThreats\",\n \"otherThreats\",\n \"blockedByType\",\n \"blockedByDay\",\n] as const;\n\nexport type OrganizationMetricsIncludeField =\n (typeof ORGANIZATION_METRICS_INCLUDE_FIELDS)[number];\n\nexport interface OrganizationMetricsServicesFilter {\n reporting?: { active?: boolean };\n reviewing?: { active?: boolean };\n protection?: { active?: boolean };\n takedowns?: { active?: boolean; automated?: boolean };\n detection?: { active?: boolean };\n darkWebMonitoring?: { active?: boolean };\n}\n\nexport interface OrganizationMetricsInput {\n organizationSlug?: string;\n slugs?: string[];\n allMyOrgs?: boolean;\n subscriptionStatus?: string[];\n services?: OrganizationMetricsServicesFilter;\n brandSlug?: string;\n startDate?: string;\n endDate?: string;\n include?: OrganizationMetricsIncludeField[];\n}\n\nexport interface OrganizationMetricsResultMetrics {\n reports: number | null;\n newThreats: number | null;\n threatsWatchlisted: number | null;\n takedownsFiled: number | null;\n takedownsCompleted: number | null;\n domainThreats: number | null;\n twitterThreats: number | null;\n telegramThreats: number | null;\n otherThreats: number | null;\n}\n\nexport interface OrganizationMetricsResult {\n metrics: OrganizationMetricsResultMetrics;\n blockedByType: Array<{ type: string; count: number }> | null;\n blockedByDay: Array<{ date: string; count: number }> | null;\n averages: {\n perDay: OrganizationMetricsResultMetrics | null;\n perOrgPerDay: OrganizationMetricsResultMetrics | null;\n windowDays: number | null;\n };\n perOrg: Record<\n string,\n {\n metrics: OrganizationMetricsResultMetrics;\n blockedByType: Array<{ type: string; count: number }> | null;\n blockedByDay: Array<{ date: string; count: number }> | null;\n }\n > | null;\n scope: {\n mode: \"single\" | \"multi\";\n orgs: string[];\n resolvedFrom: \"api-key\" | \"organizationSlug\" | \"slugs\" | \"allMyOrgs\";\n };\n}\n\nexport type HealthcheckCategory =\n | \"detection\"\n | \"reviewing\"\n | \"blocklisting\"\n | \"takedowns\"\n | \"assets\"\n | \"organization\";\n\nexport type HealthcheckSeverity = \"ok\" | \"warn\" | \"fail\";\n\nexport interface HealthcheckFinding {\n kind: string;\n ref: string | null;\n message: string;\n severity: \"warn\" | \"fail\";\n}\n\nexport interface HealthcheckResult {\n id: string;\n title: string;\n category: HealthcheckCategory;\n generatedAt: string;\n scope: { slug: string | null };\n ok: boolean;\n severity: HealthcheckSeverity;\n observed: Record<string, number | string | boolean | null>;\n threshold: Record<string, number | string | boolean | null>;\n findings: HealthcheckFinding[];\n suggestedAction: string | null;\n appUrl: string | null;\n}\n\nexport interface HealthcheckRegistryEntry {\n id: string;\n title: string;\n description: string;\n category: HealthcheckCategory;\n implemented: boolean;\n endpoint: string | null;\n defaultThreshold?: Record<string, number | string>;\n notImplementedReason?: string;\n}\n\nexport interface HealthchecksListResult {\n checks: HealthcheckRegistryEntry[];\n}\n\nexport type UserOrgsSubscriptionStatus = \"PROSPECT\" | \"POC\" | \"ACTIVE\" | \"INTEGRATION\";\n\nexport type PendingApprovalService = \"protection\" | \"takedowns\";\n\nexport interface PendingServiceApproval {\n service: PendingApprovalService;\n automated: boolean;\n serviceType: string;\n serviceName: string;\n requestedAt: string;\n}\n\nexport interface UserOrgsServiceFilters {\n reporting?: { active?: boolean };\n reviewing?: { active?: boolean };\n protection?: { active?: boolean };\n takedowns?: { active?: boolean; automated?: boolean };\n detection?: { active?: boolean };\n darkWebMonitoring?: { active?: boolean };\n}\n\nexport interface UserOrgsObligatoryAdminApprovalFilter {\n active?: boolean;\n assetTypes?: string[];\n}\n\nexport interface UserOrgsPendingServiceApprovalFilter {\n active?: boolean;\n services?: PendingApprovalService[];\n}\n\nexport interface UserOrgsInput {\n query?: string;\n subscriptionStatus?: UserOrgsSubscriptionStatus[];\n services?: UserOrgsServiceFilters;\n obligatoryAdminApproval?: UserOrgsObligatoryAdminApprovalFilter;\n pendingServiceApproval?: UserOrgsPendingServiceApprovalFilter;\n}\n\nexport interface UserOrgIntegrations {\n slack: boolean;\n discord: boolean;\n telegram: { connected: boolean; groupCount: number };\n vercel: boolean;\n intercom: boolean;\n moderation: boolean;\n}\n\nexport interface UserOrgLegalDocument {\n present: boolean;\n fileName: string | null;\n fileUrl: string | null;\n}\n\nexport interface UserOrgLegalDocuments {\n letterOfAuthorization: UserOrgLegalDocument;\n powerOfAttorney: UserOrgLegalDocument;\n}\n\nexport interface UserOrgTrademarkRegistration {\n id: number;\n brandName: string;\n trademarkOffice: string;\n registrationNumber: string;\n goodsAndServicesClass: string;\n rightsOwnerName: string | null;\n registrationPageUrl: string | null;\n certificateFileName: string | null;\n certificateFileUrl: string | null;\n}\n\nexport type OrganizationPortalVisibility = \"PUBLIC\" | \"PRIVATE\" | \"DISABLED\";\n\nexport type OrganizationReportVisibility = \"PUBLIC\" | \"PRIVATE\";\n\nexport type OrganizationMetricsVisibility = \"PUBLIC\" | \"PRIVATE\" | \"DISABLED\";\n\nexport interface UserOrgBrandMetadata {\n /** Public website URL of the brand (linked from the portal header). */\n websiteUrl: string | null;\n /** Public Twitter/X handle of the brand, stored with the leading `@` (e.g. `@acme`). */\n twitterHandle: string | null;\n /**\n * Email address for security correspondence — used by takedown providers\n * and researchers, distinct from the internal customer POC email.\n */\n securityContactEmail: string | null;\n /** Free-form industry label (e.g. `\"DeFi\"`, `\"CEX\"`, `\"NFT\"`, `\"Wallet\"`). */\n industry: string | null;\n}\n\nexport interface UserOrgPortalCustomization {\n /**\n * When `true`, the portal uses `name` / `slug` / `avatarUrl` from this\n * object instead of the org's own name / slug / avatar.\n */\n useCustomDetails: boolean;\n /** Custom display name shown on the portal (used only when `useCustomDetails=true`). */\n name: string | null;\n /**\n * Custom URL slug (`chainpatrol.io/<slug>`) — takes precedence over the\n * org's own slug when set, regardless of `useCustomDetails`.\n */\n slug: string | null;\n /** Custom avatar URL shown on the portal (used only when `useCustomDetails=true`). */\n avatarUrl: string | null;\n /** When `true`, the portal renders `bannerContent` as a highlighted banner. */\n bannerEnabled: boolean;\n /**\n * Markdown body of the portal banner. Null (or empty) with\n * `bannerEnabled=true` means the toggle is on but no content has been\n * written yet.\n */\n bannerContent: string | null;\n}\n\nexport interface UserOrg {\n id: number;\n name: string;\n slug: string;\n avatarUrl: string | null;\n contactUrl: string | null;\n subscriptionStatus: \"PROSPECT\" | \"POC\" | \"ACTIVE\" | \"INTEGRATION\" | \"INACTIVE\";\n /**\n * Visibility of the org's public security portal (chainpatrol.io/<slug>).\n * - `PUBLIC` — portal is fully discoverable (metrics, listings, report form).\n * - `PRIVATE` — only the report form is rendered; no metrics or listings.\n * - `DISABLED` — the portal returns a 404.\n */\n portalVisibility: OrganizationPortalVisibility;\n /**\n * Whether the report listings on the public portal are visible to\n * visitors. `PUBLIC` shows the org's reports; `PRIVATE` hides the report\n * list even when the portal is discoverable.\n */\n reportVisibility: OrganizationReportVisibility;\n /**\n * Whether the metrics / threats-blocked stats render on the public portal.\n * - `PUBLIC` — metrics tab is visible.\n * - `PRIVATE` — metrics tab is hidden from anonymous visitors.\n * - `DISABLED` — metrics are not computed for this org.\n */\n metricsVisibility: OrganizationMetricsVisibility;\n /**\n * Public brand-facing metadata (website, twitter, security contact,\n * industry) shown on the portal and used by staff for outbound.\n */\n brandMetadata: UserOrgBrandMetadata;\n /**\n * Customer-configurable presentation of the public security portal —\n * custom name / slug / avatar and the banner content.\n */\n portalCustomization: UserOrgPortalCustomization;\n services: {\n reporting: { active: boolean };\n reviewing: { active: boolean };\n protection: { active: boolean };\n takedowns: { active: boolean; automated: boolean };\n detection: { active: boolean };\n darkWebMonitoring: { active: boolean };\n };\n integrations: UserOrgIntegrations;\n obligatoryAdminApproval: {\n active: boolean;\n assetTypes: string[];\n };\n pendingServiceApprovals: PendingServiceApproval[];\n legalDocuments: UserOrgLegalDocuments;\n trademarkRegistrations: UserOrgTrademarkRegistration[];\n}\n\nexport interface UserOrgsResult {\n organizations: UserOrg[];\n}\n\nexport interface UserOrgGetInput {\n slug: string;\n}\n\nexport interface UserOrgGetResult {\n organization: UserOrg;\n}\n","const ISO_DATE_REGEX =\n /^(\\d{4})-(\\d{2})-(\\d{2})(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\n\nexport function parseIsoDate(value: string | undefined): Date | undefined {\n if (!value) return undefined;\n const m = ISO_DATE_REGEX.exec(value);\n if (!m) {\n throw new Error(`Invalid ISO date: '${value}'. Use YYYY-MM-DD or full ISO 8601.`);\n }\n // Normalize offset-less datetimes to UTC (matches Luxon's { zone: \"utc\" } behavior).\n // Date-only strings are already UTC per ECMAScript spec.\n const hasTime = m[4] !== undefined;\n const hasOffset = m[7] !== undefined;\n const normalized = hasTime && !hasOffset ? value + \"Z\" : value;\n const date = new Date(normalized);\n if (Number.isNaN(date.getTime())) {\n throw new Error(`Invalid ISO date: '${value}'. Use YYYY-MM-DD or full ISO 8601.`);\n }\n // Reject impossible calendar dates that Date rolls forward (e.g. Feb 31 → Mar 3)\n if (\n date.getUTCFullYear() !== Number(m[1]) ||\n date.getUTCMonth() + 1 !== Number(m[2]) ||\n date.getUTCDate() !== Number(m[3])\n ) {\n throw new Error(`Invalid ISO date: '${value}'. Use YYYY-MM-DD or full ISO 8601.`);\n }\n return date;\n}\n\nexport function parseIsoDateString(value: string | undefined): string | undefined {\n return parseIsoDate(value)?.toISOString();\n}\n","import { parseIsoDate, parseIsoDateString } from \"./date-utils\";\nimport type {\n ApiClient,\n ApiCredential,\n AssetCheckInput,\n AssetCheckResult,\n AssetListInput,\n AssetListResult,\n AssetSearchInput,\n AssetSearchResult,\n ChainPatrolApiClientOptions,\n CredentialProvider,\n DetectionConfigRunInput,\n DetectionConfigRunResult,\n DetectionConfigUpdateInput,\n DetectionConfigUpdateResult,\n DetectionConfigValidateInput,\n DetectionConfigValidateResult,\n DetectionDriftInput,\n DetectionDriftResult,\n DetectionListInput,\n DetectionListResult,\n DetectionSource,\n HealthcheckResult,\n HealthchecksListResult,\n MetricsBreakdownInput,\n MetricsBreakdownResult,\n MetricsFoundInput,\n MetricsFoundResult,\n MetricsSummaryInput,\n MetricsSummaryResult,\n OperationsQueuesSnapshotInput,\n OperationsQueuesSnapshotResult,\n OrganizationAssetsListInput,\n OrganizationAssetsListResult,\n OrganizationAssetGroupsListResult,\n OrganizationBrandsListResult,\n OrganizationMetricsInput,\n OrganizationMetricsResult,\n OrganizationProposalsReviewInput,\n OrganizationProposalsReviewResult,\n OrganizationReportsListInput,\n OrganizationReportsListResult,\n ReportCreateInput,\n ReportCreateResult,\n ReportsSearchInput,\n ReportsSearchResult,\n TakedownsListInput,\n TakedownsListResult,\n ThreatsListInput,\n ThreatsListResult,\n UserMeResult,\n UserOrgGetInput,\n UserOrgGetResult,\n UserOrgsInput,\n UserOrgsResult,\n ValidateApiKeyResult,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://app.chainpatrol.io\";\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nfunction trimTrailingSlashes(url: string): string {\n return url.replace(/\\/+$/, \"\");\n}\n\n/**\n * Query params are strings, and `requestGet` drops `undefined`, so booleans and\n * numbers have to be stringified without turning \"unset\" into a value.\n * `String(false)` is `\"false\"`, which the API distinguishes from an absent\n * param — passing `false` filters, passing nothing does not.\n */\nfunction optionalBooleanParam(value: boolean | undefined): string | undefined {\n return value === undefined ? undefined : String(value);\n}\n\nfunction optionalNumberParam(value: number | undefined): string | undefined {\n return value === undefined ? undefined : String(value);\n}\n\nexport function staticApiKey(key: string): CredentialProvider {\n return () => ({ kind: \"api-key\", value: key });\n}\n\nexport function staticBearerToken(token: string): CredentialProvider {\n return () => ({ kind: \"bearer\", value: token });\n}\n\nexport class ChainPatrolApiClient implements ApiClient {\n private readonly baseUrl: string;\n private readonly credential: CredentialProvider;\n private readonly timeoutMs: number;\n\n constructor(options: ChainPatrolApiClientOptions) {\n this.baseUrl = trimTrailingSlashes(options.baseUrl ?? DEFAULT_BASE_URL);\n this.credential = options.credential;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n private async buildAuthHeaders(): Promise<Record<string, string>> {\n const credential = await this.credential();\n const headers: Record<string, string> = {};\n if (credential.kind === \"api-key\") {\n headers[\"x-api-key\"] = credential.value;\n } else {\n headers[\"Authorization\"] = `Bearer ${credential.value}`;\n }\n return headers;\n }\n\n private async requestGet<T>(\n path: string,\n query: Record<string, string | string[] | undefined>,\n ): Promise<T> {\n const headers = await this.buildAuthHeaders();\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== undefined && item !== \"\") {\n search.append(key, item);\n }\n }\n continue;\n }\n if (value !== \"\") {\n search.set(key, value);\n }\n }\n const queryString = search.toString();\n const url = `${this.baseUrl}/api/v2${path}${queryString ? `?${queryString}` : \"\"}`;\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"GET\",\n headers,\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n throw this.wrapFetchError(err);\n }\n\n return this.handleResponse<T>(res);\n }\n\n private async request<T>(path: string, body: unknown): Promise<T> {\n const headers = await this.buildAuthHeaders();\n headers[\"Content-Type\"] = \"application/json\";\n\n let res: Response;\n try {\n res = await fetch(`${this.baseUrl}/api/v2${path}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n throw this.wrapFetchError(err);\n }\n\n return this.handleResponse<T>(res);\n }\n\n private wrapFetchError(err: unknown): Error {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n return new Error(\"Request timed out. Check your network connection and try again.\");\n }\n if (\n err instanceof TypeError &&\n (err as NodeJS.ErrnoException).code === \"ECONNREFUSED\"\n ) {\n return new Error(`Cannot connect to ${this.baseUrl}. Is the server running?`);\n }\n return new Error(\"Network error. Check your internet connection and try again.\");\n }\n\n private async handleResponse<T>(res: Response): Promise<T> {\n if (!res.ok) {\n let errorMessageFromResponse: string | null = null;\n try {\n const errorBody = (await res.json()) as { message?: string };\n errorMessageFromResponse = errorBody.message ?? null;\n } catch {\n // Response body may not be JSON; ignore parse failures\n }\n\n if (res.status === 401) {\n throw new Error(errorMessageFromResponse ?? \"Authentication failed.\");\n }\n if (res.status === 403) {\n throw new Error(\n errorMessageFromResponse ??\n \"You don't have permission to access this resource.\",\n );\n }\n if (res.status === 404) {\n throw new Error(errorMessageFromResponse ?? \"Resource not found.\");\n }\n if (res.status === 422) {\n throw new Error(errorMessageFromResponse ?? \"Request validation failed.\");\n }\n if (res.status >= 500) {\n throw new Error(\n \"ChainPatrol API is temporarily unavailable. Please try again later.\",\n );\n }\n throw new Error(errorMessageFromResponse ?? `Request failed (${res.status}).`);\n }\n\n return (await res.json()) as T;\n }\n\n assetCheck(input: AssetCheckInput) {\n return this.request<AssetCheckResult>(\"/asset/check\", input);\n }\n\n assetSearch(input: AssetSearchInput) {\n return this.request<AssetSearchResult>(\"/asset/search\", input);\n }\n\n listDetectionConfigs(slug: string) {\n return this.request<DetectionSource[]>(\"/detection/configs/list\", { slug });\n }\n\n updateDetectionConfig(input: DetectionConfigUpdateInput) {\n return this.request<DetectionConfigUpdateResult>(\"/detection/configs/update\", input);\n }\n\n runDetectionConfigs(input: DetectionConfigRunInput) {\n return this.request<DetectionConfigRunResult>(\"/detection/configs/run\", input);\n }\n\n validateDetectionConfigs(input: DetectionConfigValidateInput) {\n return this.request<DetectionConfigValidateResult>(\n \"/detection/configs/validate\",\n input,\n );\n }\n\n getDetectionDrift(input: DetectionDriftInput) {\n return this.request<DetectionDriftResult>(\"/detection/drift\", {\n ...input,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n });\n }\n\n getOperationsQueuesSnapshot(input: OperationsQueuesSnapshotInput) {\n return this.request<OperationsQueuesSnapshotResult>(\n \"/operations/queues/snapshot\",\n input,\n );\n }\n\n getMetricsSummary(input: MetricsSummaryInput) {\n return this.request<MetricsSummaryResult>(\"/metrics/summary\", {\n ...input,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n });\n }\n\n getMetricsFound(input: MetricsFoundInput) {\n return this.request<MetricsFoundResult>(\"/metrics/found\", {\n ...input,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n });\n }\n\n getMetricsBreakdown(input: MetricsBreakdownInput) {\n return this.request<MetricsBreakdownResult>(\"/metrics/breakdown\", {\n ...input,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n });\n }\n\n createReport(input: ReportCreateInput) {\n return this.request<ReportCreateResult>(\"/report/create\", input);\n }\n\n listOrganizationReports(input: OrganizationReportsListInput) {\n return this.requestGet<OrganizationReportsListResult>(\"/organization/reports\", {\n slug: input.slug,\n limit: String(input.limit ?? 10),\n cursor: optionalNumberParam(input.cursor),\n status: input.status,\n searchQuery: input.searchQuery,\n reporterQuery: input.reporterQuery,\n reportedByCustomer: optionalBooleanParam(input.reportedByCustomer),\n excludeAutomation: optionalBooleanParam(input.excludeAutomation),\n reporterKind: input.reporterKind,\n reviewerKind: input.reviewerKind,\n onlyRejected: optionalBooleanParam(input.onlyRejected),\n reviewStatuses: input.reviewStatuses?.length ? input.reviewStatuses : undefined,\n assetTypes: input.assetTypes?.length ? input.assetTypes : undefined,\n brandIds: input.brandIds?.length ? input.brandIds.map(String) : undefined,\n countryCodes: input.countryCodes?.length ? input.countryCodes : undefined,\n reviewedByUserId: optionalNumberParam(input.reviewedByUserId),\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n updatedAtStartDate: parseIsoDateString(input.updatedAtStartDate),\n updatedAtEndDate: parseIsoDateString(input.updatedAtEndDate),\n needsCustomerReview: optionalBooleanParam(input.needsCustomerReview),\n });\n }\n\n reviewOrganizationProposal(input: OrganizationProposalsReviewInput) {\n // `proposalId` addresses the resource in the path, so it is not repeated in\n // the body. `assetId` stays in the body — it is the echo-back the server\n // checks against the proposal's actual asset.\n const { proposalId, ...body } = input;\n return this.request<OrganizationProposalsReviewResult>(\n `/organization/proposals/${proposalId}/review`,\n body,\n );\n }\n\n listTakedowns(input: TakedownsListInput) {\n return this.request<TakedownsListResult>(\"/takedowns/list\", {\n organizationSlug: input.organizationSlug,\n query: input.query,\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n assetType: input.assetType,\n takedownStatus: input.takedownStatus,\n livenessStatus: input.livenessStatus,\n brandIds: input.brandIds?.length ? input.brandIds : undefined,\n assigneeIds: input.assigneeIds?.length ? input.assigneeIds : undefined,\n startedAtStartDate: parseIsoDateString(input.startedAtStartDate),\n startedAtEndDate: parseIsoDateString(input.startedAtEndDate),\n hideAutomatedTakedowns: input.hideAutomatedTakedowns,\n hideAutomatedLivenessChecks: input.hideAutomatedLivenessChecks,\n sorting: input.sorting,\n per_page: input.perPage,\n next_page: input.nextPage,\n });\n }\n\n getOrganizationMetrics(input: OrganizationMetricsInput) {\n return this.requestGet<OrganizationMetricsResult>(\"/organization/metrics\", {\n organizationSlug: input.organizationSlug,\n slugs: input.slugs,\n allMyOrgs: input.allMyOrgs ? \"true\" : undefined,\n subscriptionStatus: input.subscriptionStatus,\n services: input.services ? JSON.stringify(input.services) : undefined,\n brandSlug: input.brandSlug,\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n include: input.include,\n });\n }\n\n listHealthchecks() {\n return this.request<HealthchecksListResult>(\"/healthchecks/list\", {});\n }\n\n runHealthcheck(endpoint: string, input: Record<string, unknown>) {\n return this.request<HealthcheckResult>(endpoint, input);\n }\n\n getUserOrgs(input: UserOrgsInput) {\n return this.request<UserOrgsResult>(\"/user/orgs\", input);\n }\n\n getUserOrg(input: UserOrgGetInput) {\n return this.requestGet<UserOrgGetResult>(\n `/user/orgs/${encodeURIComponent(input.slug)}`,\n {},\n );\n }\n\n listAssets(input: AssetListInput) {\n return this.request<AssetListResult>(\"/asset/list\", {\n type: input.type,\n status: input.status,\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n per_page: input.perPage,\n next_page: input.nextPage,\n });\n }\n\n listThreats(input: ThreatsListInput) {\n return this.request<ThreatsListResult>(\"/threats/list\", {\n query: input.query,\n startDate: parseIsoDateString(input.startDate),\n endDate: parseIsoDateString(input.endDate),\n assetType: input.assetType,\n sorting: input.sorting,\n per_page: input.perPage,\n next_page: input.nextPage,\n });\n }\n\n listDetections(input: DetectionListInput) {\n const filters: Array<{\n property: string;\n operator: \"in\" | \"notIn\";\n value: unknown[];\n }> = [];\n if (input.sources?.length) {\n filters.push({ property: \"source\", operator: \"in\", value: input.sources });\n }\n if (input.confidence?.length) {\n filters.push({ property: \"confidence\", operator: \"in\", value: input.confidence });\n }\n if (input.assetStatus?.length) {\n filters.push({\n property: \"assetStatus\",\n operator: \"in\",\n value: input.assetStatus,\n });\n }\n if (input.assetType?.length) {\n filters.push({ property: \"assetType\", operator: \"in\", value: input.assetType });\n }\n if (input.brandIds?.length) {\n filters.push({ property: \"brand\", operator: \"in\", value: input.brandIds });\n }\n if (input.liveness?.length) {\n filters.push({ property: \"liveness\", operator: \"in\", value: input.liveness });\n }\n if (input.watchlist?.length) {\n filters.push({ property: \"watchlist\", operator: \"in\", value: input.watchlist });\n }\n if (input.reported?.length) {\n filters.push({ property: \"reported\", operator: \"in\", value: input.reported });\n }\n if (input.countryCodes?.length) {\n filters.push({\n property: \"countryCode\",\n operator: \"in\",\n value: input.countryCodes,\n });\n }\n if (input.onlyDeleted) {\n filters.push({ property: \"deleted\", operator: \"in\", value: [\"deleted\"] });\n }\n return this.request<DetectionListResult>(\"/detection/list\", {\n slug: input.slug,\n cursor: input.cursor,\n limit: input.limit,\n query: input.query,\n startDate: parseIsoDate(input.startDate),\n endDate: parseIsoDate(input.endDate),\n filters: filters.length > 0 ? filters : undefined,\n });\n }\n\n searchReports(input: ReportsSearchInput) {\n return this.request<ReportsSearchResult>(\"/reports/search\", input);\n }\n\n listOrganizationAssets(input: OrganizationAssetsListInput) {\n return this.requestGet<OrganizationAssetsListResult>(\"/organization/assets\", {\n type: input.type,\n groupId: input.groupId !== undefined ? String(input.groupId) : undefined,\n query: input.query,\n per_page: input.perPage !== undefined ? String(input.perPage) : undefined,\n next_page: input.nextPage,\n });\n }\n\n listOrganizationAssetGroups() {\n return this.requestGet<OrganizationAssetGroupsListResult>(\n \"/organization/asset-groups\",\n {},\n );\n }\n\n listOrganizationBrands() {\n return this.requestGet<OrganizationBrandsListResult>(\"/organization/brands\", {});\n }\n\n getCurrentUser() {\n return this.request<UserMeResult>(\"/user/me\", {});\n }\n\n validateApiKey() {\n return this.requestGet<ValidateApiKeyResult>(\"/validate\", {});\n }\n}\n"]}
@@ -316,18 +316,26 @@ like:
316
316
  chainpatrol --json reports list --org <slug> --needs-customer-review
317
317
  \`\`\`
318
318
 
319
- The server works out what "waiting on the customer" means for that org:
320
-
321
- - **Obligatory Organization Admin Approval on** (\`orgs get <slug>\` shows it as
322
- \`obligatoryAdminApproval\`) \u2014 every report with a pending proposal whose asset
323
- type is in the approval scope counts, plus anything staff escalated to the
324
- customer. When no asset types are configured, the scope is all asset types.
325
- - **Obligatory Organization Admin Approval off** \u2014 only reports staff escalated
326
- to the customer count.
327
-
328
- Reports the customer submitted themselves are never included: ChainPatrol staff
329
- can action those without customer sign-off. Orgs with reviewing turned off have
330
- no review queue, so the filter returns nothing for them.
319
+ This is the same queue the org sees on its **Review** page in the app, so the
320
+ count you get back should match what they see there. A report is included when
321
+ it has at least one pending proposal that is the org's to action:
322
+
323
+ - ChainPatrol staff **escalated** the proposal to the customer and the customer
324
+ has not approved or rejected it yet, **or**
325
+ - the org **submitted the report itself** (those show up in their Review queue
326
+ too).
327
+
328
+ Orgs with reviewing turned off have no review queue, so the filter returns
329
+ nothing for them.
330
+
331
+ **Obligatory Organization Admin Approval does not widen this filter.** That
332
+ setting (\`orgs get <slug>\` shows it as \`obligatoryAdminApproval\`) means an
333
+ asset type will need admin sign-off before it is blocked \u2014 it does not mean
334
+ every pending proposal is waiting on the admin today. Proposals ChainPatrol has
335
+ not triaged yet are still waiting on **our** review and reach the customer only
336
+ once staff escalate them. If a user expects the filter to cover "everything that
337
+ will eventually need approval," say so explicitly rather than quoting this count
338
+ for it.
331
339
 
332
340
  #### Use case: finding gaps in ChainPatrol detection
333
341
 
@@ -775,9 +783,10 @@ and summarize patterns by service or by subscription tier.
775
783
 
776
784
  ### \`brands list\` \u2014 List the brands (sub-brands) belonging to an org
777
785
 
778
- Returns every brand for the org the caller is authenticated as, both
779
- parent / product brands (\`type: "ORGANIZATION"\`) and individual /
780
- employee brands (\`type: "INDIVIDUAL"\`). Soft-deleted brands are excluded.
786
+ Returns every brand for the org the caller is authenticated as:
787
+ parent brands (\`type: "ORGANIZATION"\`), individual / employee brands
788
+ (\`type: "INDIVIDUAL"\`), and product brands (\`type: "PRODUCT"\`).
789
+ Soft-deleted brands are excluded.
781
790
  The endpoint is org-scoped and inferred from auth \u2014 there's no \`--org\`
782
791
  flag \u2014 so org-scoped API keys, user API keys, and user sessions all work
783
792
  without extra arguments.
@@ -785,7 +794,8 @@ without extra arguments.
785
794
  \`\`\`bash
786
795
  chainpatrol brands list # all brands
787
796
  chainpatrol brands list --type INDIVIDUAL # employee / person brands only
788
- chainpatrol brands list --type ORGANIZATION # product / parent brands only
797
+ chainpatrol brands list --type ORGANIZATION # parent / organization brands only
798
+ chainpatrol brands list --type PRODUCT # product / service brands only
789
799
  chainpatrol --json brands list # machine-readable
790
800
  \`\`\`
791
801
 
@@ -1675,5 +1685,5 @@ finding.
1675
1685
  }
1676
1686
 
1677
1687
  export { buildSkillContent };
1678
- //# sourceMappingURL=chunk-CXASSCWN.mjs.map
1679
- //# sourceMappingURL=chunk-CXASSCWN.mjs.map
1688
+ //# sourceMappingURL=chunk-ZTE6QNOQ.mjs.map
1689
+ //# sourceMappingURL=chunk-ZTE6QNOQ.mjs.map