@akasecurity/ai-tc-claude-code 0.8.1 → 0.9.0-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/scripts/stop.js CHANGED
@@ -547,6 +547,12 @@ var PRICE_MAP = {
547
547
  };
548
548
  var CANONICAL_ANTHROPIC_MODELS = Object.keys(ANTHROPIC_PRICES);
549
549
 
550
+ // ../../packages/schema/src/token/format.ts
551
+ var COMPACT = new Intl.NumberFormat("en-US", {
552
+ notation: "compact",
553
+ maximumFractionDigits: 1
554
+ });
555
+
550
556
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
551
557
  var external_exports = {};
552
558
  __export(external_exports, {
@@ -15125,6 +15131,12 @@ var FindingInstance = external_exports.object({
15125
15131
  provider: FindingProvider,
15126
15132
  repo: external_exports.string(),
15127
15133
  file: external_exports.string(),
15134
+ // Host tool that produced the scanned text (event metadata's toolName).
15135
+ // Present whenever the capturing hook recorded one — including
15136
+ // file-attributed captures (views prefer `file`); its display value is
15137
+ // the location fallback ("via Bash") when no filePath exists. Absent for
15138
+ // legacy rows and non-tool captures (prompts, worktree scans).
15139
+ toolName: external_exports.string().optional(),
15128
15140
  // Effective action: override.action ?? actionTaken, translated to FindingAction.
15129
15141
  action: FindingAction,
15130
15142
  detectedAt: external_exports.iso.datetime(),
@@ -15180,6 +15192,9 @@ var ListGroupedFindingsQuery = external_exports.object({
15180
15192
  provider: external_exports.array(FindingProvider).optional(),
15181
15193
  action: external_exports.array(FindingAction).optional(),
15182
15194
  q: external_exports.string().optional(),
15195
+ // Scope to findings whose event carries this session id (the Activity page's
15196
+ // session → findings drilldown). Findings without a session never match.
15197
+ sessionId: external_exports.string().optional(),
15183
15198
  groupBy: external_exports.literal("type").optional(),
15184
15199
  limit: external_exports.coerce.number().int().min(1).max(100).optional(),
15185
15200
  cursor: external_exports.string().optional()
@@ -15191,7 +15206,13 @@ var ListGroupedFindingsResponse = external_exports.object({
15191
15206
  }),
15192
15207
  facets: FindingFacets,
15193
15208
  items: external_exports.array(FindingGroup),
15194
- nextCursor: external_exports.string().nullable()
15209
+ nextCursor: external_exports.string().nullable(),
15210
+ // Present only on session-scoped queries (`sessionId` set): per ruleId, how
15211
+ // many times that rule fired in the session's persisted transcript. Findings
15212
+ // here are deduplicated to unique values while the transcript tally counts
15213
+ // every firing, so the two numbers legitimately differ — this map lets a
15214
+ // session-scoped view show both.
15215
+ sessionFirings: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()).optional()
15195
15216
  }).meta({ id: "ListGroupedFindingsResponse" });
15196
15217
  var ApplyFindingActionRequest = external_exports.object({
15197
15218
  // 'quarantined' is system-assigned (see FindingAction) — clients may not set
@@ -15233,6 +15254,11 @@ var AuditEventType = external_exports.enum([
15233
15254
  "prompt",
15234
15255
  "response",
15235
15256
  "code_change",
15257
+ // The events.kind of a scanned tool call, widened in to keep this a
15258
+ // superset. Narrower than 'tool_call' above and not a duplicate of it:
15259
+ // 'tool_call' is the reconciler's structural row for every call, while
15260
+ // 'tool_use' exists only where a hook enforced against the arguments.
15261
+ "tool_use",
15236
15262
  // One row per config-inventory scan, hung off the session root. It is the
15237
15263
  // fact the posture inspection findings reference (findings require an
15238
15264
  // audit_event_id), and its started_at is the "scanned Nm ago" the read
@@ -15584,6 +15610,10 @@ var ListActivitySessionsQuery = external_exports.object({
15584
15610
  from: external_exports.union([external_exports.iso.date(), external_exports.iso.datetime()]).optional(),
15585
15611
  /** Upper bound on startedAt; omitted defaults to now. */
15586
15612
  to: external_exports.union([external_exports.iso.date(), external_exports.iso.datetime()]).optional(),
15613
+ /** Exclude zero-activity sessions — roots whose only recorded children are
15614
+ * bookkeeping rows (hooks, config scans), typically background `claude`
15615
+ * launches. Omitted = list everything. `z.stringbool()` per the note above. */
15616
+ excludeEmpty: external_exports.stringbool().optional(),
15587
15617
  /** Page size, 1–100; out-of-range values are a 400. `z.coerce` — query params arrive as strings. */
15588
15618
  limit: external_exports.coerce.number().int().min(1).max(100).default(50),
15589
15619
  /** Opaque pagination cursor (most-recent first). */
@@ -15592,7 +15622,11 @@ var ListActivitySessionsQuery = external_exports.object({
15592
15622
  var ListActivitySessionsResponse = external_exports.object({
15593
15623
  items: external_exports.array(ActivitySessionSummary),
15594
15624
  /** `null` once the last page is reached. */
15595
- nextCursor: external_exports.string().nullable()
15625
+ nextCursor: external_exports.string().nullable(),
15626
+ /** Zero-activity sessions matching the query's filters/range (whether or
15627
+ * not `excludeEmpty` dropped them from `items`) — the count a UI toggle
15628
+ * shows when collapsing them. */
15629
+ emptyCount: external_exports.number().int().nonnegative()
15596
15630
  }).meta({ id: "ListActivitySessionsResponse" });
15597
15631
  var ListSessionEventsQuery = external_exports.object({
15598
15632
  /** Default 100, range 1–500. */
@@ -15621,12 +15655,18 @@ var ActivityOverviewResponse = external_exports.object({
15621
15655
  }).meta({ id: "ActivityOverviewResponse" });
15622
15656
 
15623
15657
  // ../../packages/schema/src/zod/event.ts
15624
- var EventKind = external_exports.enum(["prompt", "response", "code_change"]).meta({ id: "EventKind" });
15658
+ var EventKind = external_exports.enum(["prompt", "response", "code_change", "tool_use"]).meta({ id: "EventKind" });
15625
15659
  var SourceTool = external_exports.enum(["claude-code", "claude-desktop", "cursor", "chatgpt", "github-copilot", "cli", "unknown"]).meta({ id: "SourceTool" });
15626
15660
  var EventMetadata = external_exports.object({
15627
15661
  sessionId: external_exports.string().optional(),
15628
15662
  repo: external_exports.string().optional(),
15629
15663
  filePath: external_exports.string().optional(),
15664
+ // The host tool whose input/output was scanned (e.g. 'Bash', 'WebFetch'),
15665
+ // set by the tool-scanning hooks. The tool NAME only — never the tool's
15666
+ // arguments or output, which can carry the very value a finding masked
15667
+ // (metadata is stored unredacted). Gives findings on non-file captures a
15668
+ // display location ("via Bash") when no filePath exists.
15669
+ toolName: external_exports.string().optional(),
15630
15670
  // Set (true) by the worktree scanner when the file is excluded by the
15631
15671
  // repo's .gitignore. Gitignored files ARE still scanned — local scratch and
15632
15672
  // generated code can leak real secrets — but the provenance is recorded so
@@ -15934,7 +15974,7 @@ var DetectionException = external_exports.object({
15934
15974
  justification: external_exports.string().min(1),
15935
15975
  conditions: ExceptionConditions.nullable(),
15936
15976
  createdBy: external_exports.string(),
15937
- createdVia: external_exports.enum(["cli-approve", "cli-add", "web-approve", "web-add", "api"]),
15977
+ createdVia: external_exports.enum(["cli-approve", "cli-add", "web-approve", "web-add", "api", "setup-triage"]),
15938
15978
  createdAt: external_exports.iso.datetime(),
15939
15979
  updatedAt: external_exports.iso.datetime(),
15940
15980
  // Revocation is terminal and retained — consumed/expired/revoked rows are
@@ -15958,7 +15998,10 @@ var ExceptionBundleEntry = DetectionException.pick({
15958
15998
  var MatcherType = external_exports.enum(["keyword", "regex", "validator"]).meta({ id: "MatcherType" });
15959
15999
  var KeywordMatcher = external_exports.object({
15960
16000
  type: external_exports.literal("keyword"),
15961
- keywords: external_exports.array(external_exports.string()).min(1),
16001
+ // An empty keyword matches at every position, yielding one zero-length span
16002
+ // per character. Rejected here because a keyword that matches everything is
16003
+ // never intentional.
16004
+ keywords: external_exports.array(external_exports.string().min(1)).min(1),
15962
16005
  caseSensitive: external_exports.boolean().default(false)
15963
16006
  });
15964
16007
  function isValidRegex(pattern, flags) {
@@ -16105,6 +16148,24 @@ var PolicyBundle = external_exports.object({
16105
16148
  }).meta({ id: "PolicyBundle" });
16106
16149
  var OBSERVE_ONLY_CATEGORIES = ["config"];
16107
16150
  var ENFORCEABLE_CATEGORIES = DetectionCategory.options.filter((c) => !OBSERVE_ONLY_CATEGORIES.includes(c));
16151
+ var CATEGORY_PEAK_SEVERITY = {
16152
+ secret: "critical",
16153
+ financial: "critical",
16154
+ // core-financial/credit-card
16155
+ code_flaw: "critical",
16156
+ pii: "high",
16157
+ phi: "high",
16158
+ custom: "high",
16159
+ // user-defined; conservative
16160
+ code_context: "low",
16161
+ config: "low"
16162
+ // observe-only; floors to monitor regardless
16163
+ };
16164
+ function severityFloorPolicy(category) {
16165
+ if (OBSERVE_ONLY_CATEGORIES.includes(category)) return "monitor";
16166
+ const peak = CATEGORY_PEAK_SEVERITY[category];
16167
+ return peak === "critical" || peak === "high" ? "warn" : "monitor";
16168
+ }
16108
16169
  var PolicyKind = external_exports.enum(["builtin", "custom"]).meta({ id: "PolicyKind" });
16109
16170
  var KNOWN_BUILTIN_IDS = ["monitor", "warn", "redact", "block"];
16110
16171
  var BuiltinPolicyId = external_exports.enum(KNOWN_BUILTIN_IDS).meta({ id: "BuiltinPolicyId" });
@@ -16130,6 +16191,12 @@ var BUILTIN_POLICY_SPECS = {
16130
16191
  description: "Refuse the request entirely whenever any rule in this detection matches."
16131
16192
  }
16132
16193
  };
16194
+ function builtinPolicyToAction(id) {
16195
+ return BUILTIN_POLICY_SPECS[id].action;
16196
+ }
16197
+ var DEFAULT_ACTIONS = Object.fromEntries(
16198
+ DetectionCategory.options.map((c) => [c, builtinPolicyToAction(severityFloorPolicy(c))])
16199
+ );
16133
16200
  var BUILTIN_POLICIES = Object.fromEntries(
16134
16201
  KNOWN_BUILTIN_IDS.map((id) => [id, { id, ...BUILTIN_POLICY_SPECS[id] }])
16135
16202
  );
@@ -16176,6 +16243,10 @@ var ListEventsResponse = external_exports.object({
16176
16243
  items: external_exports.array(Event),
16177
16244
  nextCursor: external_exports.string().nullable()
16178
16245
  }).meta({ id: "ListEventsResponse" });
16246
+ var IngestResponse = external_exports.object({
16247
+ accepted: external_exports.number().int().nonnegative(),
16248
+ duplicates: external_exports.number().int().nonnegative()
16249
+ }).meta({ id: "IngestResponse" });
16179
16250
  var ListFindingsQuery = external_exports.object({
16180
16251
  cursor: external_exports.string().optional(),
16181
16252
  limit: external_exports.coerce.number().int().min(1).max(LIST_QUERY_MAX_LIMIT).default(50),
@@ -16499,6 +16570,65 @@ var ProjectFilesScan = external_exports.object({
16499
16570
  scannedAt: external_exports.string()
16500
16571
  });
16501
16572
 
16573
+ // ../../packages/schema/src/zod/ranges.ts
16574
+ var TIME_RANGES = ["7d", "30d", "3m", "6m"];
16575
+ var TimeRange = external_exports.enum(TIME_RANGES).meta({ id: "TimeRange" });
16576
+ var DEFAULT_TIME_RANGE = "7d";
16577
+ var TIME_RANGE_OR_DEFAULT = TimeRange.catch(DEFAULT_TIME_RANGE);
16578
+
16579
+ // ../../packages/schema/src/zod/remediation.ts
16580
+ var SecretFindingState = external_exports.enum(["still-valid", "unknown", "invalid"]);
16581
+ var MaskedFindingLocation = external_exports.object({
16582
+ filePath: external_exports.string(),
16583
+ span: Span.optional()
16584
+ }).strict();
16585
+ var MaskedSecretFinding = external_exports.object({
16586
+ provider: external_exports.string(),
16587
+ maskedToken: external_exports.string(),
16588
+ where: MaskedFindingLocation,
16589
+ state: SecretFindingState,
16590
+ observedAt: external_exports.iso.datetime().optional()
16591
+ }).strict();
16592
+ var RotationChecklistEntry = external_exports.object({
16593
+ provider: external_exports.string(),
16594
+ maskedToken: external_exports.string(),
16595
+ consolePath: external_exports.string(),
16596
+ occurrenceSpread: external_exports.number().int().positive()
16597
+ }).strict();
16598
+ var RemediationOption = external_exports.enum([
16599
+ "redact-rotation-checklist",
16600
+ "redact-only",
16601
+ "set-secret-redact",
16602
+ "leave"
16603
+ ]);
16604
+ var RemediationEntrySource = external_exports.enum(["first-run", "pre-push", "secret-scan"]);
16605
+ var RemediationEntryContext = external_exports.object({
16606
+ entrySource: RemediationEntrySource
16607
+ }).strict();
16608
+ var RemediationOptionChoice = external_exports.object({
16609
+ id: RemediationOption,
16610
+ label: external_exports.string()
16611
+ });
16612
+ var BatchedRemediationDecision = external_exports.object({
16613
+ kind: external_exports.literal("decision"),
16614
+ entrySource: RemediationEntrySource,
16615
+ secretCount: external_exports.number().int().positive(),
16616
+ prompt: external_exports.string(),
16617
+ options: external_exports.tuple([
16618
+ RemediationOptionChoice.extend({ id: external_exports.literal("redact-rotation-checklist") }),
16619
+ RemediationOptionChoice.extend({ id: external_exports.literal("redact-only") }),
16620
+ RemediationOptionChoice.extend({ id: external_exports.literal("set-secret-redact") }),
16621
+ RemediationOptionChoice.extend({ id: external_exports.literal("leave") })
16622
+ ])
16623
+ });
16624
+ var NoRemediationDecision = external_exports.object({
16625
+ kind: external_exports.literal("no-decision")
16626
+ });
16627
+ var BatchedRemediation = external_exports.discriminatedUnion("kind", [
16628
+ BatchedRemediationDecision,
16629
+ NoRemediationDecision
16630
+ ]);
16631
+
16502
16632
  // ../../packages/schema/src/zod/rule-test.ts
16503
16633
  var TestRulesRequest = external_exports.object({
16504
16634
  rules: external_exports.array(Rule).min(1).max(100),
@@ -16557,10 +16687,8 @@ var SeveritySummaryResponse = external_exports.object({
16557
16687
  // All four severity levels are always present (count may be 0).
16558
16688
  bySeverity: external_exports.array(SeveritySummaryItem)
16559
16689
  }).meta({ id: "SeveritySummaryResponse" });
16560
- var SECURITY_RANGES = ["7d", "30d", "3m", "6m"];
16561
- var SecurityRange = external_exports.enum(SECURITY_RANGES).meta({ id: "SecurityRange" });
16562
16690
  var SecurityRangeQuery = external_exports.object({
16563
- range: external_exports.enum(SECURITY_RANGES).default("30d")
16691
+ range: external_exports.enum(TIME_RANGES).default(DEFAULT_TIME_RANGE)
16564
16692
  });
16565
16693
  var EnforcementActionKind = external_exports.enum(["blocked", "redacted", "warned"]).meta({ id: "EnforcementActionKind" });
16566
16694
  var EnforcementAction = external_exports.object({
@@ -16570,7 +16698,7 @@ var EnforcementAction = external_exports.object({
16570
16698
  delta: external_exports.number().int()
16571
16699
  }).meta({ id: "EnforcementAction" });
16572
16700
  var EnforcementActionsResponse = external_exports.object({
16573
- range: SecurityRange,
16701
+ range: TimeRange,
16574
16702
  // Sum of actions[].count in the window.
16575
16703
  total: external_exports.number().int().nonnegative(),
16576
16704
  // One entry per kind, always all three present (count may be 0).
@@ -16585,7 +16713,7 @@ var FindingsTimeseriesPoint = external_exports.object({
16585
16713
  medium: external_exports.number().int().nonnegative()
16586
16714
  }).meta({ id: "FindingsTimeseriesPoint" });
16587
16715
  var FindingsTimeseriesResponse = external_exports.object({
16588
- range: SecurityRange,
16716
+ range: TimeRange,
16589
16717
  granularity: TimeseriesGranularity,
16590
16718
  points: external_exports.array(FindingsTimeseriesPoint)
16591
16719
  }).meta({ id: "FindingsTimeseriesResponse" });
@@ -16600,7 +16728,7 @@ var MttrTrendPoint = external_exports.object({
16600
16728
  })
16601
16729
  }).meta({ id: "MttrTrendPoint" });
16602
16730
  var MttrTrendResponse = external_exports.object({
16603
- range: SecurityRange,
16731
+ range: TimeRange,
16604
16732
  granularity: TimeseriesGranularity,
16605
16733
  points: external_exports.array(MttrTrendPoint)
16606
16734
  }).meta({ id: "MttrTrendResponse" });
@@ -16627,11 +16755,11 @@ var TopSource = external_exports.object({
16627
16755
  findingsCount: external_exports.number().int().nonnegative()
16628
16756
  }).meta({ id: "TopSource" });
16629
16757
  var TopSourcesResponse = external_exports.object({
16630
- range: SecurityRange,
16758
+ range: TimeRange,
16631
16759
  items: external_exports.array(TopSource)
16632
16760
  }).meta({ id: "TopSourcesResponse" });
16633
16761
  var TopSourcesQuery = external_exports.object({
16634
- range: external_exports.enum(SECURITY_RANGES).default("30d"),
16762
+ range: external_exports.enum(TIME_RANGES).default(DEFAULT_TIME_RANGE),
16635
16763
  limit: external_exports.coerce.number().int().min(1).max(50).default(5),
16636
16764
  // Omit for both kinds.
16637
16765
  kind: external_exports.enum(SOURCE_KINDS).optional()
@@ -16644,7 +16772,7 @@ var ScanCoverageProvider = external_exports.object({
16644
16772
  supported: external_exports.boolean()
16645
16773
  }).meta({ id: "ScanCoverageProvider" });
16646
16774
  var ScanCoverageResponse = external_exports.object({
16647
- range: SecurityRange,
16775
+ range: TimeRange,
16648
16776
  providers: external_exports.array(ScanCoverageProvider)
16649
16777
  }).meta({ id: "ScanCoverageResponse" });
16650
16778
  var SubjectType = external_exports.enum(["repo", "user", "team", "policy", "share", "rule"]).meta({
@@ -16693,6 +16821,114 @@ var ApplyRecommendedActionResponse = external_exports.object({
16693
16821
  var DismissRecommendedActionResponse = external_exports.object({ id: external_exports.string(), status: external_exports.literal("dismissed") }).meta({ id: "DismissRecommendedActionResponse" });
16694
16822
  var RecommendedActionIdParam = external_exports.object({ id: external_exports.string() });
16695
16823
 
16824
+ // ../../packages/schema/src/zod/triage.ts
16825
+ var TriageHit = external_exports.object({
16826
+ ruleId: external_exports.string(),
16827
+ category: DetectionCategory,
16828
+ severity: Severity,
16829
+ maskedMatch: external_exports.string(),
16830
+ rawMatch: external_exports.string(),
16831
+ context: external_exports.string(),
16832
+ filePath: external_exports.string().optional(),
16833
+ confidence: external_exports.number().min(0).max(1),
16834
+ id: external_exports.string().optional(),
16835
+ valueFingerprint: external_exports.string().optional(),
16836
+ keyVersion: external_exports.number().int().nonnegative().optional()
16837
+ });
16838
+ var TriagePolicy = BuiltinPolicyId;
16839
+ var TriageCategoryRec = external_exports.object({
16840
+ category: DetectionCategory,
16841
+ action: TriagePolicy,
16842
+ reasoning: external_exports.string(),
16843
+ genuineCount: external_exports.number().int().nonnegative(),
16844
+ fpCount: external_exports.number().int().nonnegative(),
16845
+ // TriageHit ids judged false-positive in this category. fpCount must equal
16846
+ // this array's length — enforced by the consumer, not this schema.
16847
+ fpIds: external_exports.array(external_exports.string())
16848
+ });
16849
+ var TriageRecommendation = external_exports.object({
16850
+ perCategory: external_exports.array(TriageCategoryRec),
16851
+ notes: external_exports.string()
16852
+ });
16853
+
16854
+ // ../../packages/schema/src/zod/setup-frame.ts
16855
+ var CalibrationCounts = external_exports.object({
16856
+ total: external_exports.number().int().nonnegative(),
16857
+ important: external_exports.number().int().nonnegative(),
16858
+ routine: external_exports.number().int().nonnegative()
16859
+ }).refine((c) => c.total === c.important + c.routine, {
16860
+ message: "total must equal important + routine",
16861
+ path: ["total"]
16862
+ });
16863
+ var FalsePositivePatternValue = external_exports.object({
16864
+ ruleId: external_exports.string(),
16865
+ category: DetectionCategory,
16866
+ valueFingerprint: external_exports.string(),
16867
+ keyVersion: external_exports.number().int().nonnegative()
16868
+ });
16869
+ var FalsePositivePatternGroup = external_exports.object({
16870
+ pattern: external_exports.string(),
16871
+ count: external_exports.number().int().nonnegative(),
16872
+ values: external_exports.array(FalsePositivePatternValue).min(1)
16873
+ });
16874
+ var CalibrationFindingKind = external_exports.object({
16875
+ category: DetectionCategory,
16876
+ count: external_exports.number().int().nonnegative(),
16877
+ egress: external_exports.boolean()
16878
+ });
16879
+ var CalibrationFrame = external_exports.object({
16880
+ counts: CalibrationCounts,
16881
+ routineCategories: external_exports.array(DetectionCategory),
16882
+ surfacedCategories: external_exports.array(DetectionCategory),
16883
+ findingKinds: external_exports.array(CalibrationFindingKind),
16884
+ posture: external_exports.record(DetectionCategory, BuiltinPolicyId),
16885
+ maskedFindings: external_exports.array(MaskedSecretFinding).optional(),
16886
+ falsePositivePatterns: external_exports.array(FalsePositivePatternGroup).optional()
16887
+ });
16888
+ var CalibrationPreviewCategory = TriageCategoryRec.pick({
16889
+ category: true,
16890
+ genuineCount: true,
16891
+ fpCount: true
16892
+ }).extend({
16893
+ egress: external_exports.boolean()
16894
+ });
16895
+ var CalibrationPreview = external_exports.object({
16896
+ categories: external_exports.array(CalibrationPreviewCategory),
16897
+ posture: external_exports.record(DetectionCategory, BuiltinPolicyId)
16898
+ });
16899
+ var CalibrationResult = external_exports.object({
16900
+ frame: CalibrationFrame,
16901
+ copy: external_exports.string()
16902
+ });
16903
+ var FirstRunCalibration = external_exports.enum(["scan", "floor"]);
16904
+ var SetupHandoffOption = external_exports.object({
16905
+ id: external_exports.enum(["enter-remediation", "open-dashboard", "not-now"]),
16906
+ label: external_exports.string()
16907
+ });
16908
+ var DashboardHandoffOptions = external_exports.tuple([
16909
+ SetupHandoffOption.extend({ id: external_exports.literal("open-dashboard") }),
16910
+ SetupHandoffOption.extend({ id: external_exports.literal("not-now") })
16911
+ ]);
16912
+ var ComposedRemediationOptions = external_exports.tuple([
16913
+ SetupHandoffOption.extend({ id: external_exports.literal("enter-remediation") }),
16914
+ SetupHandoffOption.extend({ id: external_exports.literal("open-dashboard") }),
16915
+ SetupHandoffOption.extend({ id: external_exports.literal("not-now") })
16916
+ ]);
16917
+ var SetupHandoffOffer = external_exports.object({
16918
+ worthALook: external_exports.number().int().nonnegative(),
16919
+ liveKeys: external_exports.number().int().nonnegative().optional(),
16920
+ options: external_exports.union([DashboardHandoffOptions, ComposedRemediationOptions])
16921
+ }).refine(
16922
+ (o) => o.options.some((opt) => opt.id === "enter-remediation") === (o.liveKeys ?? 0) > 0,
16923
+ {
16924
+ message: "the chain-entry option is present exactly when liveKeys > 0",
16925
+ path: ["options"]
16926
+ }
16927
+ ).refine((o) => (o.liveKeys ?? 0) <= o.worthALook, {
16928
+ message: "liveKeys is a subset of worthALook and cannot exceed it",
16929
+ path: ["liveKeys"]
16930
+ });
16931
+
16696
16932
  // ../../packages/schema/src/zod/shares.ts
16697
16933
  var DestinationKind = external_exports.enum(["provider", "internal", "ip"]).meta({ id: "DestinationKind" });
16698
16934
  var Transport = external_exports.enum(["https", "http", "sftp", "grpc", "smtp"]).meta({ id: "Transport" });
@@ -16840,6 +17076,17 @@ import { chmodSync, mkdirSync } from "fs";
16840
17076
  var DATA_DIR_MODE = 448;
16841
17077
  var DATA_FILE_MODE = 384;
16842
17078
 
17079
+ // ../../packages/persistence/src/internal/json.ts
17080
+ function parseJsonObject(s) {
17081
+ if (s == null) return void 0;
17082
+ try {
17083
+ const parsed = JSON.parse(s);
17084
+ if (typeof parsed === "object" && parsed !== null) return parsed;
17085
+ } catch {
17086
+ }
17087
+ return void 0;
17088
+ }
17089
+
16843
17090
  // ../../packages/persistence/src/repositories/activity.ts
16844
17091
  var LIVE_ACTIVITY_WINDOW_MS = 30 * 6e4;
16845
17092
 
@@ -16921,14 +17168,19 @@ function readWorkspaceSettings(base = defaultDataDir()) {
16921
17168
  }
16922
17169
  }
16923
17170
  function readJson(file2) {
17171
+ let text;
16924
17172
  try {
16925
- const parsed = JSON.parse(readFileSync2(file2, "utf8"));
16926
- return typeof parsed === "object" && parsed !== null ? parsed : null;
17173
+ text = readFileSync2(file2, "utf8");
16927
17174
  } catch {
16928
17175
  return null;
16929
17176
  }
17177
+ return parseJsonObject(text) ?? null;
16930
17178
  }
16931
17179
 
17180
+ // ../../packages/persistence/src/warn-era-cap.ts
17181
+ import { existsSync as existsSync2, writeFileSync as writeFileSync3 } from "fs";
17182
+ import { join as join5 } from "path";
17183
+
16932
17184
  // ../../packages/plugin-sdk/src/provider-env.ts
16933
17185
  var DEFAULT_ANTHROPIC_HOST = "api.anthropic.com";
16934
17186
  var booleanish = external_exports.string().optional().transform((v) => {
@@ -17001,23 +17253,30 @@ function resolveProviderSafe() {
17001
17253
  // ../../packages/plugin-sdk/src/config-inventory.ts
17002
17254
  import { readdirSync, readFileSync as readFileSync4, realpathSync, statSync as statSync2 } from "fs";
17003
17255
  import { homedir as homedir2 } from "os";
17004
- import { basename as basename2, join as join6 } from "path";
17256
+ import { basename as basename2, join as join7 } from "path";
17257
+
17258
+ // ../../packages/detections/src/escape-regexp.ts
17259
+ function escapeRegExp(value) {
17260
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
17261
+ }
17262
+
17263
+ // ../../packages/detections/src/matchers/limits.ts
17264
+ var MAX_MATCHES_PER_RULE = 1e4;
17005
17265
 
17006
17266
  // ../../packages/detections/src/matchers/keyword.ts
17007
17267
  var KeywordMatcher2 = class {
17008
17268
  match(text, rule) {
17009
17269
  if (rule.matcher.type !== "keyword") return [];
17010
17270
  const { keywords, caseSensitive } = rule.matcher;
17011
- const haystack = caseSensitive ? text : text.toLowerCase();
17012
17271
  const spans = [];
17013
17272
  for (const kw of keywords) {
17014
- const needle = caseSensitive ? kw : kw.toLowerCase();
17015
- let idx = 0;
17016
- while (idx < haystack.length) {
17017
- const pos = haystack.indexOf(needle, idx);
17018
- if (pos === -1) break;
17019
- spans.push({ start: pos, end: pos + kw.length });
17020
- idx = pos + 1;
17273
+ if (kw.length === 0) continue;
17274
+ if (spans.length >= MAX_MATCHES_PER_RULE) break;
17275
+ const re = new RegExp(escapeRegExp(kw), caseSensitive ? "gu" : "giu");
17276
+ let m;
17277
+ while ((m = re.exec(text)) !== null) {
17278
+ spans.push({ start: m.index, end: m.index + m[0].length });
17279
+ if (spans.length >= MAX_MATCHES_PER_RULE) break;
17021
17280
  }
17022
17281
  }
17023
17282
  return spans;
@@ -17025,7 +17284,6 @@ var KeywordMatcher2 = class {
17025
17284
  };
17026
17285
 
17027
17286
  // ../../packages/detections/src/matchers/regex.ts
17028
- var MAX_MATCHES_PER_RULE = 1e4;
17029
17287
  var RegexMatcher2 = class {
17030
17288
  match(text, rule) {
17031
17289
  if (rule.matcher.type !== "regex") return [];
@@ -17109,8 +17367,8 @@ var CONFIG_POSTURE_RULES = [
17109
17367
  ];
17110
17368
 
17111
17369
  // ../../packages/plugin-sdk/src/repo.ts
17112
- import { existsSync as existsSync2, readFileSync as readFileSync3, statSync } from "fs";
17113
- import { basename, dirname, isAbsolute, join as join5, sep as sep2 } from "path";
17370
+ import { existsSync as existsSync3, readFileSync as readFileSync3, statSync } from "fs";
17371
+ import { basename, dirname, isAbsolute, join as join6, sep as sep2 } from "path";
17114
17372
 
17115
17373
  // ../../packages/plugin-sdk/src/events.ts
17116
17374
  import { createHash as createHash3, randomUUID as randomUUID9 } from "crypto";
@@ -17122,29 +17380,32 @@ import { createHash as createHash4 } from "crypto";
17122
17380
  import { arch, hostname as hostname3, platform, release } from "os";
17123
17381
 
17124
17382
  // ../../packages/plugin-sdk/src/nudge.ts
17125
- import { mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
17126
- import { join as join7 } from "path";
17383
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
17384
+ import { join as join8 } from "path";
17127
17385
 
17128
17386
  // ../../packages/plugin-sdk/src/project-files.ts
17129
17387
  var import_ignore = __toESM(require_ignore(), 1);
17130
- import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
17131
- import { basename as basename3, join as join8, relative, sep as sep3 } from "path";
17388
+ import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
17389
+ import { basename as basename3, join as join9, relative, sep as sep3 } from "path";
17132
17390
 
17133
17391
  // ../../packages/plugin-sdk/src/runtime.ts
17134
17392
  import { randomUUID as randomUUID10 } from "crypto";
17135
17393
 
17394
+ // ../../packages/plugin-sdk/src/suppressions.ts
17395
+ var THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1e3;
17396
+
17136
17397
  // ../../packages/plugin-sdk/src/throttle.ts
17137
- import { mkdirSync as mkdirSync4, statSync as statSync3, writeFileSync as writeFileSync4 } from "fs";
17138
- import { join as join9 } from "path";
17398
+ import { mkdirSync as mkdirSync4, statSync as statSync3, writeFileSync as writeFileSync5 } from "fs";
17399
+ import { join as join10 } from "path";
17139
17400
  function throttled(dataDir2, markerName, windowMs) {
17140
- const marker = join9(dataDir2, markerName);
17401
+ const marker = join10(dataDir2, markerName);
17141
17402
  try {
17142
17403
  if (Date.now() - statSync3(marker).mtimeMs < windowMs) return true;
17143
17404
  } catch {
17144
17405
  }
17145
17406
  try {
17146
17407
  mkdirSync4(dataDir2, { recursive: true, mode: DATA_DIR_MODE });
17147
- writeFileSync4(marker, String(Date.now()), { mode: DATA_FILE_MODE });
17408
+ writeFileSync5(marker, String(Date.now()), { mode: DATA_FILE_MODE });
17148
17409
  } catch {
17149
17410
  }
17150
17411
  return false;
@@ -17152,7 +17413,7 @@ function throttled(dataDir2, markerName, windowMs) {
17152
17413
 
17153
17414
  // src/history/reconcile-trigger.ts
17154
17415
  import { spawn } from "child_process";
17155
- import { dirname as dirname2, join as join11 } from "path";
17416
+ import { dirname as dirname2, join as join12 } from "path";
17156
17417
  import { fileURLToPath } from "url";
17157
17418
 
17158
17419
  // src/history/tail.ts
@@ -17164,9 +17425,9 @@ import {
17164
17425
  openSync,
17165
17426
  readFileSync as readFileSync7,
17166
17427
  readSync,
17167
- writeFileSync as writeFileSync5
17428
+ writeFileSync as writeFileSync6
17168
17429
  } from "fs";
17169
- import { join as join10 } from "path";
17430
+ import { join as join11 } from "path";
17170
17431
  var SAFE_SESSION_ID = /^[A-Za-z0-9._-]+$/;
17171
17432
  function safeSessionId(sessionId) {
17172
17433
  if (SAFE_SESSION_ID.test(sessionId) && sessionId !== "." && sessionId !== "..") {
@@ -17183,7 +17444,7 @@ function triggerReconcile(dataDir2, sessionId, transcriptPath) {
17183
17444
  const marker = `${RECONCILE_MARKER_PREFIX}-${safeSessionId(sessionId)}`;
17184
17445
  if (throttled(dataDir2, marker, RECONCILE_THROTTLE_MS)) return;
17185
17446
  const here = dirname2(fileURLToPath(import.meta.url));
17186
- const child = spawn(process.execPath, [join11(here, "reconcile.js"), sessionId, transcriptPath], {
17447
+ const child = spawn(process.execPath, [join12(here, "reconcile.js"), sessionId, transcriptPath], {
17187
17448
  detached: true,
17188
17449
  stdio: "ignore"
17189
17450
  });