@akasecurity/ai-tc-claude-code 0.9.0 → 0.9.2

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.
@@ -491,9 +491,13 @@ var require_ignore = __commonJS({
491
491
  }
492
492
  });
493
493
 
494
+ // ../../packages/plugin-sdk/src/config.ts
495
+ import { existsSync as existsSync3 } from "fs";
496
+ import { join as join6 } from "path";
497
+
494
498
  // ../../packages/persistence/src/database.ts
495
499
  import { randomUUID as randomUUID8 } from "crypto";
496
- import { existsSync, renameSync, rmSync } from "fs";
500
+ import { existsSync, renameSync as renameSync2, rmSync as rmSync2 } from "fs";
497
501
  import { join, sep } from "path";
498
502
  import { DatabaseSync } from "node:sqlite";
499
503
 
@@ -15182,7 +15186,12 @@ var FindingFacets = external_exports.object({
15182
15186
  severity: external_exports.array(FindingFacetItem),
15183
15187
  subtype: external_exports.array(FindingFacetItem),
15184
15188
  provider: external_exports.array(FindingFacetItem),
15185
- action: external_exports.array(FindingFacetItem)
15189
+ action: external_exports.array(FindingFacetItem),
15190
+ // Counts by the group's derived status. The SQLite store derives a status
15191
+ // for every instance, so every group lands in a bucket; a status-less
15192
+ // group (possible only for callers whose rows carry no statuses) is
15193
+ // counted under no value.
15194
+ status: external_exports.array(FindingFacetItem)
15186
15195
  }).meta({ id: "FindingFacets" });
15187
15196
  var ListGroupedFindingsQuery = external_exports.object({
15188
15197
  // NOTE: severity filters by Severity (critical/high/medium/low), not by
@@ -15191,6 +15200,10 @@ var ListGroupedFindingsQuery = external_exports.object({
15191
15200
  subtype: external_exports.array(external_exports.string()).optional(),
15192
15201
  provider: external_exports.array(FindingProvider).optional(),
15193
15202
  action: external_exports.array(FindingAction).optional(),
15203
+ // Matches a group's DERIVED status (see FindingGroup.status), not its
15204
+ // individual instances' — so a filtered group's Status column always reads
15205
+ // one of the requested values.
15206
+ status: external_exports.array(FindingStatus).optional(),
15194
15207
  q: external_exports.string().optional(),
15195
15208
  // Scope to findings whose event carries this session id (the Activity page's
15196
15209
  // session → findings drilldown). Findings without a session never match.
@@ -15371,6 +15384,33 @@ var ToolCallAttributes = external_exports.object({
15371
15384
  parent_uuid: external_exports.string().optional(),
15372
15385
  run_key: external_exports.string().optional()
15373
15386
  }).catchall(external_exports.unknown());
15387
+ var CaptureAttributes = external_exports.object({
15388
+ // The harness/tool that produced the capture (`claude-code`, `cli`, …). A
15389
+ // column on the legacy `events` table; here it rides the bag because a
15390
+ // capture-typed audit row has no equivalent column of its own.
15391
+ source_tool: external_exports.string().optional(),
15392
+ file_path: external_exports.string().optional(),
15393
+ repo: external_exports.string().optional(),
15394
+ // The host tool whose input/output was scanned (e.g. 'Bash', 'WebFetch') —
15395
+ // gives a non-file capture a display location ("via Bash") when file_path
15396
+ // is absent. The tool NAME only, never its arguments/output.
15397
+ tool_name: external_exports.string().optional(),
15398
+ // Presence-only provenance flag: set when the file is excluded by the
15399
+ // repo's .gitignore. Omitted (not false) for tracked files.
15400
+ gitignored: external_exports.boolean().optional(),
15401
+ // Set ONLY when the capture is a COMPLETE file snapshot (a worktree scan
15402
+ // reading from disk), never a partial fragment (a hook-captured edit).
15403
+ whole_file: external_exports.boolean().optional(),
15404
+ // Distributed-tracing correlation: `correlation_id` ties the capture back to
15405
+ // the request that produced it; `trace_id` is the originating span's W3C
15406
+ // trace id when telemetry is enabled.
15407
+ correlation_id: external_exports.uuid().optional(),
15408
+ trace_id: external_exports.string().regex(/^[0-9a-f]{32}$/).optional(),
15409
+ // Ids of the detection exceptions that downgraded findings in this capture
15410
+ // to 'allow' — the enforcement audit trail's link back to the grant that
15411
+ // authorized the bypass.
15412
+ exception_ids: external_exports.array(external_exports.guid()).optional()
15413
+ }).catchall(external_exports.unknown());
15374
15414
  var ToolCallInspection = external_exports.object({
15375
15415
  ruleId: external_exports.string().min(1),
15376
15416
  ruleName: external_exports.string(),
@@ -15457,7 +15497,18 @@ var InspectionFindingInput = external_exports.object({
15457
15497
  span: Span,
15458
15498
  maskedMatch: external_exports.string(),
15459
15499
  actionTaken: ActionTaken,
15460
- confidence: external_exports.number().min(0).max(1)
15500
+ confidence: external_exports.number().min(0).max(1),
15501
+ // Stable, content-addressed key correlating this finding across re-detections
15502
+ // — mirrors the legacy `findings.finding_key` (uq_inspection_findings_key is
15503
+ // its unique index). Optional: only an at-rest/re-scannable finding carries
15504
+ // one; an in-flight capture (prompt/response) has nothing to re-detect
15505
+ // against and leaves it unset, so every insert is a fresh row.
15506
+ findingKey: external_exports.string().optional(),
15507
+ // The ORIGINAL detection time, preserved across a later re-detection of the
15508
+ // same findingKey — mirrors the legacy `findings.first_detected_at`.
15509
+ // Optional: when omitted, the writer derives it from the referenced audit
15510
+ // event's startedAt on first insert (see SqliteInspectionFindingsRepository).
15511
+ firstDetectedAt: external_exports.iso.datetime().optional()
15461
15512
  });
15462
15513
  var InventoryContext = external_exports.object({
15463
15514
  host: InventoryInput.optional(),
@@ -15656,6 +15707,7 @@ var ActivityOverviewResponse = external_exports.object({
15656
15707
 
15657
15708
  // ../../packages/schema/src/zod/event.ts
15658
15709
  var EventKind = external_exports.enum(["prompt", "response", "code_change", "tool_use"]).meta({ id: "EventKind" });
15710
+ var CAPTURE_EVENT_TYPES_SQL = EventKind.options.map((k) => `'${k}'`).join(",");
15659
15711
  var SourceTool = external_exports.enum(["claude-code", "claude-desktop", "cursor", "chatgpt", "github-copilot", "cli", "unknown"]).meta({ id: "SourceTool" });
15660
15712
  var EventMetadata = external_exports.object({
15661
15713
  sessionId: external_exports.string().optional(),
@@ -15996,6 +16048,7 @@ var ExceptionBundleEntry = DetectionException.pick({
15996
16048
 
15997
16049
  // ../../packages/schema/src/zod/rule.ts
15998
16050
  var MatcherType = external_exports.enum(["keyword", "regex", "validator"]).meta({ id: "MatcherType" });
16051
+ var RuleProbeVerdict = external_exports.enum(["safe", "quarantined"]).meta({ id: "RuleProbeVerdict" });
15999
16052
  var KeywordMatcher = external_exports.object({
16000
16053
  type: external_exports.literal("keyword"),
16001
16054
  // An empty keyword matches at every position, yielding one zero-length span
@@ -16020,9 +16073,10 @@ function matchesEmptyString(pattern, flags) {
16020
16073
  return false;
16021
16074
  }
16022
16075
  }
16076
+ var MAX_PATTERN_LENGTH = 2e3;
16023
16077
  var RegexMatcher = external_exports.object({
16024
16078
  type: external_exports.literal("regex"),
16025
- pattern: external_exports.string(),
16079
+ pattern: external_exports.string().min(1).max(MAX_PATTERN_LENGTH),
16026
16080
  flags: external_exports.string().default("gi"),
16027
16081
  captureGroup: external_exports.number().int().nonnegative().optional()
16028
16082
  }).refine((v) => isValidRegex(v.pattern, v.flags), {
@@ -16143,6 +16197,12 @@ var PolicyBundle = external_exports.object({
16143
16197
  // on-disk caches — that omit the field still parse; consumers read
16144
16198
  // `bundle.exceptions ?? []`.
16145
16199
  exceptions: external_exports.array(ExceptionBundleEntry).optional(),
16200
+ // Installed pack version, keyed by ruleId, for rules in `rules` that came
16201
+ // from a versioned installed pack. Optional so older backends — and older
16202
+ // on-disk caches — that omit the field still parse; consumers fall back to
16203
+ // the rule's own spec version. NOT the bundle version above — see
16204
+ // installedRuleset's ruleVersions for the source of truth.
16205
+ ruleVersions: external_exports.record(external_exports.string(), external_exports.string()).optional(),
16146
16206
  customKeywords: external_exports.array(external_exports.string()),
16147
16207
  fetchedAt: external_exports.iso.datetime()
16148
16208
  }).meta({ id: "PolicyBundle" });
@@ -16510,6 +16570,212 @@ var ImportDetectionRequest = external_exports.object({
16510
16570
  })
16511
16571
  }).meta({ id: "ImportDetectionRequest" });
16512
16572
 
16573
+ // ../../packages/schema/src/zod/shares.ts
16574
+ var DestinationKind = external_exports.enum(["provider", "internal", "external", "ip"]).meta({ id: "DestinationKind" });
16575
+ var Transport = external_exports.enum(["https", "http", "sftp", "grpc", "smtp", "ws", "wss"]).meta({ id: "Transport" });
16576
+ var DataClass = external_exports.enum(["secrets", "pii", "customer", "source", "telemetry", "logs", "metrics", "none"]).meta({ id: "DataClass" });
16577
+ var DATA_CLASS_ORDER = DataClass.options;
16578
+ var ShareTrustLevel = external_exports.enum(["recognized", "internal", "unverified", "ip"]).meta({ id: "ShareTrustLevel" });
16579
+ var EgressDecision = external_exports.enum(["allow", "block"]).meta({ id: "EgressDecision" });
16580
+ var EgressStatus = external_exports.enum(["allowed", "blocked", "review"]).meta({ id: "EgressStatus" });
16581
+ var ReviewReason = external_exports.enum(["raw_ip", "unverified_domain", "plaintext_transport"]).meta({ id: "ReviewReason" });
16582
+ var HttpMethod = external_exports.enum(["GET", "POST", "PUT", "DELETE", "SDK", "REF"]).meta({ id: "HttpMethod" });
16583
+ var ReviewInfo = external_exports.object({
16584
+ needsReview: external_exports.boolean(),
16585
+ reasons: external_exports.array(ReviewReason)
16586
+ }).meta({ id: "ReviewInfo" });
16587
+ var DestinationNetwork = external_exports.object({
16588
+ port: external_exports.number().int().nullable(),
16589
+ geo: external_exports.string().nullable(),
16590
+ ptr: external_exports.string().nullable()
16591
+ }).meta({ id: "DestinationNetwork" });
16592
+ var EndpointSummary = external_exports.object({
16593
+ id: external_exports.string(),
16594
+ method: HttpMethod,
16595
+ transport: Transport,
16596
+ url: external_exports.string(),
16597
+ template: external_exports.boolean(),
16598
+ dataClass: DataClass,
16599
+ lastSeen: external_exports.iso.datetime(),
16600
+ callSiteCount: external_exports.number().int().nonnegative()
16601
+ }).meta({ id: "EndpointSummary" });
16602
+ var CallSite = external_exports.object({
16603
+ id: external_exports.string(),
16604
+ project: external_exports.string(),
16605
+ file: external_exports.string(),
16606
+ line: external_exports.number().int().nonnegative(),
16607
+ snippet: external_exports.string(),
16608
+ dynamic: external_exports.boolean(),
16609
+ vendored: external_exports.boolean(),
16610
+ /** Deep-link to the Inventory project, when the repo is governed there. */
16611
+ projectId: external_exports.string().nullable()
16612
+ }).meta({ id: "CallSite" });
16613
+ var EndpointWithSites = EndpointSummary.extend({
16614
+ sites: external_exports.array(CallSite)
16615
+ }).meta({ id: "EndpointWithSites" });
16616
+ var ShareDestinationSummary = external_exports.object({
16617
+ id: external_exports.string(),
16618
+ kind: DestinationKind,
16619
+ name: external_exports.string(),
16620
+ host: external_exports.string(),
16621
+ category: external_exports.string(),
16622
+ trust: ShareTrustLevel,
16623
+ /** Effective state (decision applied over the trust default). */
16624
+ status: EgressStatus,
16625
+ /** True when an egress decision override differs from the trust default. */
16626
+ isCustom: external_exports.boolean(),
16627
+ lastSeen: external_exports.iso.datetime(),
16628
+ endpointCount: external_exports.number().int().nonnegative(),
16629
+ callSiteCount: external_exports.number().int().nonnegative(),
16630
+ transports: external_exports.array(Transport),
16631
+ /** Most-sensitive first. */
16632
+ dataClasses: external_exports.array(DataClass),
16633
+ review: ReviewInfo,
16634
+ /** Non-provider hosts only; null for providers. */
16635
+ network: DestinationNetwork.nullable(),
16636
+ /** Embedded for inline expansion — no call sites here. */
16637
+ endpoints: external_exports.array(EndpointSummary)
16638
+ }).meta({ id: "ShareDestinationSummary" });
16639
+ var ShareDestinationDetail = ShareDestinationSummary.omit({
16640
+ endpointCount: true,
16641
+ callSiteCount: true,
16642
+ endpoints: true
16643
+ }).extend({
16644
+ /** Ownership/geo rationale; null for providers. */
16645
+ note: external_exports.string().nullable(),
16646
+ endpoints: external_exports.array(EndpointWithSites)
16647
+ }).meta({ id: "ShareDestinationDetail" });
16648
+ var ReviewDestination = external_exports.object({
16649
+ id: external_exports.string(),
16650
+ kind: DestinationKind,
16651
+ name: external_exports.string(),
16652
+ /** Registrable host — lets the strip derive the provider lettermark, as the register does. */
16653
+ host: external_exports.string(),
16654
+ trust: ShareTrustLevel,
16655
+ status: EgressStatus,
16656
+ review: ReviewInfo,
16657
+ topDataClass: DataClass,
16658
+ callSiteCount: external_exports.number().int().nonnegative(),
16659
+ lastSeen: external_exports.iso.datetime()
16660
+ }).meta({ id: "ReviewDestination" });
16661
+ var ShareDestinationGroup = external_exports.object({
16662
+ kind: DestinationKind,
16663
+ total: external_exports.number().int().nonnegative(),
16664
+ items: external_exports.array(ShareDestinationSummary)
16665
+ }).meta({ id: "ShareDestinationGroup" });
16666
+ var ListShareDestinationsResponse = external_exports.object({ groups: external_exports.array(ShareDestinationGroup) }).meta({ id: "ListShareDestinationsResponse" });
16667
+ var NeedsReviewResponse = external_exports.object({ items: external_exports.array(ReviewDestination) }).meta({ id: "NeedsReviewResponse" });
16668
+ var SharesStats = external_exports.object({
16669
+ destinations: external_exports.number().int().nonnegative(),
16670
+ endpoints: external_exports.number().int().nonnegative(),
16671
+ callSites: external_exports.number().int().nonnegative(),
16672
+ needsReview: external_exports.number().int().nonnegative(),
16673
+ insecure: external_exports.number().int().nonnegative(),
16674
+ byKind: external_exports.object({
16675
+ provider: external_exports.number().int().nonnegative(),
16676
+ internal: external_exports.number().int().nonnegative(),
16677
+ external: external_exports.number().int().nonnegative(),
16678
+ ip: external_exports.number().int().nonnegative()
16679
+ }),
16680
+ byTrust: external_exports.object({
16681
+ recognized: external_exports.number().int().nonnegative(),
16682
+ internal: external_exports.number().int().nonnegative(),
16683
+ unverified: external_exports.number().int().nonnegative(),
16684
+ ip: external_exports.number().int().nonnegative()
16685
+ })
16686
+ }).meta({ id: "SharesStats" });
16687
+ var SetEgressDecisionBody = external_exports.object({
16688
+ /** `null` clears the override — reverts to the trust default, isCustom false. */
16689
+ decision: EgressDecision.nullable()
16690
+ }).meta({ id: "SetEgressDecisionBody" });
16691
+ var SetEgressDecisionResponse = external_exports.object({ destination: ShareDestinationSummary }).meta({ id: "SetEgressDecisionResponse" });
16692
+ var ListShareDestinationsQuery = external_exports.object({
16693
+ /** Case-insensitive match over destination name/category, endpoint url, call-site project/file. */
16694
+ q: external_exports.string().optional(),
16695
+ /** Repeatable. Restrict to these DestinationKind values; absent means all kinds. */
16696
+ kind: external_exports.array(DestinationKind).optional(),
16697
+ /** Reserved for future grouping modes; only 'destination' is supported today. */
16698
+ groupBy: external_exports.enum(["destination"]).default("destination"),
16699
+ /**
16700
+ * When true, return a flat severity-ordered `items[]` instead of `groups`.
16701
+ * Uses `z.stringbool()` (NOT `z.coerce.boolean()` — `Boolean(str)` is true for
16702
+ * any non-empty string, so `?review=false`/`?review=0` would wrongly coerce
16703
+ * to `true`). `z.stringbool()` parses true/1/yes vs false/0/no correctly.
16704
+ */
16705
+ review: external_exports.stringbool().default(false)
16706
+ });
16707
+ var ExportSharesQuery = external_exports.object({
16708
+ format: external_exports.enum(["csv", "json"]).default("csv"),
16709
+ q: external_exports.string().optional(),
16710
+ kind: external_exports.array(DestinationKind).optional()
16711
+ });
16712
+
16713
+ // ../../packages/schema/src/zod/egress-extraction.ts
16714
+ var EgressEcosystem = external_exports.enum(["npm", "pypi", "go", "maven", "rubygems", "cargo", "composer", "nuget"]).meta({ id: "EgressEcosystem" });
16715
+ var ProviderRegistryEntry = external_exports.object({
16716
+ id: external_exports.string(),
16717
+ name: external_exports.string(),
16718
+ category: external_exports.string(),
16719
+ /** Suffix-matched: 'stripe.com' matches api.stripe.com, never evilstripe.com. */
16720
+ hostSuffixes: external_exports.array(external_exports.string()).min(1),
16721
+ /** Canonical API base URL recorded for manifest-derived (method 'SDK') endpoints. */
16722
+ apiBase: external_exports.string(),
16723
+ /** Most-sensitive first; index 0 becomes the endpoint dataClass. */
16724
+ defaultDataClasses: external_exports.array(DataClass).min(1),
16725
+ /** SDK identifiers per ecosystem ('go' prefix-matched by path, 'maven' by group-id prefix). */
16726
+ sdks: external_exports.partialRecord(EgressEcosystem, external_exports.array(external_exports.string()))
16727
+ }).meta({ id: "ProviderRegistryEntry" });
16728
+ var EgressCallSiteHit = external_exports.object({
16729
+ file: external_exports.string(),
16730
+ line: external_exports.number().int().positive(),
16731
+ snippet: external_exports.string(),
16732
+ dynamic: external_exports.boolean(),
16733
+ vendored: external_exports.boolean()
16734
+ }).meta({ id: "EgressCallSiteHit" });
16735
+ var ResolvedEgressHit = external_exports.object({
16736
+ host: external_exports.string(),
16737
+ kind: DestinationKind,
16738
+ name: external_exports.string(),
16739
+ category: external_exports.string(),
16740
+ trust: ShareTrustLevel,
16741
+ network: DestinationNetwork.nullable(),
16742
+ method: HttpMethod,
16743
+ transport: Transport,
16744
+ url: external_exports.string(),
16745
+ template: external_exports.boolean(),
16746
+ dataClass: DataClass,
16747
+ site: EgressCallSiteHit
16748
+ }).meta({ id: "ResolvedEgressHit" });
16749
+ var EgressReconcile = external_exports.discriminatedUnion("mode", [
16750
+ external_exports.object({ mode: external_exports.literal("walk"), walkedPrefix: external_exports.string() }),
16751
+ external_exports.object({
16752
+ mode: external_exports.literal("ledger"),
16753
+ scannedFiles: external_exports.array(external_exports.string()),
16754
+ deletedFiles: external_exports.array(external_exports.string())
16755
+ })
16756
+ ]).meta({ id: "EgressReconcile" });
16757
+ var RecordProjectEgressInput = external_exports.object({
16758
+ /** Stable reconcile key: 'git:<repo identity>' or 'path:<abs root>' (non-git). */
16759
+ projectKey: external_exports.string().min(1),
16760
+ /** Display name only — never keys reconciliation. */
16761
+ project: external_exports.string(),
16762
+ projectId: external_exports.string().nullable(),
16763
+ reconcile: EgressReconcile,
16764
+ hits: external_exports.array(ResolvedEgressHit)
16765
+ }).meta({ id: "RecordProjectEgressInput" });
16766
+ var EgressWriteSummary = external_exports.object({
16767
+ destinations: external_exports.number().int().nonnegative(),
16768
+ endpoints: external_exports.number().int().nonnegative(),
16769
+ callSites: external_exports.number().int().nonnegative(),
16770
+ truncated: external_exports.boolean(),
16771
+ /**
16772
+ * Files the cap dropped whole. Their stored rows were left untouched, so a
16773
+ * ledger-keeping caller must withhold their ledger entries and read them
16774
+ * again next scan.
16775
+ */
16776
+ droppedFiles: external_exports.array(external_exports.string()).default([])
16777
+ }).meta({ id: "EgressWriteSummary" });
16778
+
16513
16779
  // ../../packages/schema/src/zod/installed-pack.ts
16514
16780
  var InstalledPack = external_exports.object({
16515
16781
  id: external_exports.guid(),
@@ -16541,10 +16807,14 @@ var PatchInstalledPackRequest = external_exports.object({
16541
16807
  }).meta({ id: "PatchInstalledPackRequest" });
16542
16808
 
16543
16809
  // ../../packages/schema/src/zod/local.ts
16544
- var WORKSPACE_SETTINGS_SPEC_VERSION = 2;
16810
+ var WORKSPACE_SETTINGS_SPEC_VERSION = 4;
16545
16811
  var RunMode = external_exports.enum(["standalone"]);
16546
16812
  var SimpleDetectionPolicy = external_exports.enum(["redact", "warn"]);
16547
16813
  var HistoricalAccess = external_exports.enum(["full", "session-only"]);
16814
+ var ModelJudgeConsent = external_exports.object({
16815
+ acknowledgedAt: external_exports.iso.datetime(),
16816
+ payloadVersion: external_exports.number().int().positive()
16817
+ });
16548
16818
  var WorkspaceSettings = external_exports.object({
16549
16819
  specVersion: external_exports.number().int().positive().default(WORKSPACE_SETTINGS_SPEC_VERSION),
16550
16820
  // Settings files written by earlier releases may carry the retired 'attached'
@@ -16556,8 +16826,16 @@ var WorkspaceSettings = external_exports.object({
16556
16826
  policy: SimpleDetectionPolicy.default("redact"),
16557
16827
  // Consent for scanning pre-install surfaces; opt-in (see HistoricalAccess).
16558
16828
  historicalAccess: HistoricalAccess.default("session-only"),
16829
+ // In-place egress extraction on the scan paths; disable to stop all Data
16830
+ // Shares writes.
16831
+ dataSharesInPlace: external_exports.boolean().default(true),
16559
16832
  // Absent until /aka:setup completes; its presence is what "onboarded" means.
16560
- onboardedAt: external_exports.iso.datetime().optional()
16833
+ onboardedAt: external_exports.iso.datetime().optional(),
16834
+ // Records that the user consented to sending findings to the model API for
16835
+ // the /aka:setup judge, along with the payload-shape version they agreed to.
16836
+ // Absent until granted; a stale payloadVersion means the consent no longer
16837
+ // covers the current payload and must be re-granted.
16838
+ modelJudgeConsent: ModelJudgeConsent.optional()
16561
16839
  });
16562
16840
 
16563
16841
  // ../../packages/schema/src/zod/project-files.ts
@@ -16932,150 +17210,11 @@ var SetupHandoffOffer = external_exports.object({
16932
17210
  path: ["liveKeys"]
16933
17211
  });
16934
17212
 
16935
- // ../../packages/schema/src/zod/shares.ts
16936
- var DestinationKind = external_exports.enum(["provider", "internal", "ip"]).meta({ id: "DestinationKind" });
16937
- var Transport = external_exports.enum(["https", "http", "sftp", "grpc", "smtp"]).meta({ id: "Transport" });
16938
- var DataClass = external_exports.enum(["secrets", "pii", "customer", "source", "telemetry", "logs", "metrics", "none"]).meta({ id: "DataClass" });
16939
- var DATA_CLASS_ORDER = DataClass.options;
16940
- var ShareTrustLevel = external_exports.enum(["recognized", "internal", "unverified", "ip"]).meta({ id: "ShareTrustLevel" });
16941
- var EgressDecision = external_exports.enum(["allow", "block"]).meta({ id: "EgressDecision" });
16942
- var EgressStatus = external_exports.enum(["allowed", "blocked", "review"]).meta({ id: "EgressStatus" });
16943
- var ReviewReason = external_exports.enum(["raw_ip", "unverified_domain", "plaintext_transport"]).meta({ id: "ReviewReason" });
16944
- var HttpMethod = external_exports.enum(["GET", "POST", "PUT", "DELETE"]).meta({ id: "HttpMethod" });
16945
- var ReviewInfo = external_exports.object({
16946
- needsReview: external_exports.boolean(),
16947
- reasons: external_exports.array(ReviewReason)
16948
- }).meta({ id: "ReviewInfo" });
16949
- var DestinationNetwork = external_exports.object({
16950
- port: external_exports.number().int().nullable(),
16951
- geo: external_exports.string().nullable(),
16952
- ptr: external_exports.string().nullable()
16953
- }).meta({ id: "DestinationNetwork" });
16954
- var EndpointSummary = external_exports.object({
16955
- id: external_exports.string(),
16956
- method: HttpMethod,
16957
- transport: Transport,
16958
- url: external_exports.string(),
16959
- template: external_exports.boolean(),
16960
- dataClass: DataClass,
16961
- lastSeen: external_exports.iso.datetime(),
16962
- callSiteCount: external_exports.number().int().nonnegative()
16963
- }).meta({ id: "EndpointSummary" });
16964
- var CallSite = external_exports.object({
16965
- id: external_exports.string(),
16966
- project: external_exports.string(),
16967
- file: external_exports.string(),
16968
- line: external_exports.number().int().nonnegative(),
16969
- snippet: external_exports.string(),
16970
- dynamic: external_exports.boolean(),
16971
- vendored: external_exports.boolean(),
16972
- /** Deep-link to the Inventory project, when the repo is governed there. */
16973
- projectId: external_exports.string().nullable()
16974
- }).meta({ id: "CallSite" });
16975
- var EndpointWithSites = EndpointSummary.extend({
16976
- sites: external_exports.array(CallSite)
16977
- }).meta({ id: "EndpointWithSites" });
16978
- var ShareDestinationSummary = external_exports.object({
16979
- id: external_exports.string(),
16980
- kind: DestinationKind,
16981
- name: external_exports.string(),
16982
- host: external_exports.string(),
16983
- category: external_exports.string(),
16984
- trust: ShareTrustLevel,
16985
- /** Effective state (decision applied over the trust default). */
16986
- status: EgressStatus,
16987
- /** True when an egress decision override differs from the trust default. */
16988
- isCustom: external_exports.boolean(),
16989
- lastSeen: external_exports.iso.datetime(),
16990
- endpointCount: external_exports.number().int().nonnegative(),
16991
- callSiteCount: external_exports.number().int().nonnegative(),
16992
- transports: external_exports.array(Transport),
16993
- /** Most-sensitive first. */
16994
- dataClasses: external_exports.array(DataClass),
16995
- review: ReviewInfo,
16996
- /** Non-provider hosts only; null for providers. */
16997
- network: DestinationNetwork.nullable(),
16998
- /** Embedded for inline expansion — no call sites here. */
16999
- endpoints: external_exports.array(EndpointSummary)
17000
- }).meta({ id: "ShareDestinationSummary" });
17001
- var ShareDestinationDetail = ShareDestinationSummary.omit({
17002
- endpointCount: true,
17003
- callSiteCount: true,
17004
- endpoints: true
17005
- }).extend({
17006
- /** Ownership/geo rationale; null for providers. */
17007
- note: external_exports.string().nullable(),
17008
- endpoints: external_exports.array(EndpointWithSites)
17009
- }).meta({ id: "ShareDestinationDetail" });
17010
- var ReviewDestination = external_exports.object({
17011
- id: external_exports.string(),
17012
- kind: DestinationKind,
17013
- name: external_exports.string(),
17014
- /** Registrable host — lets the strip derive the provider lettermark, as the register does. */
17015
- host: external_exports.string(),
17016
- trust: ShareTrustLevel,
17017
- status: EgressStatus,
17018
- review: ReviewInfo,
17019
- topDataClass: DataClass,
17020
- callSiteCount: external_exports.number().int().nonnegative(),
17021
- lastSeen: external_exports.iso.datetime()
17022
- }).meta({ id: "ReviewDestination" });
17023
- var ShareDestinationGroup = external_exports.object({
17024
- kind: DestinationKind,
17025
- total: external_exports.number().int().nonnegative(),
17026
- items: external_exports.array(ShareDestinationSummary)
17027
- }).meta({ id: "ShareDestinationGroup" });
17028
- var ListShareDestinationsResponse = external_exports.object({ groups: external_exports.array(ShareDestinationGroup) }).meta({ id: "ListShareDestinationsResponse" });
17029
- var NeedsReviewResponse = external_exports.object({ items: external_exports.array(ReviewDestination) }).meta({ id: "NeedsReviewResponse" });
17030
- var SharesStats = external_exports.object({
17031
- destinations: external_exports.number().int().nonnegative(),
17032
- endpoints: external_exports.number().int().nonnegative(),
17033
- callSites: external_exports.number().int().nonnegative(),
17034
- needsReview: external_exports.number().int().nonnegative(),
17035
- insecure: external_exports.number().int().nonnegative(),
17036
- byKind: external_exports.object({
17037
- provider: external_exports.number().int().nonnegative(),
17038
- internal: external_exports.number().int().nonnegative(),
17039
- ip: external_exports.number().int().nonnegative()
17040
- }),
17041
- byTrust: external_exports.object({
17042
- recognized: external_exports.number().int().nonnegative(),
17043
- internal: external_exports.number().int().nonnegative(),
17044
- unverified: external_exports.number().int().nonnegative(),
17045
- ip: external_exports.number().int().nonnegative()
17046
- })
17047
- }).meta({ id: "SharesStats" });
17048
- var SetEgressDecisionBody = external_exports.object({
17049
- /** `null` clears the override — reverts to the trust default, isCustom false. */
17050
- decision: EgressDecision.nullable()
17051
- }).meta({ id: "SetEgressDecisionBody" });
17052
- var SetEgressDecisionResponse = external_exports.object({ destination: ShareDestinationSummary }).meta({ id: "SetEgressDecisionResponse" });
17053
- var ListShareDestinationsQuery = external_exports.object({
17054
- /** Case-insensitive match over destination name/category, endpoint url, call-site project/file. */
17055
- q: external_exports.string().optional(),
17056
- /** Repeatable. Restrict to these DestinationKind values; absent means all kinds. */
17057
- kind: external_exports.array(DestinationKind).optional(),
17058
- /** Reserved for future grouping modes; only 'destination' is supported today. */
17059
- groupBy: external_exports.enum(["destination"]).default("destination"),
17060
- /**
17061
- * When true, return a flat severity-ordered `items[]` instead of `groups`.
17062
- * Uses `z.stringbool()` (NOT `z.coerce.boolean()` — `Boolean(str)` is true for
17063
- * any non-empty string, so `?review=false`/`?review=0` would wrongly coerce
17064
- * to `true`). `z.stringbool()` parses true/1/yes vs false/0/no correctly.
17065
- */
17066
- review: external_exports.stringbool().default(false)
17067
- });
17068
- var ExportSharesQuery = external_exports.object({
17069
- format: external_exports.enum(["csv", "json"]).default("csv"),
17070
- q: external_exports.string().optional(),
17071
- kind: external_exports.array(DestinationKind).optional()
17072
- });
17073
-
17074
17213
  // ../../packages/persistence/src/ids.ts
17075
17214
  import { createHash } from "crypto";
17076
17215
 
17077
17216
  // ../../packages/persistence/src/paths.ts
17078
- import { chmodSync, mkdirSync } from "fs";
17217
+ import { chmodSync, lstatSync, mkdirSync, renameSync, rmSync, writeFileSync } from "fs";
17079
17218
 
17080
17219
  // ../../packages/persistence/src/repositories/activity.ts
17081
17220
  var LIVE_ACTIVITY_WINDOW_MS = 30 * 6e4;
@@ -17105,23 +17244,26 @@ import { randomUUID as randomUUID6 } from "crypto";
17105
17244
  // ../../packages/persistence/src/repositories/shares.ts
17106
17245
  import { randomUUID as randomUUID7 } from "crypto";
17107
17246
 
17247
+ // ../../packages/persistence/src/finding-key.ts
17248
+ import { createHash as createHash3 } from "crypto";
17249
+
17108
17250
  // ../../packages/persistence/src/fingerprint.ts
17109
17251
  import { createHmac, randomBytes } from "crypto";
17110
- import { chmodSync as chmodSync2, readFileSync, renameSync as renameSync2, writeFileSync } from "fs";
17252
+ import { readFileSync } from "fs";
17111
17253
  import { join as join2 } from "path";
17112
17254
 
17113
17255
  // ../../packages/persistence/src/local-layout.ts
17114
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync2, renameSync as renameSync3 } from "fs";
17115
- import { chmod, mkdir } from "fs/promises";
17256
+ import { renameSync as renameSync3 } from "fs";
17257
+ import { mkdir } from "fs/promises";
17116
17258
  import { homedir } from "os";
17117
17259
  import { join as join3 } from "path";
17118
17260
 
17119
17261
  // ../../packages/persistence/src/settings.ts
17120
- import { readFileSync as readFileSync2, renameSync as renameSync4, writeFileSync as writeFileSync2 } from "fs";
17262
+ import { readFileSync as readFileSync2 } from "fs";
17121
17263
  import { join as join4 } from "path";
17122
17264
 
17123
17265
  // ../../packages/persistence/src/warn-era-cap.ts
17124
- import { existsSync as existsSync2, writeFileSync as writeFileSync3 } from "fs";
17266
+ import { existsSync as existsSync2, writeFileSync as writeFileSync2 } from "fs";
17125
17267
  import { join as join5 } from "path";
17126
17268
 
17127
17269
  // ../../packages/plugin-sdk/src/provider-env.ts
@@ -17145,15 +17287,583 @@ var ProviderEnvSchema = external_exports.object(providerEnvShape);
17145
17287
  // ../../packages/plugin-sdk/src/config-inventory.ts
17146
17288
  import { readdirSync, readFileSync as readFileSync4, realpathSync, statSync as statSync2 } from "fs";
17147
17289
  import { homedir as homedir2 } from "os";
17148
- import { basename as basename2, join as join7 } from "path";
17290
+ import { basename as basename2, join as join8 } from "path";
17291
+
17292
+ // ../../packages/detections/src/egress/registry.ts
17293
+ var EXTRACTOR_VERSION = "1";
17294
+ var PROVIDER_REGISTRY = [
17295
+ {
17296
+ id: "stripe",
17297
+ name: "Stripe",
17298
+ category: "Payments",
17299
+ hostSuffixes: ["stripe.com"],
17300
+ apiBase: "https://api.stripe.com",
17301
+ defaultDataClasses: ["pii", "customer"],
17302
+ sdks: {
17303
+ npm: ["stripe"],
17304
+ pypi: ["stripe"],
17305
+ go: ["github.com/stripe/stripe-go"],
17306
+ maven: ["com.stripe"],
17307
+ rubygems: ["stripe"],
17308
+ composer: ["stripe/stripe-php"],
17309
+ nuget: ["Stripe.net"]
17310
+ }
17311
+ },
17312
+ {
17313
+ id: "datadog",
17314
+ name: "Datadog",
17315
+ category: "Observability",
17316
+ hostSuffixes: ["datadoghq.com", "datadoghq.eu"],
17317
+ apiBase: "https://api.datadoghq.com",
17318
+ defaultDataClasses: ["telemetry", "logs", "metrics"],
17319
+ sdks: {
17320
+ npm: ["dd-trace", "@datadog/browser-logs"],
17321
+ pypi: ["datadog", "ddtrace"],
17322
+ go: ["github.com/DataDog/dd-trace-go"],
17323
+ maven: ["com.datadoghq"],
17324
+ rubygems: ["ddtrace", "dogapi"],
17325
+ nuget: ["Datadog.Trace"]
17326
+ }
17327
+ },
17328
+ {
17329
+ id: "newrelic",
17330
+ name: "New Relic",
17331
+ category: "Observability",
17332
+ hostSuffixes: ["newrelic.com", "nr-data.net"],
17333
+ apiBase: "https://api.newrelic.com",
17334
+ defaultDataClasses: ["telemetry", "logs", "metrics"],
17335
+ sdks: {
17336
+ npm: ["newrelic"],
17337
+ pypi: ["newrelic"],
17338
+ go: ["github.com/newrelic/go-agent"],
17339
+ maven: ["com.newrelic.agent.java"],
17340
+ rubygems: ["newrelic_rpm"],
17341
+ nuget: ["NewRelic.Agent"]
17342
+ }
17343
+ },
17344
+ {
17345
+ id: "sentry",
17346
+ name: "Sentry",
17347
+ category: "Error tracking",
17348
+ hostSuffixes: ["sentry.io"],
17349
+ apiBase: "https://sentry.io",
17350
+ defaultDataClasses: ["source", "telemetry"],
17351
+ sdks: {
17352
+ npm: ["@sentry/node", "@sentry/react", "@sentry/nextjs"],
17353
+ pypi: ["sentry-sdk"],
17354
+ go: ["github.com/getsentry/sentry-go"],
17355
+ maven: ["io.sentry"],
17356
+ rubygems: ["sentry-ruby"],
17357
+ cargo: ["sentry"],
17358
+ composer: ["sentry/sentry"],
17359
+ nuget: ["Sentry"]
17360
+ }
17361
+ },
17362
+ {
17363
+ id: "openai",
17364
+ name: "OpenAI",
17365
+ category: "LLM provider",
17366
+ hostSuffixes: ["openai.com"],
17367
+ apiBase: "https://api.openai.com",
17368
+ defaultDataClasses: ["pii", "source"],
17369
+ sdks: {
17370
+ npm: ["openai"],
17371
+ pypi: ["openai"],
17372
+ go: ["github.com/sashabaranov/go-openai"],
17373
+ maven: ["com.openai"],
17374
+ rubygems: ["ruby-openai"],
17375
+ cargo: ["async-openai"],
17376
+ composer: ["openai-php/client"],
17377
+ nuget: ["OpenAI"]
17378
+ }
17379
+ },
17380
+ {
17381
+ id: "anthropic",
17382
+ name: "Anthropic",
17383
+ category: "LLM provider",
17384
+ hostSuffixes: ["anthropic.com"],
17385
+ apiBase: "https://api.anthropic.com",
17386
+ defaultDataClasses: ["pii", "source"],
17387
+ sdks: {
17388
+ npm: ["@anthropic-ai/sdk"],
17389
+ pypi: ["anthropic"],
17390
+ go: ["github.com/anthropics/anthropic-sdk-go"],
17391
+ nuget: ["Anthropic.SDK"]
17392
+ }
17393
+ },
17394
+ {
17395
+ id: "aws",
17396
+ name: "Amazon Web Services",
17397
+ category: "Cloud platform",
17398
+ hostSuffixes: ["amazonaws.com"],
17399
+ apiBase: "https://s3.amazonaws.com",
17400
+ defaultDataClasses: ["secrets", "customer"],
17401
+ sdks: {
17402
+ npm: ["@aws-sdk/client-s3", "aws-sdk"],
17403
+ pypi: ["boto3"],
17404
+ go: ["github.com/aws/aws-sdk-go", "github.com/aws/aws-sdk-go-v2"],
17405
+ maven: ["com.amazonaws", "software.amazon.awssdk"],
17406
+ rubygems: ["aws-sdk-s3"],
17407
+ cargo: ["aws-sdk-s3"],
17408
+ nuget: ["AWSSDK.S3"]
17409
+ }
17410
+ },
17411
+ {
17412
+ id: "gcp",
17413
+ name: "Google Cloud",
17414
+ category: "Cloud platform",
17415
+ hostSuffixes: ["googleapis.com"],
17416
+ apiBase: "https://storage.googleapis.com",
17417
+ defaultDataClasses: ["customer", "logs"],
17418
+ sdks: {
17419
+ npm: ["@google-cloud/storage"],
17420
+ pypi: ["google-cloud-storage"],
17421
+ go: ["cloud.google.com/go"],
17422
+ maven: ["com.google.cloud"],
17423
+ rubygems: ["google-cloud-storage"],
17424
+ nuget: ["Google.Cloud.Storage.V1"]
17425
+ }
17426
+ },
17427
+ {
17428
+ id: "azure",
17429
+ name: "Microsoft Azure",
17430
+ category: "Cloud platform",
17431
+ hostSuffixes: ["azure.com", "windows.net"],
17432
+ apiBase: "https://management.azure.com",
17433
+ defaultDataClasses: ["customer", "logs"],
17434
+ sdks: {
17435
+ npm: ["@azure/storage-blob"],
17436
+ pypi: ["azure-storage-blob"],
17437
+ go: ["github.com/Azure/azure-sdk-for-go"],
17438
+ maven: ["com.azure"],
17439
+ rubygems: ["azure-storage-blob"],
17440
+ nuget: ["Azure.Storage.Blobs"]
17441
+ }
17442
+ },
17443
+ {
17444
+ id: "slack",
17445
+ name: "Slack",
17446
+ category: "Notifications",
17447
+ hostSuffixes: ["slack.com"],
17448
+ apiBase: "https://slack.com/api",
17449
+ defaultDataClasses: ["logs"],
17450
+ sdks: {
17451
+ npm: ["@slack/web-api"],
17452
+ pypi: ["slack-sdk"],
17453
+ go: ["github.com/slack-go/slack"],
17454
+ maven: ["com.slack.api"],
17455
+ rubygems: ["slack-ruby-client"],
17456
+ composer: ["slack-php/slack-api"],
17457
+ nuget: ["SlackNet"]
17458
+ }
17459
+ },
17460
+ {
17461
+ id: "segment",
17462
+ name: "Segment",
17463
+ category: "Analytics",
17464
+ hostSuffixes: ["segment.io", "segment.com"],
17465
+ apiBase: "https://api.segment.io",
17466
+ defaultDataClasses: ["customer"],
17467
+ sdks: {
17468
+ npm: ["@segment/analytics-node", "analytics-node"],
17469
+ pypi: ["segment-analytics-python"],
17470
+ go: ["github.com/segmentio/analytics-go"],
17471
+ maven: ["com.segment.analytics.java"],
17472
+ rubygems: ["analytics-ruby"],
17473
+ nuget: ["Analytics"]
17474
+ }
17475
+ },
17476
+ {
17477
+ id: "twilio",
17478
+ name: "Twilio",
17479
+ category: "Communications",
17480
+ hostSuffixes: ["twilio.com"],
17481
+ apiBase: "https://api.twilio.com",
17482
+ defaultDataClasses: ["pii", "customer"],
17483
+ sdks: {
17484
+ npm: ["twilio"],
17485
+ pypi: ["twilio"],
17486
+ go: ["github.com/twilio/twilio-go"],
17487
+ maven: ["com.twilio.sdk"],
17488
+ rubygems: ["twilio-ruby"],
17489
+ composer: ["twilio/sdk"],
17490
+ nuget: ["Twilio"]
17491
+ }
17492
+ },
17493
+ {
17494
+ id: "sendgrid",
17495
+ name: "SendGrid",
17496
+ category: "Email",
17497
+ hostSuffixes: ["sendgrid.com"],
17498
+ apiBase: "https://api.sendgrid.com",
17499
+ defaultDataClasses: ["pii"],
17500
+ sdks: {
17501
+ npm: ["@sendgrid/mail"],
17502
+ pypi: ["sendgrid"],
17503
+ go: ["github.com/sendgrid/sendgrid-go"],
17504
+ maven: ["com.sendgrid"],
17505
+ rubygems: ["sendgrid-ruby"],
17506
+ composer: ["sendgrid/sendgrid"],
17507
+ nuget: ["SendGrid"]
17508
+ }
17509
+ },
17510
+ {
17511
+ id: "mailgun",
17512
+ name: "Mailgun",
17513
+ category: "Email",
17514
+ hostSuffixes: ["mailgun.net"],
17515
+ apiBase: "https://api.mailgun.net",
17516
+ defaultDataClasses: ["pii"],
17517
+ sdks: {
17518
+ npm: ["mailgun.js"],
17519
+ pypi: ["mailgun"],
17520
+ rubygems: ["mailgun-ruby"],
17521
+ composer: ["mailgun/mailgun-php"],
17522
+ nuget: ["Mailgun"]
17523
+ }
17524
+ },
17525
+ {
17526
+ id: "mixpanel",
17527
+ name: "Mixpanel",
17528
+ category: "Analytics",
17529
+ hostSuffixes: ["mixpanel.com"],
17530
+ apiBase: "https://api.mixpanel.com",
17531
+ defaultDataClasses: ["customer", "telemetry"],
17532
+ sdks: {
17533
+ npm: ["mixpanel"],
17534
+ pypi: ["mixpanel"],
17535
+ rubygems: ["mixpanel-ruby"],
17536
+ nuget: ["Mixpanel"]
17537
+ }
17538
+ },
17539
+ {
17540
+ id: "amplitude",
17541
+ name: "Amplitude",
17542
+ category: "Analytics",
17543
+ hostSuffixes: ["amplitude.com"],
17544
+ apiBase: "https://api2.amplitude.com",
17545
+ defaultDataClasses: ["customer", "telemetry"],
17546
+ sdks: {
17547
+ npm: ["@amplitude/analytics-node"],
17548
+ pypi: ["amplitude-analytics"],
17549
+ nuget: ["Amplitude"]
17550
+ }
17551
+ },
17552
+ {
17553
+ id: "posthog",
17554
+ name: "PostHog",
17555
+ category: "Analytics",
17556
+ hostSuffixes: ["posthog.com"],
17557
+ apiBase: "https://us.i.posthog.com",
17558
+ defaultDataClasses: ["customer", "telemetry"],
17559
+ sdks: {
17560
+ npm: ["posthog-node", "posthog-js"],
17561
+ pypi: ["posthog"],
17562
+ go: ["github.com/posthog/posthog-go"],
17563
+ rubygems: ["posthog-ruby"],
17564
+ composer: ["posthog/posthog-php"],
17565
+ nuget: ["PostHog"]
17566
+ }
17567
+ },
17568
+ {
17569
+ id: "honeycomb",
17570
+ name: "Honeycomb",
17571
+ category: "Observability",
17572
+ hostSuffixes: ["honeycomb.io"],
17573
+ apiBase: "https://api.honeycomb.io",
17574
+ defaultDataClasses: ["telemetry", "metrics"],
17575
+ sdks: {
17576
+ npm: ["libhoney"],
17577
+ pypi: ["libhoney"],
17578
+ go: ["github.com/honeycombio/libhoney-go"],
17579
+ rubygems: ["libhoney"]
17580
+ }
17581
+ },
17582
+ {
17583
+ id: "grafana",
17584
+ name: "Grafana Cloud",
17585
+ category: "Observability",
17586
+ hostSuffixes: ["grafana.net"],
17587
+ apiBase: "https://grafana.net",
17588
+ defaultDataClasses: ["logs", "metrics"],
17589
+ sdks: {
17590
+ npm: ["@grafana/faro-web-sdk"]
17591
+ }
17592
+ },
17593
+ {
17594
+ id: "splunk",
17595
+ name: "Splunk",
17596
+ category: "Observability",
17597
+ hostSuffixes: ["splunkcloud.com", "splunk.com"],
17598
+ apiBase: "https://http-inputs.splunkcloud.com",
17599
+ defaultDataClasses: ["logs"],
17600
+ sdks: {
17601
+ npm: ["splunk-logging"],
17602
+ pypi: ["splunk-sdk"],
17603
+ maven: ["com.splunk"],
17604
+ nuget: ["Splunk.Logging.Common"]
17605
+ }
17606
+ },
17607
+ {
17608
+ id: "pagerduty",
17609
+ name: "PagerDuty",
17610
+ category: "Incident response",
17611
+ hostSuffixes: ["pagerduty.com"],
17612
+ apiBase: "https://api.pagerduty.com",
17613
+ defaultDataClasses: ["logs"],
17614
+ sdks: {
17615
+ npm: ["@pagerduty/pdjs"],
17616
+ pypi: ["pdpyras"],
17617
+ go: ["github.com/PagerDuty/go-pagerduty"],
17618
+ rubygems: ["pagerduty"]
17619
+ }
17620
+ },
17621
+ {
17622
+ id: "github",
17623
+ name: "GitHub",
17624
+ category: "Developer platform",
17625
+ hostSuffixes: ["github.com", "githubusercontent.com"],
17626
+ apiBase: "https://api.github.com",
17627
+ defaultDataClasses: ["source"],
17628
+ sdks: {
17629
+ npm: ["@octokit/rest", "octokit"],
17630
+ pypi: ["pygithub"],
17631
+ go: ["github.com/google/go-github"],
17632
+ maven: ["org.kohsuke.github-api"],
17633
+ rubygems: ["octokit"],
17634
+ cargo: ["octocrab"],
17635
+ composer: ["knplabs/github-api"],
17636
+ nuget: ["Octokit"]
17637
+ }
17638
+ },
17639
+ {
17640
+ id: "gitlab",
17641
+ name: "GitLab",
17642
+ category: "Developer platform",
17643
+ hostSuffixes: ["gitlab.com"],
17644
+ apiBase: "https://gitlab.com/api",
17645
+ defaultDataClasses: ["source"],
17646
+ sdks: {
17647
+ npm: ["@gitbeaker/rest"],
17648
+ pypi: ["python-gitlab"],
17649
+ go: ["gitlab.com/gitlab-org/api/client-go"],
17650
+ rubygems: ["gitlab"],
17651
+ nuget: ["GitLabApiClient"]
17652
+ }
17653
+ },
17654
+ {
17655
+ id: "auth0",
17656
+ name: "Auth0",
17657
+ category: "Identity",
17658
+ hostSuffixes: ["auth0.com"],
17659
+ apiBase: "https://login.auth0.com",
17660
+ defaultDataClasses: ["pii"],
17661
+ sdks: {
17662
+ npm: ["auth0"],
17663
+ pypi: ["auth0-python"],
17664
+ go: ["github.com/auth0/go-auth0"],
17665
+ maven: ["com.auth0"],
17666
+ rubygems: ["auth0"],
17667
+ composer: ["auth0/auth0-php"],
17668
+ nuget: ["Auth0.ManagementApi"]
17669
+ }
17670
+ },
17671
+ {
17672
+ id: "okta",
17673
+ name: "Okta",
17674
+ category: "Identity",
17675
+ hostSuffixes: ["okta.com", "oktapreview.com"],
17676
+ apiBase: "https://login.okta.com",
17677
+ defaultDataClasses: ["pii"],
17678
+ sdks: {
17679
+ npm: ["@okta/okta-sdk-nodejs"],
17680
+ pypi: ["okta"],
17681
+ go: ["github.com/okta/okta-sdk-golang"],
17682
+ maven: ["com.okta.sdk"],
17683
+ nuget: ["Okta.Sdk"]
17684
+ }
17685
+ },
17686
+ {
17687
+ id: "clerk",
17688
+ name: "Clerk",
17689
+ category: "Identity",
17690
+ hostSuffixes: ["clerk.com", "clerk.dev"],
17691
+ apiBase: "https://api.clerk.com",
17692
+ defaultDataClasses: ["pii"],
17693
+ sdks: {
17694
+ npm: ["@clerk/backend", "@clerk/nextjs"],
17695
+ pypi: ["clerk-backend-api"],
17696
+ go: ["github.com/clerk/clerk-sdk-go"]
17697
+ }
17698
+ },
17699
+ {
17700
+ id: "supabase",
17701
+ name: "Supabase",
17702
+ category: "Backend platform",
17703
+ hostSuffixes: ["supabase.co", "supabase.com"],
17704
+ apiBase: "https://api.supabase.com",
17705
+ defaultDataClasses: ["pii", "customer"],
17706
+ sdks: {
17707
+ npm: ["@supabase/supabase-js"],
17708
+ pypi: ["supabase"],
17709
+ cargo: ["postgrest"]
17710
+ }
17711
+ },
17712
+ {
17713
+ id: "firebase",
17714
+ name: "Firebase",
17715
+ category: "Backend platform",
17716
+ hostSuffixes: ["firebaseio.com", "firebase.google.com"],
17717
+ apiBase: "https://firebaseio.com",
17718
+ defaultDataClasses: ["customer"],
17719
+ sdks: {
17720
+ npm: ["firebase", "firebase-admin"],
17721
+ pypi: ["firebase-admin"],
17722
+ go: ["firebase.google.com/go"],
17723
+ maven: ["com.google.firebase"]
17724
+ }
17725
+ },
17726
+ {
17727
+ id: "mongodb-atlas",
17728
+ name: "MongoDB Atlas",
17729
+ category: "Database SaaS",
17730
+ hostSuffixes: ["mongodb.net", "mongodb.com"],
17731
+ apiBase: "https://cloud.mongodb.com",
17732
+ defaultDataClasses: ["customer"],
17733
+ sdks: {
17734
+ npm: ["mongodb"],
17735
+ pypi: ["pymongo"],
17736
+ go: ["go.mongodb.org/mongo-driver"],
17737
+ maven: ["org.mongodb"],
17738
+ rubygems: ["mongo"],
17739
+ cargo: ["mongodb"],
17740
+ nuget: ["MongoDB.Driver"]
17741
+ }
17742
+ },
17743
+ {
17744
+ id: "planetscale",
17745
+ name: "PlanetScale",
17746
+ category: "Database SaaS",
17747
+ hostSuffixes: ["psdb.cloud", "planetscale.com"],
17748
+ apiBase: "https://api.planetscale.com",
17749
+ defaultDataClasses: ["customer"],
17750
+ sdks: {
17751
+ npm: ["@planetscale/database"],
17752
+ go: ["github.com/planetscale/planetscale-go"]
17753
+ }
17754
+ },
17755
+ {
17756
+ id: "algolia",
17757
+ name: "Algolia",
17758
+ category: "Search SaaS",
17759
+ hostSuffixes: ["algolia.net", "algolianet.com"],
17760
+ apiBase: "https://algolia.net",
17761
+ defaultDataClasses: ["customer"],
17762
+ sdks: {
17763
+ npm: ["algoliasearch"],
17764
+ pypi: ["algoliasearch"],
17765
+ go: ["github.com/algolia/algoliasearch-client-go"],
17766
+ maven: ["com.algolia"],
17767
+ rubygems: ["algolia"],
17768
+ composer: ["algolia/algoliasearch-client-php"],
17769
+ nuget: ["Algolia.Search"]
17770
+ }
17771
+ },
17772
+ {
17773
+ id: "cloudflare",
17774
+ name: "Cloudflare",
17775
+ category: "CDN / edge",
17776
+ hostSuffixes: ["cloudflare.com", "workers.dev"],
17777
+ apiBase: "https://api.cloudflare.com",
17778
+ defaultDataClasses: ["logs"],
17779
+ sdks: {
17780
+ npm: ["cloudflare"],
17781
+ pypi: ["cloudflare"],
17782
+ go: ["github.com/cloudflare/cloudflare-go"],
17783
+ nuget: ["CloudFlare.Client"]
17784
+ }
17785
+ },
17786
+ {
17787
+ id: "huggingface",
17788
+ name: "Hugging Face",
17789
+ category: "LLM provider",
17790
+ hostSuffixes: ["huggingface.co"],
17791
+ apiBase: "https://api-inference.huggingface.co",
17792
+ defaultDataClasses: ["source"],
17793
+ sdks: {
17794
+ npm: ["@huggingface/inference"],
17795
+ pypi: ["huggingface-hub", "transformers"],
17796
+ rubygems: ["hugging-face"]
17797
+ }
17798
+ },
17799
+ {
17800
+ id: "cohere",
17801
+ name: "Cohere",
17802
+ category: "LLM provider",
17803
+ hostSuffixes: ["cohere.com", "cohere.ai"],
17804
+ apiBase: "https://api.cohere.com",
17805
+ defaultDataClasses: ["pii", "source"],
17806
+ sdks: {
17807
+ npm: ["cohere-ai"],
17808
+ pypi: ["cohere"],
17809
+ go: ["github.com/cohere-ai/cohere-go"]
17810
+ }
17811
+ },
17812
+ {
17813
+ id: "mistral",
17814
+ name: "Mistral AI",
17815
+ category: "LLM provider",
17816
+ hostSuffixes: ["mistral.ai"],
17817
+ apiBase: "https://api.mistral.ai",
17818
+ defaultDataClasses: ["pii", "source"],
17819
+ sdks: {
17820
+ npm: ["@mistralai/mistralai"],
17821
+ pypi: ["mistralai"],
17822
+ go: ["github.com/gage-technologies/mistral-go"]
17823
+ }
17824
+ }
17825
+ ];
17826
+ var EGRESS_VERSION_MATERIAL = `${EXTRACTOR_VERSION}
17827
+ ${JSON.stringify(PROVIDER_REGISTRY)}`;
17828
+
17829
+ // ../../packages/detections/src/egress/extract.ts
17830
+ var SECRET_KEY_NAMES = "api[_-]?key|apikey|private[_-]?key|access[_-]?key|access[_-]?token|token|secret|credentials?|password|passwd|pwd|authorization|sig|signature|sas|assertion";
17831
+ var AUTH_SCHEMES = "Bearer|Basic|Token|Digest|ApiKey|SSWS|AWS4-HMAC-SHA256";
17832
+ var SECRET_VALUE = new RegExp(
17833
+ `((?:${SECRET_KEY_NAMES})['"\`]?\\s*[:=]\\s*['"\`]?)(?!(?:${AUTH_SCHEMES})[\\s'"\`])[^\\s'"\`&]+`,
17834
+ "gi"
17835
+ );
17836
+ var AUTH_SCHEME_VALUE = new RegExp(
17837
+ `((?:${SECRET_KEY_NAMES})['"\`]?\\s*[:=]\\s*['"\`]?)(${AUTH_SCHEMES})\\s+[^\\s'"\`]+`,
17838
+ "gi"
17839
+ );
17840
+ var WEBHOOK_SECRET_PATHS = [
17841
+ { hosts: ["hooks.slack.com"], prefix: "/services/" },
17842
+ {
17843
+ hosts: ["discord.com", "discordapp.com", "ptb.discord.com", "canary.discord.com"],
17844
+ prefix: "/api/webhooks/"
17845
+ },
17846
+ { hosts: ["hooks.zapier.com"], prefix: "/hooks/" },
17847
+ { hosts: ["outlook.office.com", "outlook.office365.com"], prefix: "/webhook/" }
17848
+ ];
17849
+ function escapeRegExp(literal2) {
17850
+ return literal2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
17851
+ }
17852
+ var WEBHOOK_URL = new RegExp(
17853
+ `(https?://(?:${WEBHOOK_SECRET_PATHS.flatMap(
17854
+ (entry) => entry.hosts.map((host) => `${escapeRegExp(host)}${escapeRegExp(entry.prefix)}`)
17855
+ ).join("|")}))[^\\s'"\`<>()[\\]{},;]+`,
17856
+ "gi"
17857
+ );
17149
17858
 
17150
17859
  // ../../packages/detections/src/escape-regexp.ts
17151
- function escapeRegExp(value) {
17860
+ function escapeRegExp2(value) {
17152
17861
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
17153
17862
  }
17154
17863
 
17155
17864
  // ../../packages/detections/src/matchers/limits.ts
17156
17865
  var MAX_MATCHES_PER_RULE = 1e4;
17866
+ var MAX_REGEX_INPUT_LENGTH = 2e5;
17157
17867
 
17158
17868
  // ../../packages/detections/src/matchers/keyword.ts
17159
17869
  var KeywordMatcher2 = class {
@@ -17164,7 +17874,7 @@ var KeywordMatcher2 = class {
17164
17874
  for (const kw of keywords) {
17165
17875
  if (kw.length === 0) continue;
17166
17876
  if (spans.length >= MAX_MATCHES_PER_RULE) break;
17167
- const re = new RegExp(escapeRegExp(kw), caseSensitive ? "gu" : "giu");
17877
+ const re = new RegExp(escapeRegExp2(kw), caseSensitive ? "gu" : "giu");
17168
17878
  let m;
17169
17879
  while ((m = re.exec(text)) !== null) {
17170
17880
  spans.push({ start: m.index, end: m.index + m[0].length });
@@ -17181,9 +17891,13 @@ var RegexMatcher2 = class {
17181
17891
  if (rule.matcher.type !== "regex") return [];
17182
17892
  const { pattern, flags, captureGroup } = rule.matcher;
17183
17893
  const re = new RegExp(pattern, flags.includes("d") ? flags : `${flags}d`);
17894
+ const scanText2 = text.length > MAX_REGEX_INPUT_LENGTH ? text.slice(0, MAX_REGEX_INPUT_LENGTH) : text;
17184
17895
  const spans = [];
17185
17896
  let m;
17186
- while ((m = re.exec(text)) !== null) {
17897
+ const maxIterations = scanText2.length + 1;
17898
+ let iterations = 0;
17899
+ while ((m = re.exec(scanText2)) !== null) {
17900
+ if (++iterations > maxIterations) break;
17187
17901
  const group = captureGroup != null ? m[captureGroup] : m[0];
17188
17902
  if (m[0].length === 0) re.lastIndex++;
17189
17903
  if (group && spans.length < MAX_MATCHES_PER_RULE) {
@@ -17258,27 +17972,53 @@ var CONFIG_POSTURE_RULES = [
17258
17972
  }
17259
17973
  ];
17260
17974
 
17975
+ // ../../packages/detections/src/security/redos-probe.ts
17976
+ var EXPONENTIAL_UNITS = [
17977
+ "a",
17978
+ "0",
17979
+ " ",
17980
+ "x",
17981
+ "ab",
17982
+ "a.",
17983
+ "a-",
17984
+ "a_",
17985
+ "a@",
17986
+ "a/",
17987
+ "a:",
17988
+ "a=",
17989
+ "a;",
17990
+ "aA0",
17991
+ " "
17992
+ ];
17993
+ var EXPONENTIAL_PROBES = EXPONENTIAL_UNITS.flatMap(
17994
+ (unit) => [23, 25].map((len) => unit.repeat(Math.ceil(len / unit.length)).slice(0, len) + "!")
17995
+ );
17996
+ var POLYNOMIAL_PROBES = ["abc-", "a.", "a ", "a=", "x", "0", "a@", "a/", "ab"].map(
17997
+ (unit) => unit.repeat(1e4).slice(0, 4e4) + "!"
17998
+ );
17999
+
17261
18000
  // ../../packages/plugin-sdk/src/repo.ts
17262
- import { existsSync as existsSync3, readFileSync as readFileSync3, statSync } from "fs";
17263
- import { basename, dirname, isAbsolute, join as join6, sep as sep2 } from "path";
18001
+ import { existsSync as existsSync4, readFileSync as readFileSync3, statSync } from "fs";
18002
+ import { basename, dirname, isAbsolute, join as join7, sep as sep2 } from "path";
17264
18003
 
17265
18004
  // ../../packages/plugin-sdk/src/events.ts
17266
- import { createHash as createHash3, randomUUID as randomUUID9 } from "crypto";
17267
-
17268
- // ../../packages/plugin-sdk/src/finding-key.ts
17269
- import { createHash as createHash4 } from "crypto";
18005
+ import { createHash as createHash4, randomUUID as randomUUID9 } from "crypto";
17270
18006
 
17271
18007
  // ../../packages/plugin-sdk/src/inventory-resolver.ts
17272
18008
  import { arch, hostname as hostname3, platform, release } from "os";
17273
18009
 
17274
18010
  // ../../packages/plugin-sdk/src/nudge.ts
17275
- import { mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
17276
- import { join as join8 } from "path";
18011
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
18012
+ import { join as join9 } from "path";
18013
+
18014
+ // ../../packages/plugin-sdk/src/paths.ts
18015
+ import { readdirSync as readdirSync2, realpathSync as realpathSync2 } from "fs";
18016
+ import { basename as basename3, dirname as dirname2, sep as sep3 } from "path";
17277
18017
 
17278
18018
  // ../../packages/plugin-sdk/src/project-files.ts
17279
18019
  var import_ignore = __toESM(require_ignore(), 1);
17280
- import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
17281
- import { basename as basename3, join as join9, relative, sep as sep3 } from "path";
18020
+ import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "fs";
18021
+ import { basename as basename4, join as join10, relative, sep as sep4 } from "path";
17282
18022
 
17283
18023
  // ../../packages/plugin-sdk/src/runtime.ts
17284
18024
  import { randomUUID as randomUUID10 } from "crypto";
@@ -17287,8 +18027,8 @@ import { randomUUID as randomUUID10 } from "crypto";
17287
18027
  var THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1e3;
17288
18028
 
17289
18029
  // ../../packages/plugin-sdk/src/throttle.ts
17290
- import { mkdirSync as mkdirSync4, statSync as statSync3, writeFileSync as writeFileSync5 } from "fs";
17291
- import { join as join10 } from "path";
18030
+ import { mkdirSync as mkdirSync3, statSync as statSync3, writeFileSync as writeFileSync4 } from "fs";
18031
+ import { join as join11 } from "path";
17292
18032
 
17293
18033
  // src/onboard-posture.ts
17294
18034
  function parsePosture(json2) {
@@ -17383,8 +18123,8 @@ function table(headers, rows, opts = {}) {
17383
18123
  const widths = headers.map(
17384
18124
  (h, i) => Math.max(visibleLength(h), ...rows.map((r) => visibleLength(r[i] ?? "")))
17385
18125
  );
17386
- const sep4 = " ".repeat(gap);
17387
- const fmt = (cells) => cells.map((cell, i) => padEnd(cell, widths[i] ?? 0)).join(sep4);
18126
+ const sep5 = " ".repeat(gap);
18127
+ const fmt = (cells) => cells.map((cell, i) => padEnd(cell, widths[i] ?? 0)).join(sep5);
17388
18128
  const headerLine = fmt(headers.map((h) => h.toUpperCase()));
17389
18129
  if (opts.rowSep === true) {
17390
18130
  const fullWidth = widths.reduce((n, w) => n + w, 0) + gap * Math.max(0, widths.length - 1);
@@ -17396,7 +18136,7 @@ function table(headers, rows, opts = {}) {
17396
18136
  });
17397
18137
  return [headerLine, rule, ...body].join("\n");
17398
18138
  }
17399
- const ruleLine = widths.map((w) => "\u2500".repeat(w)).join(sep4);
18139
+ const ruleLine = widths.map((w) => "\u2500".repeat(w)).join(sep5);
17400
18140
  return [headerLine, ruleLine, ...rows.map(fmt)].join("\n");
17401
18141
  }
17402
18142
  function fenced(body) {
@@ -17409,7 +18149,7 @@ function show(body) {
17409
18149
  }
17410
18150
 
17411
18151
  // src/command-registry.ts
17412
- import { readdirSync as readdirSync3 } from "fs";
18152
+ import { readdirSync as readdirSync4 } from "fs";
17413
18153
  import { fileURLToPath } from "url";
17414
18154
  var COMMANDS_DIR = fileURLToPath(new URL("../commands", import.meta.url));
17415
18155