@akasecurity/ai-tc-claude-code 0.9.6 → 0.9.7

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.
@@ -711,6 +711,10 @@ function luhnCheck(digits) {
711
711
  // ../../packages/detections/src/engine.ts
712
712
  var keywordMatcher = new KeywordMatcher();
713
713
  var regexMatcher = new RegexMatcher();
714
+ var MATCHERS = {
715
+ keyword: (text, rule) => keywordMatcher.match(text, rule),
716
+ regex: (text, rule) => regexMatcher.match(text, rule)
717
+ };
714
718
  var packs = /* @__PURE__ */ new Map();
715
719
  var POST_VALIDATORS = {
716
720
  entropy: (value, config2) => isHighEntropy(value, numberOption(config2, "threshold"), numberOption(config2, "minLength")),
@@ -726,8 +730,7 @@ function passesPostValidators(rule, value) {
726
730
  for (const ref of validators) {
727
731
  const name = typeof ref === "string" ? ref : ref.name;
728
732
  const config2 = typeof ref === "string" ? void 0 : ref.config;
729
- const validate = POST_VALIDATORS[name];
730
- if (validate && !validate(value, config2)) return false;
733
+ if (!POST_VALIDATORS[name](value, config2)) return false;
731
734
  }
732
735
  return true;
733
736
  }
@@ -785,14 +788,7 @@ function scan(text, rules, context) {
785
788
  const candidates = [];
786
789
  for (const rule of ruleset2) {
787
790
  if (!ruleApplies(rule, extension)) continue;
788
- let spans;
789
- if (rule.matcher.type === "keyword") {
790
- spans = keywordMatcher.match(text, rule);
791
- } else if (rule.matcher.type === "regex") {
792
- spans = regexMatcher.match(text, rule);
793
- } else {
794
- continue;
795
- }
791
+ const spans = MATCHERS[rule.matcher.type](text, rule);
796
792
  for (const span of spans) {
797
793
  const rawMatch = text.slice(span.start, span.end);
798
794
  if (!passesPostValidators(rule, rawMatch)) continue;
@@ -1387,7 +1383,7 @@ __export(core_exports2, {
1387
1383
  parse: () => parse,
1388
1384
  parseAsync: () => parseAsync,
1389
1385
  prettifyError: () => prettifyError,
1390
- process: () => process,
1386
+ process: () => process2,
1391
1387
  regexes: () => regexes_exports,
1392
1388
  registry: () => registry,
1393
1389
  safeDecode: () => safeDecode,
@@ -12312,7 +12308,7 @@ function initializeContext(params) {
12312
12308
  external: params?.external ?? void 0
12313
12309
  };
12314
12310
  }
12315
- function process(schema, ctx, _params = { path: [], schemaPath: [] }) {
12311
+ function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
12316
12312
  var _a3;
12317
12313
  const def = schema._zod.def;
12318
12314
  const seen = ctx.seen.get(schema);
@@ -12349,7 +12345,7 @@ function process(schema, ctx, _params = { path: [], schemaPath: [] }) {
12349
12345
  if (parent) {
12350
12346
  if (!result.ref)
12351
12347
  result.ref = parent;
12352
- process(parent, ctx, params);
12348
+ process2(parent, ctx, params);
12353
12349
  ctx.seen.get(parent).isParent = true;
12354
12350
  }
12355
12351
  }
@@ -12637,14 +12633,14 @@ function isTransforming(_schema, _ctx) {
12637
12633
  }
12638
12634
  var createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
12639
12635
  const ctx = initializeContext({ ...params, processors });
12640
- process(schema, ctx);
12636
+ process2(schema, ctx);
12641
12637
  extractDefs(ctx, schema);
12642
12638
  return finalize(ctx, schema);
12643
12639
  };
12644
12640
  var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
12645
12641
  const { libraryOptions, target } = params ?? {};
12646
12642
  const ctx = initializeContext({ ...libraryOptions ?? {}, target, io, processors });
12647
- process(schema, ctx);
12643
+ process2(schema, ctx);
12648
12644
  extractDefs(ctx, schema);
12649
12645
  return finalize(ctx, schema);
12650
12646
  };
@@ -12890,7 +12886,7 @@ var arrayProcessor = (schema, ctx, _json, params) => {
12890
12886
  if (typeof maximum === "number")
12891
12887
  json2.maxItems = maximum;
12892
12888
  json2.type = "array";
12893
- json2.items = process(def.element, ctx, {
12889
+ json2.items = process2(def.element, ctx, {
12894
12890
  ...params,
12895
12891
  path: [...params.path, "items"]
12896
12892
  });
@@ -12902,7 +12898,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
12902
12898
  json2.properties = {};
12903
12899
  const shape = def.shape;
12904
12900
  for (const key in shape) {
12905
- json2.properties[key] = process(shape[key], ctx, {
12901
+ json2.properties[key] = process2(shape[key], ctx, {
12906
12902
  ...params,
12907
12903
  path: [...params.path, "properties", key]
12908
12904
  });
@@ -12925,7 +12921,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
12925
12921
  if (ctx.io === "output")
12926
12922
  json2.additionalProperties = false;
12927
12923
  } else if (def.catchall) {
12928
- json2.additionalProperties = process(def.catchall, ctx, {
12924
+ json2.additionalProperties = process2(def.catchall, ctx, {
12929
12925
  ...params,
12930
12926
  path: [...params.path, "additionalProperties"]
12931
12927
  });
@@ -12934,7 +12930,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
12934
12930
  var unionProcessor = (schema, ctx, json2, params) => {
12935
12931
  const def = schema._zod.def;
12936
12932
  const isExclusive = def.inclusive === false;
12937
- const options = def.options.map((x, i) => process(x, ctx, {
12933
+ const options = def.options.map((x, i) => process2(x, ctx, {
12938
12934
  ...params,
12939
12935
  path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
12940
12936
  }));
@@ -12946,11 +12942,11 @@ var unionProcessor = (schema, ctx, json2, params) => {
12946
12942
  };
12947
12943
  var intersectionProcessor = (schema, ctx, json2, params) => {
12948
12944
  const def = schema._zod.def;
12949
- const a = process(def.left, ctx, {
12945
+ const a = process2(def.left, ctx, {
12950
12946
  ...params,
12951
12947
  path: [...params.path, "allOf", 0]
12952
12948
  });
12953
- const b = process(def.right, ctx, {
12949
+ const b = process2(def.right, ctx, {
12954
12950
  ...params,
12955
12951
  path: [...params.path, "allOf", 1]
12956
12952
  });
@@ -12967,11 +12963,11 @@ var tupleProcessor = (schema, ctx, _json, params) => {
12967
12963
  json2.type = "array";
12968
12964
  const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
12969
12965
  const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
12970
- const prefixItems = def.items.map((x, i) => process(x, ctx, {
12966
+ const prefixItems = def.items.map((x, i) => process2(x, ctx, {
12971
12967
  ...params,
12972
12968
  path: [...params.path, prefixPath, i]
12973
12969
  }));
12974
- const rest = def.rest ? process(def.rest, ctx, {
12970
+ const rest = def.rest ? process2(def.rest, ctx, {
12975
12971
  ...params,
12976
12972
  path: [...params.path, restPath, ...ctx.target === "openapi-3.0" ? [def.items.length] : []]
12977
12973
  }) : null;
@@ -13011,7 +13007,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
13011
13007
  const keyBag = keyType._zod.bag;
13012
13008
  const patterns = keyBag?.patterns;
13013
13009
  if (def.mode === "loose" && patterns && patterns.size > 0) {
13014
- const valueSchema = process(def.valueType, ctx, {
13010
+ const valueSchema = process2(def.valueType, ctx, {
13015
13011
  ...params,
13016
13012
  path: [...params.path, "patternProperties", "*"]
13017
13013
  });
@@ -13021,12 +13017,12 @@ var recordProcessor = (schema, ctx, _json, params) => {
13021
13017
  }
13022
13018
  } else {
13023
13019
  if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
13024
- json2.propertyNames = process(def.keyType, ctx, {
13020
+ json2.propertyNames = process2(def.keyType, ctx, {
13025
13021
  ...params,
13026
13022
  path: [...params.path, "propertyNames"]
13027
13023
  });
13028
13024
  }
13029
- json2.additionalProperties = process(def.valueType, ctx, {
13025
+ json2.additionalProperties = process2(def.valueType, ctx, {
13030
13026
  ...params,
13031
13027
  path: [...params.path, "additionalProperties"]
13032
13028
  });
@@ -13041,7 +13037,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
13041
13037
  };
13042
13038
  var nullableProcessor = (schema, ctx, json2, params) => {
13043
13039
  const def = schema._zod.def;
13044
- const inner = process(def.innerType, ctx, params);
13040
+ const inner = process2(def.innerType, ctx, params);
13045
13041
  const seen = ctx.seen.get(schema);
13046
13042
  if (ctx.target === "openapi-3.0") {
13047
13043
  seen.ref = def.innerType;
@@ -13052,20 +13048,20 @@ var nullableProcessor = (schema, ctx, json2, params) => {
13052
13048
  };
13053
13049
  var nonoptionalProcessor = (schema, ctx, _json, params) => {
13054
13050
  const def = schema._zod.def;
13055
- process(def.innerType, ctx, params);
13051
+ process2(def.innerType, ctx, params);
13056
13052
  const seen = ctx.seen.get(schema);
13057
13053
  seen.ref = def.innerType;
13058
13054
  };
13059
13055
  var defaultProcessor = (schema, ctx, json2, params) => {
13060
13056
  const def = schema._zod.def;
13061
- process(def.innerType, ctx, params);
13057
+ process2(def.innerType, ctx, params);
13062
13058
  const seen = ctx.seen.get(schema);
13063
13059
  seen.ref = def.innerType;
13064
13060
  json2.default = JSON.parse(JSON.stringify(def.defaultValue));
13065
13061
  };
13066
13062
  var prefaultProcessor = (schema, ctx, json2, params) => {
13067
13063
  const def = schema._zod.def;
13068
- process(def.innerType, ctx, params);
13064
+ process2(def.innerType, ctx, params);
13069
13065
  const seen = ctx.seen.get(schema);
13070
13066
  seen.ref = def.innerType;
13071
13067
  if (ctx.io === "input")
@@ -13073,7 +13069,7 @@ var prefaultProcessor = (schema, ctx, json2, params) => {
13073
13069
  };
13074
13070
  var catchProcessor = (schema, ctx, json2, params) => {
13075
13071
  const def = schema._zod.def;
13076
- process(def.innerType, ctx, params);
13072
+ process2(def.innerType, ctx, params);
13077
13073
  const seen = ctx.seen.get(schema);
13078
13074
  seen.ref = def.innerType;
13079
13075
  let catchValue;
@@ -13088,32 +13084,32 @@ var pipeProcessor = (schema, ctx, _json, params) => {
13088
13084
  const def = schema._zod.def;
13089
13085
  const inIsTransform = def.in._zod.traits.has("$ZodTransform");
13090
13086
  const innerType = ctx.io === "input" ? inIsTransform ? def.out : def.in : def.out;
13091
- process(innerType, ctx, params);
13087
+ process2(innerType, ctx, params);
13092
13088
  const seen = ctx.seen.get(schema);
13093
13089
  seen.ref = innerType;
13094
13090
  };
13095
13091
  var readonlyProcessor = (schema, ctx, json2, params) => {
13096
13092
  const def = schema._zod.def;
13097
- process(def.innerType, ctx, params);
13093
+ process2(def.innerType, ctx, params);
13098
13094
  const seen = ctx.seen.get(schema);
13099
13095
  seen.ref = def.innerType;
13100
13096
  json2.readOnly = true;
13101
13097
  };
13102
13098
  var promiseProcessor = (schema, ctx, _json, params) => {
13103
13099
  const def = schema._zod.def;
13104
- process(def.innerType, ctx, params);
13100
+ process2(def.innerType, ctx, params);
13105
13101
  const seen = ctx.seen.get(schema);
13106
13102
  seen.ref = def.innerType;
13107
13103
  };
13108
13104
  var optionalProcessor = (schema, ctx, _json, params) => {
13109
13105
  const def = schema._zod.def;
13110
- process(def.innerType, ctx, params);
13106
+ process2(def.innerType, ctx, params);
13111
13107
  const seen = ctx.seen.get(schema);
13112
13108
  seen.ref = def.innerType;
13113
13109
  };
13114
13110
  var lazyProcessor = (schema, ctx, _json, params) => {
13115
13111
  const innerType = schema._zod.innerType;
13116
- process(innerType, ctx, params);
13112
+ process2(innerType, ctx, params);
13117
13113
  const seen = ctx.seen.get(schema);
13118
13114
  seen.ref = innerType;
13119
13115
  };
@@ -13165,7 +13161,7 @@ function toJSONSchema(input, params) {
13165
13161
  const defs = {};
13166
13162
  for (const entry of registry2._idmap.entries()) {
13167
13163
  const [_, schema] = entry;
13168
- process(schema, ctx2);
13164
+ process2(schema, ctx2);
13169
13165
  }
13170
13166
  const schemas = {};
13171
13167
  const external = {
@@ -13188,7 +13184,7 @@ function toJSONSchema(input, params) {
13188
13184
  return { schemas };
13189
13185
  }
13190
13186
  const ctx = initializeContext({ ...params, processors: allProcessors });
13191
- process(input, ctx);
13187
+ process2(input, ctx);
13192
13188
  extractDefs(ctx, input);
13193
13189
  return finalize(ctx, input);
13194
13190
  }
@@ -13246,7 +13242,7 @@ var JSONSchemaGenerator = class {
13246
13242
  * This must be called before emit().
13247
13243
  */
13248
13244
  process(schema, _params = { path: [], schemaPath: [] }) {
13249
- return process(schema, this.ctx, _params);
13245
+ return process2(schema, this.ctx, _params);
13250
13246
  }
13251
13247
  /**
13252
13248
  * Emit the final JSON Schema after processing.
@@ -15395,6 +15391,47 @@ function date4(params) {
15395
15391
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
15396
15392
  config(en_default());
15397
15393
 
15394
+ // ../../packages/schema/src/zod/harness-map.ts
15395
+ var HARNESS = {
15396
+ ClaudeCode: "claudecode",
15397
+ Cursor: "cursor",
15398
+ Copilot: "copilot",
15399
+ Codex: "codex",
15400
+ Antigravity: "antigravity",
15401
+ Windsurf: "windsurf",
15402
+ ClaudeDesktop: "claudedesktop",
15403
+ ChatGpt: "chatgpt",
15404
+ ClaudeAi: "claudeai",
15405
+ Api: "api"
15406
+ };
15407
+ var Harness = external_exports.enum(HARNESS).meta({ id: "Harness" });
15408
+ var SOURCE_TOOL = {
15409
+ ClaudeCode: "claude-code",
15410
+ ClaudeDesktop: "claude-desktop",
15411
+ Cursor: "cursor",
15412
+ ChatGpt: "chatgpt",
15413
+ ClaudeAi: "claude-ai",
15414
+ Copilot: "github-copilot",
15415
+ Codex: "codex",
15416
+ Antigravity: "antigravity",
15417
+ // No harness counterpart, deliberately: the CLI's own captures and a capture
15418
+ // whose tool could not be identified both render through the read side's
15419
+ // miss path rather than as a harness of their own.
15420
+ Cli: "cli",
15421
+ Unknown: "unknown"
15422
+ };
15423
+ var SourceTool = external_exports.enum(SOURCE_TOOL).meta({ id: "SourceTool" });
15424
+ var TOOL_TO_HARNESS = {
15425
+ [SOURCE_TOOL.ClaudeCode]: HARNESS.ClaudeCode,
15426
+ [SOURCE_TOOL.ClaudeDesktop]: HARNESS.ClaudeDesktop,
15427
+ [SOURCE_TOOL.Copilot]: HARNESS.Copilot,
15428
+ [SOURCE_TOOL.Cursor]: HARNESS.Cursor,
15429
+ [SOURCE_TOOL.ChatGpt]: HARNESS.ChatGpt,
15430
+ [SOURCE_TOOL.Codex]: HARNESS.Codex,
15431
+ [SOURCE_TOOL.Antigravity]: HARNESS.Antigravity,
15432
+ [SOURCE_TOOL.ClaudeAi]: HARNESS.ClaudeAi
15433
+ };
15434
+
15398
15435
  // ../../packages/schema/src/zod/finding.ts
15399
15436
  var DetectionCategory = external_exports.enum(["pii", "financial", "secret", "phi", "code_context", "code_flaw", "custom", "config"]).meta({ id: "DetectionCategory" });
15400
15437
  var Severity = external_exports.enum(["critical", "high", "medium", "low"]).meta({ id: "Severity" });
@@ -15417,21 +15454,22 @@ var Finding = external_exports.object({
15417
15454
  }).meta({ id: "Finding" });
15418
15455
  var DetectedFinding = Finding.meta({ id: "DetectedFinding" });
15419
15456
  var FindingAction = external_exports.enum(["blocked", "redacted", "warned", "allowed", "quarantined", "monitored"]).meta({ id: "FindingAction" });
15420
- var FindingProvider = external_exports.enum([
15421
- "claudecode",
15422
- "claudedesktop",
15423
- "cursor",
15424
- "copilot",
15425
- "chatgpt",
15426
- "claudeai",
15427
- "codex",
15428
- "antigravity",
15429
- "api"
15457
+ var FindingProvider = Harness.extract([
15458
+ "ClaudeCode",
15459
+ "ClaudeDesktop",
15460
+ "Cursor",
15461
+ "Copilot",
15462
+ "ChatGpt",
15463
+ "ClaudeAi",
15464
+ "Codex",
15465
+ "Antigravity",
15466
+ "Api"
15430
15467
  ]).meta({ id: "FindingProvider" });
15431
15468
  var FindingCategory = external_exports.enum([
15432
15469
  "secret",
15433
15470
  "pii",
15434
15471
  "source_code",
15472
+ "code_flaw",
15435
15473
  "external_share",
15436
15474
  "mcp_server",
15437
15475
  "customer_data",
@@ -15609,6 +15647,7 @@ var FindingInstanceDetail = FindingInstance.extend({
15609
15647
  detection: FindingDetectionRef,
15610
15648
  policy: FindingPolicyRef
15611
15649
  }).meta({ id: "FindingInstanceDetail" });
15650
+ var MAX_FLAT_FINDINGS_LIMIT = 200;
15612
15651
  var ListFindingInstancesQuery = external_exports.object({
15613
15652
  severity: external_exports.array(Severity).optional(),
15614
15653
  // Rule ids, the same vocabulary the grouped list's `subtype` carries.
@@ -15628,7 +15667,7 @@ var ListFindingInstancesQuery = external_exports.object({
15628
15667
  q: external_exports.string().optional(),
15629
15668
  sessionId: external_exports.string().optional(),
15630
15669
  from: external_exports.iso.datetime().optional(),
15631
- limit: external_exports.coerce.number().int().min(1).max(200).optional(),
15670
+ limit: external_exports.coerce.number().int().min(1).max(MAX_FLAT_FINDINGS_LIMIT).optional(),
15632
15671
  cursor: external_exports.string().optional()
15633
15672
  });
15634
15673
  var ListFindingInstancesResponse = external_exports.object({
@@ -15690,20 +15729,6 @@ var ListFindingLocationsResponse = external_exports.object({
15690
15729
  hasMore: external_exports.boolean()
15691
15730
  }).meta({ id: "ListFindingLocationsResponse" });
15692
15731
 
15693
- // ../../packages/schema/src/zod/harness-map.ts
15694
- var Harness = external_exports.enum([
15695
- "claudecode",
15696
- "cursor",
15697
- "copilot",
15698
- "codex",
15699
- "antigravity",
15700
- "windsurf",
15701
- "claudedesktop",
15702
- "chatgpt",
15703
- "claudeai",
15704
- "api"
15705
- ]).meta({ id: "Harness" });
15706
-
15707
15732
  // ../../packages/schema/src/zod/meta.ts
15708
15733
  var InventoryObjectType = external_exports.enum(["host", "harness", "user", "skill", "hook", "mcp_server", "config_file"]).meta({ id: "InventoryObjectType" });
15709
15734
  var AuditEventType = external_exports.enum([
@@ -16153,366 +16178,122 @@ var ActivityOverviewResponse = external_exports.object({
16153
16178
  sessions: ListActivitySessionsResponse
16154
16179
  }).meta({ id: "ActivityOverviewResponse" });
16155
16180
 
16156
- // ../../packages/schema/src/zod/event.ts
16157
- var EventKind = external_exports.enum(["prompt", "response", "code_change", "tool_use"]).meta({ id: "EventKind" });
16158
- var CAPTURE_EVENT_TYPES_SQL = EventKind.options.map((k) => `'${k}'`).join(",");
16159
- var SourceTool = external_exports.enum([
16160
- "claude-code",
16161
- "claude-desktop",
16162
- "cursor",
16163
- "chatgpt",
16164
- "claude-ai",
16165
- "github-copilot",
16166
- "codex",
16167
- "antigravity",
16168
- "cli",
16169
- "unknown"
16170
- ]).meta({ id: "SourceTool" });
16171
- var EventMetadata = external_exports.object({
16172
- sessionId: external_exports.string().optional(),
16173
- repo: external_exports.string().optional(),
16174
- filePath: external_exports.string().optional(),
16175
- // The host tool whose input/output was scanned (e.g. 'Bash', 'WebFetch'),
16176
- // set by the tool-scanning hooks. The tool NAME only — never the tool's
16177
- // arguments or output, which can carry the very value a finding masked
16178
- // (metadata is stored unredacted). Gives findings on non-file captures a
16179
- // display location ("via Bash") when no filePath exists.
16180
- toolName: external_exports.string().optional(),
16181
- // Set (true) by the worktree scanner when the file is excluded by the
16182
- // repo's .gitignore. Gitignored files ARE still scanned — local scratch and
16183
- // generated code can leak real secrets — but the provenance is recorded so
16184
- // policy/dashboards can treat those findings as informational rather than
16185
- // blocking. Omitted (not false) for tracked files and non-scan events.
16186
- gitignored: external_exports.boolean().optional(),
16187
- // Set (true) ONLY when the event's `content` is the COMPLETE file at
16188
- // capture time (a worktree scan reading from disk). Hook-captured edits
16189
- // (e.g. an Edit tool's new_string) are partial fragments and MUST NOT set
16190
- // this. The resolver-on-ingest keys its fixed-at-source dropout
16191
- // diff on this marker: only a whole-file snapshot can prove a previously
16192
- // open finding is gone; a fragment's absence proves nothing (the secret
16193
- // may live outside the hunk). Omitted (not false) for fragments and
16194
- // non-scan events, so pre-marker clients safely default to the
16195
- // non-authoritative path.
16196
- wholeFile: external_exports.boolean().optional(),
16197
- model: external_exports.string().optional(),
16198
- turnIndex: external_exports.number().int().nonnegative().optional(),
16199
- // Distributed-tracing correlation. `correlationId` ties a recorded event back
16200
- // to the request that captured/ingested it (a UUID, generated independently of
16201
- // the trace id); `traceId` is the W3C trace id (32 lowercase hex chars) of the
16202
- // originating span when telemetry is enabled. Both optional + backward
16203
- // compatible — populated by the plugin (see @akasecurity/plugin-sdk).
16204
- correlationId: external_exports.uuid().optional(),
16205
- traceId: external_exports.string().regex(/^[0-9a-f]{32}$/).optional(),
16206
- // Ids of the detection exceptions that downgraded findings in this capture
16207
- // to 'allow' — the enforcement audit trail's link back to the grant that
16208
- // authorized the bypass. Absent on captures where no exception applied.
16209
- exceptionIds: external_exports.array(external_exports.guid()).optional()
16210
- }).meta({ id: "EventMetadata" });
16211
- var Event = external_exports.object({
16212
- id: external_exports.guid(),
16213
- sourceTool: SourceTool,
16214
- kind: EventKind,
16215
- occurredAt: external_exports.iso.datetime(),
16216
- contentHash: external_exports.string(),
16217
- content: external_exports.string(),
16218
- metadata: EventMetadata.optional()
16219
- }).meta({ id: "Event" });
16220
- var IngestEvent = Event.meta({ id: "IngestEvent" });
16221
- var IngestBatch = external_exports.object({
16222
- events: external_exports.array(IngestEvent).min(1).max(100),
16223
- // Dedup policy for this batch. Id-dedup ALWAYS applies. 'content-hash'
16224
- // additionally rejects any event whose contentHash the store has already
16225
- // recorded — for re-runnable bulk ingest (worktree scan, transcript
16226
- // backfill), where a re-run mints fresh event ids for identical content and
16227
- // would otherwise accumulate duplicates. Live hook traffic must NOT set it:
16228
- // two genuinely separate prompts can be byte-identical and both belong on
16229
- // the timeline.
16230
- dedupe: external_exports.literal("content-hash").optional()
16231
- }).meta({ id: "IngestBatch" });
16232
-
16233
- // ../../packages/schema/src/zod/inventory.ts
16234
- var AssetType = external_exports.enum(["project", "skill", "mcp", "hook", "config"]).meta({ id: "AssetType" });
16235
- var AccessLevel = external_exports.enum(["open", "approved", "blocked"]).meta({ id: "AccessLevel" });
16236
- var Origin = external_exports.enum(["source", "public-dep", "vendored", "config", "data", "docs", "generated"]).meta({ id: "Origin" });
16237
- var TrustLevel = external_exports.enum(["known-good", "risky", "unapproved"]).meta({ id: "TrustLevel" });
16238
- var Flag = external_exports.enum(["update", "stale", "conflict", "unknown", "change", "untracked", "risk", "findings"]).meta({ id: "Flag" });
16239
- var Visibility = external_exports.enum(["public", "private"]).meta({ id: "Visibility" });
16240
- var HarnessEventKind = external_exports.enum(["block", "redact", "warn"]).meta({ id: "HarnessEventKind" });
16241
- var HarnessId = external_exports.enum(["claudecode", "cursor", "codex", "antigravity"]).meta({ id: "HarnessId" });
16242
- var AccessCounts = external_exports.object({
16243
- open: external_exports.number().int().nonnegative(),
16244
- approved: external_exports.number().int().nonnegative(),
16245
- blocked: external_exports.number().int().nonnegative(),
16246
- total: external_exports.number().int().nonnegative()
16247
- }).meta({ id: "AccessCounts" });
16248
- var AssetSummary = external_exports.object({
16249
- id: external_exports.string(),
16250
- type: AssetType,
16251
- name: external_exports.string(),
16252
- sub: external_exports.string(),
16253
- flags: external_exports.array(Flag),
16254
- /** MCP servers only — omitted for all other types. */
16255
- trust: TrustLevel.optional()
16256
- }).meta({ id: "AssetSummary" });
16257
- var ProjectSummary = external_exports.object({
16258
- id: external_exports.string(),
16259
- name: external_exports.string(),
16260
- repo: external_exports.string(),
16261
- visibility: Visibility,
16262
- language: external_exports.string(),
16263
- policyDefault: AccessLevel,
16264
- updatedAt: external_exports.iso.datetime(),
16265
- accessCounts: AccessCounts,
16266
- findingsCount: external_exports.number().int().nonnegative()
16267
- }).meta({ id: "ProjectSummary" });
16268
- var HarnessCategory = external_exports.object({
16269
- /** One of config/skill/mcp/hook — never project (enforced at service layer). */
16270
- type: AssetType,
16271
- assets: external_exports.array(AssetSummary)
16181
+ // ../../packages/schema/src/zod/config-inventory.ts
16182
+ var ConfigScope = external_exports.enum(["user", "project", "local", "plugin"]);
16183
+ var SkillScanEntry = external_exports.object({
16184
+ name: external_exports.string().min(1),
16185
+ // The identity source: a marketplace repo for plugin skills (e.g.
16186
+ // 'anthropics/skills'), 'local' for personal ~/.claude/skills, or
16187
+ // 'project:<repo-identity>' for checked-in project skills. The surrogate keeps
16188
+ // a personal skill named 'pdf' from colliding with the marketplace 'pdf'.
16189
+ source: external_exports.string().min(1),
16190
+ scope: ConfigScope,
16191
+ pluginName: external_exports.string().optional(),
16192
+ // Volatile — rides the attribute bag, never the identity hash.
16193
+ version: external_exports.string().optional(),
16194
+ description: external_exports.string().optional(),
16195
+ // Skill directory mtime (ISO) the "updated Nd ago" freshness signal.
16196
+ updatedAt: external_exports.iso.datetime().optional(),
16197
+ // Filesystem path — the promoted inventory `location` column.
16198
+ location: external_exports.string().optional()
16272
16199
  });
16273
- var HarnessSummary = external_exports.object({
16274
- id: HarnessId,
16275
- label: external_exports.string(),
16276
- kind: external_exports.string(),
16277
- version: external_exports.string(),
16278
- sessions: external_exports.number().int().nonnegative(),
16279
- assetCount: external_exports.number().int().nonnegative(),
16280
- flagCount: external_exports.number().int().nonnegative(),
16281
- projects: external_exports.array(ProjectSummary),
16282
- categories: external_exports.array(HarnessCategory)
16283
- }).meta({ id: "HarnessSummary" });
16284
- var ListHarnessesResponse = external_exports.object({ items: external_exports.array(HarnessSummary) }).meta({ id: "ListHarnessesResponse" });
16285
- var AssetGroup = external_exports.object({
16286
- /** Group key — never project (enforced at service layer). */
16287
- type: AssetType,
16288
- total: external_exports.number().int().nonnegative(),
16289
- /**
16290
- * MCP group only — omitted for all other types.
16291
- * Partial: only TrustLevel keys with non-zero counts are included.
16292
- * Strict: unknown keys are rejected — only TrustLevel values are valid keys.
16293
- */
16294
- trustRollup: external_exports.object({
16295
- "known-good": external_exports.number().int().nonnegative(),
16296
- risky: external_exports.number().int().nonnegative(),
16297
- unapproved: external_exports.number().int().nonnegative()
16298
- }).partial().strict().optional(),
16299
- /**
16300
- * Partial: only Flag keys with non-zero counts are included.
16301
- * Strict: unknown keys are rejected — only Flag values are valid keys.
16302
- */
16303
- flagRollup: external_exports.object({
16304
- update: external_exports.number().int().nonnegative(),
16305
- stale: external_exports.number().int().nonnegative(),
16306
- conflict: external_exports.number().int().nonnegative(),
16307
- unknown: external_exports.number().int().nonnegative(),
16308
- change: external_exports.number().int().nonnegative(),
16309
- untracked: external_exports.number().int().nonnegative(),
16310
- risk: external_exports.number().int().nonnegative(),
16311
- findings: external_exports.number().int().nonnegative()
16312
- }).partial().strict(),
16313
- items: external_exports.array(AssetSummary)
16314
- }).meta({ id: "AssetGroup" });
16315
- var ListAssetsResponse = external_exports.object({ groups: external_exports.array(AssetGroup) }).meta({ id: "ListAssetsResponse" });
16316
- var McpTool = external_exports.object({
16317
- name: external_exports.string(),
16318
- signature: external_exports.string(),
16319
- description: external_exports.string(),
16320
- write: external_exports.boolean(),
16321
- /** Non-null string when tool is dangerous / blocked; null otherwise. */
16322
- risk: external_exports.string().nullable()
16323
- }).meta({ id: "McpTool" });
16324
- var AssetFindingRef = external_exports.object({
16325
- id: external_exports.string(),
16326
- title: external_exports.string(),
16327
- note: external_exports.string()
16200
+ var HookScanEntry = external_exports.object({
16201
+ // Hook event name (PreToolUse, PostToolUse, …). Open string, not an enum: the
16202
+ // set is harness-defined and grows without a schema change.
16203
+ event: external_exports.string().min(1),
16204
+ // The tool matcher ('Bash', 'Edit|Write', …). Absent = matches all tools.
16205
+ matcher: external_exports.string().optional(),
16206
+ command: external_exports.string().min(1),
16207
+ timeout: external_exports.number().optional(),
16208
+ scope: ConfigScope,
16209
+ pluginName: external_exports.string().optional(),
16210
+ // The settings file / hooks.json the entry came from.
16211
+ location: external_exports.string().optional()
16328
16212
  });
16329
- var AssetDetail = AssetSummary.extend({
16330
- /** string | null null when no description is available. */
16331
- description: external_exports.string().nullable(),
16332
- /** trustLevel | null — null for non-MCP assets. */
16333
- trust: TrustLevel.nullable(),
16334
- /** Type-specific raw key/values — FE renders the grid. */
16335
- meta: external_exports.record(external_exports.string(), external_exports.unknown()),
16336
- /** always present object when there is an active finding, null when absent. */
16337
- finding: AssetFindingRef.nullable(),
16338
- /** MCP exposed-tools list — omitted for non-mcp. */
16339
- tools: external_exports.array(McpTool).optional()
16340
- }).meta({ id: "AssetDetail" });
16341
- var ListProjectsResponse = external_exports.object({ items: external_exports.array(ProjectSummary) }).meta({ id: "ListProjectsResponse" });
16342
- var InventoryStats = external_exports.object({
16343
- /** Total assets/projects with ≥1 flag or finding (drives the attention header chip). */
16344
- attention: external_exports.number().int().nonnegative(),
16345
- byType: external_exports.object({
16346
- project: external_exports.number().int().nonnegative(),
16347
- skill: external_exports.number().int().nonnegative(),
16348
- mcp: external_exports.number().int().nonnegative(),
16349
- hook: external_exports.number().int().nonnegative(),
16350
- config: external_exports.number().int().nonnegative()
16351
- }),
16352
- harnesses: external_exports.number().int().nonnegative(),
16353
- mcpTrust: external_exports.object({
16354
- "known-good": external_exports.number().int().nonnegative(),
16355
- risky: external_exports.number().int().nonnegative(),
16356
- unapproved: external_exports.number().int().nonnegative()
16357
- })
16358
- }).meta({ id: "InventoryStats" });
16359
- var FileSummary = external_exports.object({
16360
- path: external_exports.string(),
16361
- name: external_exports.string(),
16362
- origin: Origin,
16363
- /** Effective access (override applied). */
16364
- access: AccessLevel,
16365
- /** True when a file_access_override differs from the computed default. */
16366
- isCustom: external_exports.boolean(),
16367
- findings: external_exports.number().int().nonnegative(),
16368
- /** When the file was auto-blocked by a detection; null when not blocked. */
16369
- blockedAt: external_exports.iso.datetime().nullable().optional(),
16370
- /** Why the file was blocked; null when absent. */
16371
- note: external_exports.string().nullable().optional()
16372
- }).meta({ id: "FileSummary" });
16373
- var FolderSummary = external_exports.object({
16374
- name: external_exports.string(),
16375
- path: external_exports.string(),
16376
- /** Rollup of effective access across all descendants. */
16377
- accessCounts: AccessCounts
16378
- }).meta({ id: "FolderSummary" });
16379
- var ProjectTreeResponse = external_exports.object({
16380
- project: external_exports.object({
16381
- id: external_exports.string(),
16382
- repo: external_exports.string(),
16383
- visibility: Visibility
16384
- }),
16385
- path: external_exports.string(),
16386
- /** Browse mode: one-level folders at the current path. Omitted in search mode. */
16387
- folders: external_exports.array(FolderSummary).optional(),
16388
- files: external_exports.array(FileSummary)
16389
- }).meta({ id: "ProjectTreeResponse" });
16390
- var FileDetail = FileSummary.extend({
16391
- project: external_exports.object({
16392
- repo: external_exports.string(),
16393
- visibility: Visibility,
16394
- language: external_exports.string(),
16395
- policyDefault: AccessLevel,
16396
- updatedAt: external_exports.iso.datetime()
16397
- }),
16398
- findingsRefs: external_exports.array(external_exports.object({ id: external_exports.string(), title: external_exports.string() }))
16399
- }).meta({ id: "FileDetail" });
16400
- var SetFileAccessBody = external_exports.object({
16401
- path: external_exports.string(),
16402
- access: AccessLevel
16403
- }).meta({ id: "SetFileAccessBody" });
16404
- var SetFileAccessResponse = external_exports.object({
16405
- file: FileSummary,
16406
- accessCounts: AccessCounts
16407
- }).meta({ id: "SetFileAccessResponse" });
16408
- var SetMcpTrustBody = external_exports.object({ trust: TrustLevel }).meta({ id: "SetMcpTrustBody" });
16409
- var HarnessEventItem = external_exports.object({
16410
- kind: HarnessEventKind,
16411
- title: external_exports.string(),
16412
- detail: external_exports.string(),
16413
- occurredAt: external_exports.iso.datetime(),
16414
- findingId: external_exports.string().nullable().optional()
16415
- }).meta({ id: "HarnessEventItem" });
16416
- var HarnessEventsResponse = external_exports.object({
16417
- counts: external_exports.object({
16418
- block: external_exports.number().int().nonnegative(),
16419
- redact: external_exports.number().int().nonnegative(),
16420
- warn: external_exports.number().int().nonnegative()
16421
- }),
16422
- items: external_exports.array(HarnessEventItem)
16423
- }).meta({ id: "HarnessEventsResponse" });
16424
- var RescanResponse = external_exports.object({
16425
- jobId: external_exports.string(),
16426
- startedAt: external_exports.iso.datetime()
16427
- }).meta({ id: "RescanResponse" });
16428
- var ConnectProjectBody = external_exports.object({ repo: external_exports.string() }).meta({ id: "ConnectProjectBody" });
16429
- var ListAssetsQuery = external_exports.object({
16430
- /** Filter by one or more AssetType values; absent means all types. */
16431
- type: external_exports.array(AssetType).optional(),
16432
- /** Free-text search term. */
16433
- q: external_exports.string().optional()
16434
- });
16435
- var GetProjectTreeQuery = external_exports.object({
16436
- /** Subtree root path; defaults to repository root when absent. */
16437
- path: external_exports.string().optional(),
16438
- /** Free-text filter applied to file paths. */
16439
- q: external_exports.string().optional(),
16440
- /**
16441
- * Special listing mode. `blocked` returns every effectively-blocked, auto-blocked
16442
- * file across the whole repo (folders omitted, most-recent first), ignoring
16443
- * `path`/`q` — powers the project-wide "recently blocked" strip.
16444
- */
16445
- filter: external_exports.enum(["blocked"]).optional()
16213
+ var McpServerScanEntry = external_exports.object({
16214
+ // The server's config key ("github", "filesystem", …) identity, with the
16215
+ // qualified scope (see mcpServerIdentityKey).
16216
+ name: external_exports.string().min(1),
16217
+ scope: ConfigScope,
16218
+ pluginName: external_exports.string().optional(),
16219
+ // The owning plugin's marketplace — part of PLUGIN-scope identity: two
16220
+ // marketplaces can each ship a plugin named `guard`, and without this their
16221
+ // same-named servers would collapse to one row (the second silently dropped,
16222
+ // inheriting the first's trust).
16223
+ marketplace: external_exports.string().optional(),
16224
+ // The repo identity (remote url, or the cwd for un-remoted repos) — part of
16225
+ // PROJECT/LOCAL-scope identity: a server named `github` in repo A and one in
16226
+ // repo B are different servers with different commands, and MUST NOT share a
16227
+ // row a shared row would let a cloned repo's .mcp.json inherit the trust
16228
+ // the user granted elsewhere.
16229
+ project: external_exports.string().optional(),
16230
+ // 'stdio' when the entry carries a command; otherwise the config's `type`
16231
+ // ('http' / 'sse' / …). Open string — the transport set is harness-defined.
16232
+ transport: external_exports.string().min(1),
16233
+ // Volatile on purpose (unlike hook `command`): a changed command/url is drift
16234
+ // on a stable row — visible across config_scan snapshots and preserving the
16235
+ // user's trust decision — never a quiet new row. One of the two is present.
16236
+ // Secret-masked at collection time (the scanner runs the bundled detection
16237
+ // packs over both — tokens routinely ride command args and URLs).
16238
+ command: external_exports.string().optional(),
16239
+ url: external_exports.string().optional(),
16240
+ // Env var NAMES only, never values (the no-secrets rule).
16241
+ envKeys: external_exports.array(external_exports.string()).optional(),
16242
+ // The config file the entry came from.
16243
+ location: external_exports.string().optional()
16446
16244
  });
16447
- var GetProjectFileQuery = external_exports.object({
16448
- /** Repository-relative file path; absent or empty 400. */
16449
- path: external_exports.string()
16245
+ var ConfigFileScanEntry = external_exports.object({
16246
+ // Basename (settings.json, CLAUDE.md) or dir name (commands/, agents/).
16247
+ name: external_exports.string().min(1),
16248
+ // The absolute path — identity (with scope) and the promoted `location`.
16249
+ path: external_exports.string().min(1),
16250
+ scope: ConfigScope,
16251
+ // Human label: "User settings", "Project memory", "Slash commands", …
16252
+ kind: external_exports.string().min(1),
16253
+ // Derived SHAPE summary — top-level key names, entry counts, line counts.
16254
+ // Never file content or values (memory files can carry sensitive detail).
16255
+ detail: external_exports.string().optional(),
16256
+ // Dir configs (commands/, agents/) and .mcp.json: how many entries.
16257
+ entryCount: external_exports.number().optional(),
16258
+ // File mtime (ISO) — the freshness signal.
16259
+ updatedAt: external_exports.iso.datetime().optional()
16450
16260
  });
16451
- var GetHarnessEventsQuery = external_exports.object({
16452
- /** Maximum number of events to return. Range: 1–50; default: 7. */
16453
- limit: external_exports.coerce.number().int().min(1).max(50).default(7)
16261
+ var ConfigScanResult = external_exports.object({
16262
+ scannedAt: external_exports.iso.datetime(),
16263
+ skills: external_exports.array(SkillScanEntry),
16264
+ hooks: external_exports.array(HookScanEntry),
16265
+ mcpServers: external_exports.array(McpServerScanEntry),
16266
+ configFiles: external_exports.array(ConfigFileScanEntry),
16267
+ errors: external_exports.array(external_exports.object({ source: external_exports.string(), reason: external_exports.string() }))
16454
16268
  });
16455
-
16456
- // ../../packages/schema/src/zod/exception.ts
16457
- var ExceptionScope = external_exports.enum(["once", "temporary", "permanent"]);
16458
- var ExceptionConditions = external_exports.object({
16459
- repo: external_exports.string().optional(),
16460
- sourceTool: external_exports.string().optional(),
16461
- provider: external_exports.string().optional()
16462
- }).strict();
16463
- var ExceptionCapability = external_exports.enum(["suppress", "reveal_to_model"]);
16464
- var DetectionException = external_exports.object({
16465
- id: external_exports.guid(),
16466
- ruleId: external_exports.string(),
16467
- // Denormalized from the rule, for reporting — never matched on.
16468
- category: DetectionCategory,
16469
- // HMAC-SHA256 hex of the raw match under a machine-local key: a KEYED
16470
- // fingerprint, never the raw value, and never reversible. Matching recomputes
16471
- // the fingerprint from a fresh capture; the value itself is never stored.
16472
- // Shape-constrained so a malformed — or accidentally raw — value is rejected
16473
- // at the boundary rather than persisted.
16474
- valueFingerprint: external_exports.string().regex(/^[0-9a-f]{64}$/),
16475
- // Version of the fingerprint key the grant was written under; a rotated key
16476
- // invalidates old grants rather than silently mismatching them.
16477
- keyVersion: external_exports.number().int().positive(),
16478
- // maskMatch() preview of the approved value — never the raw value.
16479
- maskedValue: external_exports.string(),
16480
- capability: ExceptionCapability.default("suppress"),
16481
- scope: ExceptionScope,
16482
- expiresAt: external_exports.iso.datetime().nullable(),
16483
- maxUses: external_exports.number().int().positive().nullable(),
16484
- useCount: external_exports.number().int().nonnegative(),
16485
- lastUsedAt: external_exports.iso.datetime().nullable(),
16486
- // Mandatory: every grant carries the human reason it exists.
16487
- justification: external_exports.string().min(1),
16488
- conditions: ExceptionConditions.nullable(),
16489
- createdBy: external_exports.string(),
16490
- createdVia: external_exports.enum(["cli-approve", "cli-add", "web-approve", "web-add", "api", "setup-triage"]),
16491
- createdAt: external_exports.iso.datetime(),
16492
- updatedAt: external_exports.iso.datetime(),
16493
- // Revocation is terminal and retained — consumed/expired/revoked rows are
16494
- // audit evidence; nothing in the exception lifecycle hard-deletes.
16495
- revokedAt: external_exports.iso.datetime().nullable(),
16496
- revokedBy: external_exports.string().nullable(),
16497
- revokeReason: external_exports.string().nullable()
16269
+ var ConfigPostureFindingInput = external_exports.object({
16270
+ ruleId: external_exports.string().min(1),
16271
+ version: external_exports.string().min(1),
16272
+ span: Span,
16273
+ // For posture rules this is the offending COMMAND (config the user already
16274
+ // holds locally, not captured secret content) — it is also the correlation
16275
+ // key the read surface matches back to a hook row.
16276
+ maskedMatch: external_exports.string(),
16277
+ actionTaken: ActionTaken,
16278
+ confidence: external_exports.number().min(0).max(1)
16498
16279
  });
16499
- var ExceptionBundleEntry = DetectionException.pick({
16500
- id: true,
16501
- ruleId: true,
16502
- valueFingerprint: true,
16503
- keyVersion: true,
16504
- capability: true,
16505
- expiresAt: true,
16506
- maxUses: true,
16507
- useCount: true,
16508
- conditions: true
16280
+ var ConfigScanRecord = external_exports.object({
16281
+ items: external_exports.array(InventoryInput),
16282
+ scanEvent: AuditEventInput,
16283
+ definitions: external_exports.array(InspectionDefinitionInput).optional(),
16284
+ findings: external_exports.array(ConfigPostureFindingInput).optional()
16509
16285
  });
16510
- var ExceptionDescriptor = DetectionException.omit({ valueFingerprint: true });
16286
+
16287
+ // ../../packages/schema/src/zod/registry.ts
16288
+ var Namespace = external_exports.string().regex(/^[a-z][a-z0-9-]*$/);
16289
+ var PackId = external_exports.string().regex(/^[a-z][a-z0-9-]*$/);
16290
+ var SemVer = external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?$/);
16291
+ var PublisherKind = external_exports.enum(["labs", "user", "org"]);
16511
16292
 
16512
16293
  // ../../packages/schema/src/zod/rule.ts
16513
- var MatcherType = external_exports.enum(["keyword", "regex", "validator"]).meta({ id: "MatcherType" });
16294
+ var MatcherType = external_exports.enum(["keyword", "regex"]).meta({ id: "MatcherType" });
16514
16295
  var RuleProbeVerdict = external_exports.enum(["safe", "quarantined"]).meta({ id: "RuleProbeVerdict" });
16515
- var KeywordMatcher2 = external_exports.object({
16296
+ var KeywordMatcher2 = external_exports.strictObject({
16516
16297
  type: external_exports.literal("keyword"),
16517
16298
  // An empty keyword matches at every position, yielding one zero-length span
16518
16299
  // per character. Rejected here because a keyword that matches everything is
@@ -16528,16 +16309,31 @@ function isValidRegex(pattern, flags) {
16528
16309
  return false;
16529
16310
  }
16530
16311
  }
16312
+ function probeFlags(flags) {
16313
+ return flags.replace(/[gy]/g, "");
16314
+ }
16531
16315
  function matchesEmptyString(pattern, flags) {
16532
16316
  try {
16533
- const re = new RegExp(pattern, flags.replace(/[gy]/g, ""));
16317
+ const re = new RegExp(pattern, probeFlags(flags));
16534
16318
  return re.exec("")?.[0].length === 0;
16535
16319
  } catch {
16536
16320
  return false;
16537
16321
  }
16538
16322
  }
16323
+ function spansWholeMatch(captureGroup) {
16324
+ return captureGroup === void 0 || captureGroup === 0;
16325
+ }
16326
+ function captureGroupCount(pattern, flags) {
16327
+ try {
16328
+ const probe = new RegExp(`${pattern}|`, probeFlags(flags));
16329
+ const result = probe.exec("");
16330
+ return result ? result.length - 1 : void 0;
16331
+ } catch {
16332
+ return void 0;
16333
+ }
16334
+ }
16539
16335
  var MAX_PATTERN_LENGTH = 2e3;
16540
- var RegexMatcher2 = external_exports.object({
16336
+ var RegexMatcher2 = external_exports.strictObject({
16541
16337
  type: external_exports.literal("regex"),
16542
16338
  pattern: external_exports.string().min(1).max(MAX_PATTERN_LENGTH),
16543
16339
  flags: external_exports.string().default("gi"),
@@ -16545,28 +16341,47 @@ var RegexMatcher2 = external_exports.object({
16545
16341
  }).refine((v) => isValidRegex(v.pattern, v.flags), {
16546
16342
  message: "pattern/flags do not form a valid JavaScript regular expression",
16547
16343
  path: ["pattern"]
16548
- }).refine((v) => v.captureGroup !== void 0 || !matchesEmptyString(v.pattern, v.flags), {
16344
+ }).refine((v) => !spansWholeMatch(v.captureGroup) || !matchesEmptyString(v.pattern, v.flags), {
16549
16345
  message: 'a whole-match regex that can match the empty string (e.g. "\\d*", "a?", "(?:)") can hang the matcher \u2014 scope the quantifier to a captureGroup, or require at least one character',
16550
16346
  path: ["pattern"]
16347
+ }).superRefine((v, ctx) => {
16348
+ if (v.captureGroup === void 0) return;
16349
+ const groups = captureGroupCount(v.pattern, v.flags);
16350
+ if (groups === void 0 || v.captureGroup <= groups) return;
16351
+ ctx.addIssue({
16352
+ code: "custom",
16353
+ path: ["captureGroup"],
16354
+ message: `captureGroup ${String(v.captureGroup)} is out of range \u2014 the pattern declares ${String(groups)} capture group(s), so valid values are 0-${String(groups)}. An out-of-range group never matches, which would make the rule silently never fire.`
16355
+ });
16551
16356
  });
16552
- var ValidatorMatcher = external_exports.object({
16553
- type: external_exports.literal("validator"),
16554
- name: external_exports.enum(["luhn", "entropy", "ssn-checksum"]),
16555
- config: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
16556
- });
16557
- var Matcher = external_exports.discriminatedUnion("type", [KeywordMatcher2, RegexMatcher2, ValidatorMatcher]).meta({ id: "Matcher" });
16558
- var AppliesTo = external_exports.object({
16357
+ var Matcher = external_exports.discriminatedUnion("type", [KeywordMatcher2, RegexMatcher2]).meta({ id: "Matcher" });
16358
+ var MATCHER_TYPES = MatcherType.options;
16359
+ var AppliesTo = external_exports.strictObject({
16559
16360
  // Dot-prefixed, e.g. ".py" — matches the scanner's SOURCE_EXTENSIONS shape.
16560
16361
  extensions: external_exports.array(external_exports.string().regex(/^\.[A-Za-z0-9]+$/)).min(1)
16561
16362
  }).meta({ id: "AppliesTo" });
16562
- var PostValidatorRef = external_exports.union([
16563
- external_exports.string(),
16564
- external_exports.object({
16565
- name: external_exports.string(),
16566
- config: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
16567
- })
16568
- ]).meta({ id: "PostValidatorRef" });
16569
- var RequiresNearby = external_exports.object({
16363
+ var PostValidatorName = external_exports.enum(["entropy", "luhn"]).meta({ id: "PostValidatorName" });
16364
+ var PostValidatorRef = external_exports.union(
16365
+ [
16366
+ PostValidatorName,
16367
+ external_exports.strictObject({
16368
+ name: PostValidatorName,
16369
+ config: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
16370
+ })
16371
+ ],
16372
+ {
16373
+ // A union reports one collapsed issue for every way its arms can fail, so
16374
+ // this has to describe the whole shape rather than just the name — it is
16375
+ // what an author sees for a misspelled name AND for a stray key in the
16376
+ // object form. The names come from the enum so the message cannot go
16377
+ // stale. Without it Zod says only "Invalid input", which is precisely the
16378
+ // no-feedback outcome this schema exists to remove.
16379
+ error: () => `not a valid post-validator: use a bare name (${PostValidatorName.options.map((name) => JSON.stringify(name)).join(
16380
+ " or "
16381
+ )}) or { "name": ..., "config": { ... } }. An unrecognized name would be a false-positive guard that never runs.`
16382
+ }
16383
+ ).meta({ id: "PostValidatorRef" });
16384
+ var RequiresNearby = external_exports.strictObject({
16570
16385
  // Each array, when present, must be non-empty and contain non-empty strings —
16571
16386
  // an empty/blank criterion would either never fire or (for labels) match
16572
16387
  // everything.
@@ -16581,16 +16396,23 @@ var RequiresNearby = external_exports.object({
16581
16396
  (v) => (v.categories?.length ?? 0) + (v.ruleIds?.length ?? 0) + (v.labels?.length ?? 0) > 0,
16582
16397
  { message: "requiresNearby needs at least one of categories, ruleIds, or labels" }
16583
16398
  ).meta({ id: "RequiresNearby" });
16584
- var RuleFixture = external_exports.object({
16399
+ var RuleFixture = external_exports.strictObject({
16585
16400
  label: external_exports.string(),
16586
16401
  text: external_exports.string().max(5e4),
16587
16402
  shouldMatch: external_exports.boolean(),
16588
16403
  // Simulated file context for the scan, so fixtures can assert `appliesTo`
16589
16404
  // gating (e.g. a Python-only pattern must NOT fire in a .ts file).
16590
16405
  filePath: external_exports.string().optional(),
16591
- expectedSpans: external_exports.array(external_exports.object({ start: external_exports.number(), end: external_exports.number() })).optional()
16406
+ expectedSpans: external_exports.array(external_exports.strictObject({ start: external_exports.number(), end: external_exports.number() })).optional()
16592
16407
  }).meta({ id: "RuleFixture" });
16593
- var Rule = external_exports.object({
16408
+ var Rule = external_exports.strictObject({
16409
+ // A pinned literal over a STRICT object, and the two together decide how this
16410
+ // format may grow. A rule carrying a key not listed below is refused with
16411
+ // `unrecognized_keys`; a rule declaring `specVersion: 2` is refused with
16412
+ // `invalid_value`. So the only additive path is adding an OPTIONAL field here
16413
+ // — that keeps every rule authored before it valid — and a rule author has no
16414
+ // way to introduce a field of their own or to opt into a later version.
16415
+ // Widening the format means changing this literal and every consumer of it.
16594
16416
  specVersion: external_exports.literal(1),
16595
16417
  // `packId/ruleName` (e.g. `secrets/aws-access-key`). NOTE the first segment is
16596
16418
  // the PACK id, NOT a namespace — this is a DIFFERENT slug space from a
@@ -16626,287 +16448,6 @@ var PackManifest = external_exports.object({
16626
16448
  sourceUrl: external_exports.url().optional()
16627
16449
  }).meta({ id: "PackManifest" });
16628
16450
 
16629
- // ../../packages/schema/src/zod/policy.ts
16630
- var PolicyScope = external_exports.enum(["global", "repo", "user"]).meta({ id: "PolicyScope" });
16631
- var PolicyTarget = external_exports.union([external_exports.object({ ruleId: external_exports.string() }), external_exports.object({ category: DetectionCategory })]).meta({ id: "PolicyTarget" });
16632
- var Policy = external_exports.object({
16633
- id: external_exports.guid(),
16634
- scope: PolicyScope,
16635
- target: PolicyTarget,
16636
- action: ActionTaken,
16637
- enabled: external_exports.boolean().default(true),
16638
- customKeywords: external_exports.array(external_exports.string()).optional(),
16639
- // Display name — optional so older policy rows without name still parse.
16640
- // Added for the findings API (policy.name column migration).
16641
- name: external_exports.string().optional()
16642
- }).meta({ id: "Policy" });
16643
- var PolicyBundle = external_exports.object({
16644
- version: external_exports.string(),
16645
- policies: external_exports.array(Policy),
16646
- // Rules from the installed marketplace packs (snapshotted by the
16647
- // control plane). The plugin registers these in addition to its bundled
16648
- // packs. Optional so older backends — and older on-disk caches — that omit
16649
- // the field still parse; consumers read `bundle.rules ?? []`.
16650
- rules: external_exports.array(Rule).optional(),
16651
- // When true, `rules` IS the complete effective ruleset and the runtime must
16652
- // NOT merge its compiled-in bundled packs — the standalone gateway sets this
16653
- // after reading the user's installed snapshot (installed_packs, enabled
16654
- // packs only), which is how detection updates stay manual: new bundled
16655
- // rules run only after the user applies the pack update. Absent/false keeps
16656
- // the historical composition (bundled packs + rules) — older caches.
16657
- rulesComplete: external_exports.boolean().optional(),
16658
- // Active detection exceptions, evaluation subset only (see
16659
- // ExceptionBundleEntry). Optional so older bundle producers — and older
16660
- // on-disk caches — that omit the field still parse; consumers read
16661
- // `bundle.exceptions ?? []`.
16662
- exceptions: external_exports.array(ExceptionBundleEntry).optional(),
16663
- // Installed pack version, keyed by ruleId, for rules in `rules` that came
16664
- // from a versioned installed pack. Optional so older backends — and older
16665
- // on-disk caches — that omit the field still parse; consumers fall back to
16666
- // the rule's own spec version. NOT the bundle version above — see
16667
- // installedRuleset's ruleVersions for the source of truth.
16668
- ruleVersions: external_exports.record(external_exports.string(), external_exports.string()).optional(),
16669
- customKeywords: external_exports.array(external_exports.string()),
16670
- fetchedAt: external_exports.iso.datetime()
16671
- }).meta({ id: "PolicyBundle" });
16672
- var OBSERVE_ONLY_CATEGORIES = ["config"];
16673
- var ENFORCEABLE_CATEGORIES = DetectionCategory.options.filter((c) => !OBSERVE_ONLY_CATEGORIES.includes(c));
16674
- var CATEGORY_PEAK_SEVERITY = {
16675
- secret: "critical",
16676
- financial: "critical",
16677
- // core-financial/credit-card
16678
- code_flaw: "critical",
16679
- pii: "high",
16680
- phi: "high",
16681
- custom: "high",
16682
- // user-defined; conservative
16683
- code_context: "low",
16684
- config: "low"
16685
- // observe-only; floors to monitor regardless
16686
- };
16687
- function severityFloorPolicy(category) {
16688
- if (OBSERVE_ONLY_CATEGORIES.includes(category)) return "monitor";
16689
- const peak = CATEGORY_PEAK_SEVERITY[category];
16690
- return peak === "critical" || peak === "high" ? "warn" : "monitor";
16691
- }
16692
- var PolicyKind = external_exports.enum(["builtin", "custom"]).meta({ id: "PolicyKind" });
16693
- var KNOWN_BUILTIN_IDS = ["monitor", "warn", "redact", "block"];
16694
- var BuiltinPolicyId = external_exports.enum(KNOWN_BUILTIN_IDS).meta({ id: "BuiltinPolicyId" });
16695
- var BUILTIN_POLICY_SPECS = {
16696
- monitor: {
16697
- name: "Monitor",
16698
- action: "log",
16699
- description: "Log every match for audit. The request is allowed through untouched."
16700
- },
16701
- warn: {
16702
- name: "Warn",
16703
- action: "warn",
16704
- description: "Allow the request, but warn the user inline before it is sent."
16705
- },
16706
- redact: {
16707
- name: "Redact",
16708
- action: "redact",
16709
- description: "Automatically strip the matched value from the request, then continue."
16710
- },
16711
- block: {
16712
- name: "Block",
16713
- action: "block",
16714
- description: "Refuse the request entirely whenever any rule in this detection matches."
16715
- }
16716
- };
16717
- function builtinPolicyToAction(id) {
16718
- return BUILTIN_POLICY_SPECS[id].action;
16719
- }
16720
- var DEFAULT_ACTIONS = Object.fromEntries(
16721
- DetectionCategory.options.map((c) => [c, builtinPolicyToAction(severityFloorPolicy(c))])
16722
- );
16723
- var BUILTIN_POLICIES = Object.fromEntries(
16724
- KNOWN_BUILTIN_IDS.map((id) => [id, { id, ...BUILTIN_POLICY_SPECS[id] }])
16725
- );
16726
- var UsedByItem = external_exports.object({
16727
- id: external_exports.string(),
16728
- name: external_exports.string(),
16729
- ruleCount: external_exports.number().int().nonnegative(),
16730
- enabled: external_exports.boolean()
16731
- }).meta({ id: "UsedByItem" });
16732
- var PolicyListItem = external_exports.object({
16733
- id: external_exports.string(),
16734
- kind: PolicyKind,
16735
- name: external_exports.string(),
16736
- enabled: external_exports.boolean(),
16737
- usedByCount: external_exports.number().int().nonnegative()
16738
- }).meta({ id: "PolicyListItem" });
16739
- var PolicyDetail = external_exports.object({
16740
- specVersion: external_exports.literal(1),
16741
- id: external_exports.string(),
16742
- kind: PolicyKind,
16743
- name: external_exports.string(),
16744
- enabled: external_exports.boolean(),
16745
- description: external_exports.string(),
16746
- usedBy: external_exports.array(UsedByItem)
16747
- }).meta({ id: "PolicyDetail" });
16748
- var PolicyStatsResponse = external_exports.object({
16749
- policies: external_exports.number().int().nonnegative(),
16750
- builtin: external_exports.number().int().nonnegative(),
16751
- custom: external_exports.number().int().nonnegative(),
16752
- detectionsGoverned: external_exports.number().int().nonnegative()
16753
- }).meta({ id: "PolicyStatsResponse" });
16754
-
16755
- // ../../packages/schema/src/zod/api.ts
16756
- var LIST_QUERY_MAX_LIMIT = 200;
16757
- var ListEventsQuery = external_exports.object({
16758
- cursor: external_exports.string().optional(),
16759
- limit: external_exports.coerce.number().int().min(1).max(LIST_QUERY_MAX_LIMIT).default(50),
16760
- sourceTool: external_exports.string().optional(),
16761
- kind: external_exports.string().optional(),
16762
- from: external_exports.iso.datetime().optional(),
16763
- to: external_exports.iso.datetime().optional()
16764
- });
16765
- var ListEventsResponse = external_exports.object({
16766
- items: external_exports.array(Event),
16767
- nextCursor: external_exports.string().nullable()
16768
- }).meta({ id: "ListEventsResponse" });
16769
- var IngestResponse = external_exports.object({
16770
- accepted: external_exports.number().int().nonnegative(),
16771
- duplicates: external_exports.number().int().nonnegative()
16772
- }).meta({ id: "IngestResponse" });
16773
- var ListFindingsQuery = external_exports.object({
16774
- cursor: external_exports.string().optional(),
16775
- limit: external_exports.coerce.number().int().min(1).max(LIST_QUERY_MAX_LIMIT).default(50),
16776
- severity: external_exports.string().optional(),
16777
- category: external_exports.string().optional(),
16778
- eventId: external_exports.guid().optional()
16779
- });
16780
- var ListFindingsResponse = external_exports.object({
16781
- items: external_exports.array(Finding),
16782
- nextCursor: external_exports.string().nullable()
16783
- }).meta({ id: "ListFindingsResponse" });
16784
- var ListPoliciesResponse = external_exports.object({ items: external_exports.array(PolicyListItem) }).meta({ id: "ListPoliciesResponse" });
16785
- var CreatePolicyRequest = Policy.omit({ id: true }).meta({
16786
- id: "CreatePolicyRequest"
16787
- });
16788
- var UpdatePolicyRequest = Policy.partial().required({ id: true }).meta({ id: "UpdatePolicyRequest" });
16789
- var RecordAuditEventResponse = external_exports.object({ accepted: external_exports.boolean() }).meta({ id: "RecordAuditEventResponse" });
16790
- var ErrorResponse = external_exports.object({
16791
- error: external_exports.object({
16792
- code: external_exports.string(),
16793
- message: external_exports.string(),
16794
- details: external_exports.unknown().optional()
16795
- })
16796
- }).meta({ id: "ErrorResponse" });
16797
-
16798
- // ../../packages/schema/src/zod/config-inventory.ts
16799
- var ConfigScope = external_exports.enum(["user", "project", "local", "plugin"]);
16800
- var SkillScanEntry = external_exports.object({
16801
- name: external_exports.string().min(1),
16802
- // The identity source: a marketplace repo for plugin skills (e.g.
16803
- // 'anthropics/skills'), 'local' for personal ~/.claude/skills, or
16804
- // 'project:<repo-identity>' for checked-in project skills. The surrogate keeps
16805
- // a personal skill named 'pdf' from colliding with the marketplace 'pdf'.
16806
- source: external_exports.string().min(1),
16807
- scope: ConfigScope,
16808
- pluginName: external_exports.string().optional(),
16809
- // Volatile — rides the attribute bag, never the identity hash.
16810
- version: external_exports.string().optional(),
16811
- description: external_exports.string().optional(),
16812
- // Skill directory mtime (ISO) — the "updated Nd ago" freshness signal.
16813
- updatedAt: external_exports.iso.datetime().optional(),
16814
- // Filesystem path — the promoted inventory `location` column.
16815
- location: external_exports.string().optional()
16816
- });
16817
- var HookScanEntry = external_exports.object({
16818
- // Hook event name (PreToolUse, PostToolUse, …). Open string, not an enum: the
16819
- // set is harness-defined and grows without a schema change.
16820
- event: external_exports.string().min(1),
16821
- // The tool matcher ('Bash', 'Edit|Write', …). Absent = matches all tools.
16822
- matcher: external_exports.string().optional(),
16823
- command: external_exports.string().min(1),
16824
- timeout: external_exports.number().optional(),
16825
- scope: ConfigScope,
16826
- pluginName: external_exports.string().optional(),
16827
- // The settings file / hooks.json the entry came from.
16828
- location: external_exports.string().optional()
16829
- });
16830
- var McpServerScanEntry = external_exports.object({
16831
- // The server's config key ("github", "filesystem", …) — identity, with the
16832
- // qualified scope (see mcpServerIdentityKey).
16833
- name: external_exports.string().min(1),
16834
- scope: ConfigScope,
16835
- pluginName: external_exports.string().optional(),
16836
- // The owning plugin's marketplace — part of PLUGIN-scope identity: two
16837
- // marketplaces can each ship a plugin named `guard`, and without this their
16838
- // same-named servers would collapse to one row (the second silently dropped,
16839
- // inheriting the first's trust).
16840
- marketplace: external_exports.string().optional(),
16841
- // The repo identity (remote url, or the cwd for un-remoted repos) — part of
16842
- // PROJECT/LOCAL-scope identity: a server named `github` in repo A and one in
16843
- // repo B are different servers with different commands, and MUST NOT share a
16844
- // row — a shared row would let a cloned repo's .mcp.json inherit the trust
16845
- // the user granted elsewhere.
16846
- project: external_exports.string().optional(),
16847
- // 'stdio' when the entry carries a command; otherwise the config's `type`
16848
- // ('http' / 'sse' / …). Open string — the transport set is harness-defined.
16849
- transport: external_exports.string().min(1),
16850
- // Volatile on purpose (unlike hook `command`): a changed command/url is drift
16851
- // on a stable row — visible across config_scan snapshots and preserving the
16852
- // user's trust decision — never a quiet new row. One of the two is present.
16853
- // Secret-masked at collection time (the scanner runs the bundled detection
16854
- // packs over both — tokens routinely ride command args and URLs).
16855
- command: external_exports.string().optional(),
16856
- url: external_exports.string().optional(),
16857
- // Env var NAMES only, never values (the no-secrets rule).
16858
- envKeys: external_exports.array(external_exports.string()).optional(),
16859
- // The config file the entry came from.
16860
- location: external_exports.string().optional()
16861
- });
16862
- var ConfigFileScanEntry = external_exports.object({
16863
- // Basename (settings.json, CLAUDE.md) or dir name (commands/, agents/).
16864
- name: external_exports.string().min(1),
16865
- // The absolute path — identity (with scope) and the promoted `location`.
16866
- path: external_exports.string().min(1),
16867
- scope: ConfigScope,
16868
- // Human label: "User settings", "Project memory", "Slash commands", …
16869
- kind: external_exports.string().min(1),
16870
- // Derived SHAPE summary — top-level key names, entry counts, line counts.
16871
- // Never file content or values (memory files can carry sensitive detail).
16872
- detail: external_exports.string().optional(),
16873
- // Dir configs (commands/, agents/) and .mcp.json: how many entries.
16874
- entryCount: external_exports.number().optional(),
16875
- // File mtime (ISO) — the freshness signal.
16876
- updatedAt: external_exports.iso.datetime().optional()
16877
- });
16878
- var ConfigScanResult = external_exports.object({
16879
- scannedAt: external_exports.iso.datetime(),
16880
- skills: external_exports.array(SkillScanEntry),
16881
- hooks: external_exports.array(HookScanEntry),
16882
- mcpServers: external_exports.array(McpServerScanEntry),
16883
- configFiles: external_exports.array(ConfigFileScanEntry),
16884
- errors: external_exports.array(external_exports.object({ source: external_exports.string(), reason: external_exports.string() }))
16885
- });
16886
- var ConfigPostureFindingInput = external_exports.object({
16887
- ruleId: external_exports.string().min(1),
16888
- version: external_exports.string().min(1),
16889
- span: Span,
16890
- // For posture rules this is the offending COMMAND (config the user already
16891
- // holds locally, not captured secret content) — it is also the correlation
16892
- // key the read surface matches back to a hook row.
16893
- maskedMatch: external_exports.string(),
16894
- actionTaken: ActionTaken,
16895
- confidence: external_exports.number().min(0).max(1)
16896
- });
16897
- var ConfigScanRecord = external_exports.object({
16898
- items: external_exports.array(InventoryInput),
16899
- scanEvent: AuditEventInput,
16900
- definitions: external_exports.array(InspectionDefinitionInput).optional(),
16901
- findings: external_exports.array(ConfigPostureFindingInput).optional()
16902
- });
16903
-
16904
- // ../../packages/schema/src/zod/registry.ts
16905
- var Namespace = external_exports.string().regex(/^[a-z][a-z0-9-]*$/);
16906
- var PackId = external_exports.string().regex(/^[a-z][a-z0-9-]*$/);
16907
- var SemVer = external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?$/);
16908
- var PublisherKind = external_exports.enum(["labs", "user", "org"]);
16909
-
16910
16451
  // ../../packages/schema/src/zod/detection.ts
16911
16452
  var OriginEnum = external_exports.enum(["library"]).meta({ id: "OriginEnum" });
16912
16453
  var DetectionFilterEnum = external_exports.enum(["all", "library", "custom", "customized", "updates"]);
@@ -16951,81 +16492,306 @@ var ListDetectionsQuery = external_exports.object({
16951
16492
  filter: DetectionFilterEnum.optional().default("all"),
16952
16493
  q: external_exports.string().optional()
16953
16494
  });
16954
- var DetectionStats = external_exports.object({
16955
- detections: external_exports.number().int().nonnegative(),
16956
- rules: external_exports.number().int().nonnegative(),
16957
- active: external_exports.number().int().nonnegative(),
16958
- findingsLast30d: external_exports.number().int().nonnegative()
16959
- }).meta({ id: "DetectionStats" });
16960
- var DetectionRule = external_exports.object({
16961
- id: external_exports.string(),
16962
- name: external_exports.string(),
16963
- category: DetectionCategory,
16964
- severity: Severity,
16965
- matcher: Matcher
16966
- }).meta({ id: "DetectionRule" });
16967
- var DetectionUpdate = external_exports.object({
16968
- available: external_exports.boolean(),
16969
- latestVersion: SemVer,
16970
- // Rule count of the latest snapshot. Lets the update UI show a meaningful
16971
- // delta ("2 rules → 14 rules") when the version did NOT change but the rule
16972
- // content did — the OSS store compares content, not just version. Optional:
16973
- // registry-backed updates omit it.
16974
- latestRuleCount: external_exports.number().int().nonnegative().optional()
16975
- }).nullable().meta({ id: "DetectionUpdate" });
16976
- var DetectionDetail = external_exports.object({
16977
- id: external_exports.string(),
16978
- name: external_exports.string(),
16979
- version: SemVer,
16980
- enabled: external_exports.boolean(),
16981
- origin: OriginEnum,
16982
- publisher: Namespace.optional(),
16983
- publisherKind: PublisherKind.optional(),
16984
- ruleCount: external_exports.number().int().nonnegative(),
16985
- namespace: Namespace,
16986
- packId: PackId,
16987
- description: external_exports.string().optional(),
16988
- editedAt: external_exports.iso.datetime(),
16989
- findingsLast30d: external_exports.number().int().nonnegative(),
16990
- latestVersion: SemVer.nullable().optional(),
16991
- update: DetectionUpdate,
16992
- rules: external_exports.array(DetectionRule),
16993
- modified: external_exports.boolean(),
16994
- // Per-pack enforcement-policy assignment. Holds a BuiltinPolicyId ARCHETYPE
16995
- // (monitor|warn|redact|block) — NOT a policies-table Policy.id guid; a
16996
- // detection is a PACK, and its policy is the archetype applied to all its
16997
- // rules. Absent == unassigned, which resolves to Monitor everywhere
16998
- // (DEFAULT_PACK_POLICY_ID). Every enforcement surface expands it into
16999
- // per-rule policies (see policyIdToAction). Typed z.string() (not
17000
- // the enum) to keep the OpenAPI response tolerant of a future custom id.
17001
- policyId: external_exports.string().optional()
17002
- }).meta({ id: "DetectionDetail" });
17003
- var LibraryItem = external_exports.object({
17004
- id: external_exports.string(),
17005
- name: external_exports.string(),
17006
- publisher: Namespace,
17007
- publisherKind: PublisherKind.optional(),
17008
- // LOSSY single-category view of a pack. A pack MAY span several categories;
17009
- // this carries only the canonical-first one for display. Do NOT filter/facet
17010
- // on it — the library filter matches a pack's full category set (see
17011
- // ListLibraryResponse.categories).
17012
- category: DetectionCategory.optional(),
17013
- version: SemVer,
17014
- ruleCount: external_exports.number().int().nonnegative(),
17015
- description: external_exports.string().optional(),
17016
- updatedAt: external_exports.iso.datetime(),
17017
- state: LibraryStateEnum,
17018
- importedAs: external_exports.string().nullable()
17019
- }).meta({ id: "LibraryItem" });
17020
- var ListLibraryResponse = external_exports.object({
17021
- categories: external_exports.array(DetectionCategory),
17022
- items: external_exports.array(LibraryItem)
17023
- }).meta({ id: "ListLibraryResponse" });
17024
- var ImportDetectionRequest = external_exports.object({
17025
- libraryId: external_exports.string().refine((v) => /^[^/]+\/[^/]+$/.test(v), {
17026
- message: "libraryId must be in namespace/packId format"
17027
- })
17028
- }).meta({ id: "ImportDetectionRequest" });
16495
+ var DetectionStats = external_exports.object({
16496
+ detections: external_exports.number().int().nonnegative(),
16497
+ rules: external_exports.number().int().nonnegative(),
16498
+ active: external_exports.number().int().nonnegative(),
16499
+ findingsLast30d: external_exports.number().int().nonnegative()
16500
+ }).meta({ id: "DetectionStats" });
16501
+ var DetectionRule = external_exports.object({
16502
+ id: external_exports.string(),
16503
+ name: external_exports.string(),
16504
+ category: DetectionCategory,
16505
+ severity: Severity,
16506
+ matcher: Matcher
16507
+ }).meta({ id: "DetectionRule" });
16508
+ var DetectionUpdate = external_exports.object({
16509
+ available: external_exports.boolean(),
16510
+ latestVersion: SemVer,
16511
+ // Rule count of the latest snapshot. Lets the update UI show a meaningful
16512
+ // delta ("2 rules → 14 rules") when the version did NOT change but the rule
16513
+ // content did — the OSS store compares content, not just version. Optional:
16514
+ // registry-backed updates omit it.
16515
+ latestRuleCount: external_exports.number().int().nonnegative().optional()
16516
+ }).nullable().meta({ id: "DetectionUpdate" });
16517
+ var DetectionDetail = external_exports.object({
16518
+ id: external_exports.string(),
16519
+ name: external_exports.string(),
16520
+ version: SemVer,
16521
+ enabled: external_exports.boolean(),
16522
+ origin: OriginEnum,
16523
+ publisher: Namespace.optional(),
16524
+ publisherKind: PublisherKind.optional(),
16525
+ ruleCount: external_exports.number().int().nonnegative(),
16526
+ namespace: Namespace,
16527
+ packId: PackId,
16528
+ description: external_exports.string().optional(),
16529
+ editedAt: external_exports.iso.datetime(),
16530
+ findingsLast30d: external_exports.number().int().nonnegative(),
16531
+ latestVersion: SemVer.nullable().optional(),
16532
+ update: DetectionUpdate,
16533
+ rules: external_exports.array(DetectionRule),
16534
+ modified: external_exports.boolean(),
16535
+ // Per-pack enforcement-policy assignment. Holds a BuiltinPolicyId ARCHETYPE
16536
+ // (monitor|warn|redact|block) — NOT a policies-table Policy.id guid; a
16537
+ // detection is a PACK, and its policy is the archetype applied to all its
16538
+ // rules. Absent == unassigned, which resolves to Monitor everywhere
16539
+ // (DEFAULT_PACK_POLICY_ID). Every enforcement surface expands it into
16540
+ // per-rule policies (see policyIdToAction). Typed z.string() (not
16541
+ // the enum) to keep the OpenAPI response tolerant of a future custom id.
16542
+ policyId: external_exports.string().optional()
16543
+ }).meta({ id: "DetectionDetail" });
16544
+ var LibraryItem = external_exports.object({
16545
+ id: external_exports.string(),
16546
+ name: external_exports.string(),
16547
+ publisher: Namespace,
16548
+ publisherKind: PublisherKind.optional(),
16549
+ // LOSSY single-category view of a pack. A pack MAY span several categories;
16550
+ // this carries only the canonical-first one for display. Do NOT filter/facet
16551
+ // on it — the library filter matches a pack's full category set (see
16552
+ // ListLibraryResponse.categories).
16553
+ category: DetectionCategory.optional(),
16554
+ version: SemVer,
16555
+ ruleCount: external_exports.number().int().nonnegative(),
16556
+ description: external_exports.string().optional(),
16557
+ updatedAt: external_exports.iso.datetime(),
16558
+ state: LibraryStateEnum,
16559
+ importedAs: external_exports.string().nullable()
16560
+ }).meta({ id: "LibraryItem" });
16561
+ var ListLibraryResponse = external_exports.object({
16562
+ categories: external_exports.array(DetectionCategory),
16563
+ items: external_exports.array(LibraryItem)
16564
+ }).meta({ id: "ListLibraryResponse" });
16565
+ var ImportDetectionRequest = external_exports.object({
16566
+ libraryId: external_exports.string().refine((v) => /^[^/]+\/[^/]+$/.test(v), {
16567
+ message: "libraryId must be in namespace/packId format"
16568
+ })
16569
+ }).meta({ id: "ImportDetectionRequest" });
16570
+
16571
+ // ../../packages/schema/src/zod/inventory.ts
16572
+ var AssetType = external_exports.enum(["project", "skill", "mcp", "hook", "config"]).meta({ id: "AssetType" });
16573
+ var AccessLevel = external_exports.enum(["open", "approved", "blocked"]).meta({ id: "AccessLevel" });
16574
+ var Origin = external_exports.enum(["source", "public-dep", "vendored", "config", "data", "docs", "generated"]).meta({ id: "Origin" });
16575
+ var TrustLevel = external_exports.enum(["known-good", "risky", "unapproved"]).meta({ id: "TrustLevel" });
16576
+ var Flag = external_exports.enum(["update", "stale", "conflict", "unknown", "change", "untracked", "risk", "findings"]).meta({ id: "Flag" });
16577
+ var Visibility = external_exports.enum(["public", "private"]).meta({ id: "Visibility" });
16578
+ var HarnessEventKind = external_exports.enum(["block", "redact", "warn"]).meta({ id: "HarnessEventKind" });
16579
+ var HarnessId = Harness.extract(["ClaudeCode", "Cursor", "Codex", "Antigravity"]).meta({
16580
+ id: "HarnessId"
16581
+ });
16582
+ var AccessCounts = external_exports.object({
16583
+ open: external_exports.number().int().nonnegative(),
16584
+ approved: external_exports.number().int().nonnegative(),
16585
+ blocked: external_exports.number().int().nonnegative(),
16586
+ total: external_exports.number().int().nonnegative()
16587
+ }).meta({ id: "AccessCounts" });
16588
+ var AssetSummary = external_exports.object({
16589
+ id: external_exports.string(),
16590
+ type: AssetType,
16591
+ name: external_exports.string(),
16592
+ sub: external_exports.string(),
16593
+ flags: external_exports.array(Flag),
16594
+ /** MCP servers only — omitted for all other types. */
16595
+ trust: TrustLevel.optional()
16596
+ }).meta({ id: "AssetSummary" });
16597
+ var ProjectSummary = external_exports.object({
16598
+ id: external_exports.string(),
16599
+ name: external_exports.string(),
16600
+ repo: external_exports.string(),
16601
+ visibility: Visibility,
16602
+ language: external_exports.string(),
16603
+ policyDefault: AccessLevel,
16604
+ updatedAt: external_exports.iso.datetime(),
16605
+ accessCounts: AccessCounts,
16606
+ findingsCount: external_exports.number().int().nonnegative()
16607
+ }).meta({ id: "ProjectSummary" });
16608
+ var HarnessCategory = external_exports.object({
16609
+ /** One of config/skill/mcp/hook — never project (enforced at service layer). */
16610
+ type: AssetType,
16611
+ assets: external_exports.array(AssetSummary)
16612
+ });
16613
+ var HarnessSummary = external_exports.object({
16614
+ id: HarnessId,
16615
+ label: external_exports.string(),
16616
+ kind: external_exports.string(),
16617
+ version: external_exports.string(),
16618
+ sessions: external_exports.number().int().nonnegative(),
16619
+ assetCount: external_exports.number().int().nonnegative(),
16620
+ flagCount: external_exports.number().int().nonnegative(),
16621
+ projects: external_exports.array(ProjectSummary),
16622
+ categories: external_exports.array(HarnessCategory)
16623
+ }).meta({ id: "HarnessSummary" });
16624
+ var ListHarnessesResponse = external_exports.object({ items: external_exports.array(HarnessSummary) }).meta({ id: "ListHarnessesResponse" });
16625
+ var AssetGroup = external_exports.object({
16626
+ /** Group key — never project (enforced at service layer). */
16627
+ type: AssetType,
16628
+ total: external_exports.number().int().nonnegative(),
16629
+ /**
16630
+ * MCP group only — omitted for all other types.
16631
+ * Partial: only TrustLevel keys with non-zero counts are included.
16632
+ * Strict: unknown keys are rejected — only TrustLevel values are valid keys.
16633
+ */
16634
+ trustRollup: external_exports.object({
16635
+ "known-good": external_exports.number().int().nonnegative(),
16636
+ risky: external_exports.number().int().nonnegative(),
16637
+ unapproved: external_exports.number().int().nonnegative()
16638
+ }).partial().strict().optional(),
16639
+ /**
16640
+ * Partial: only Flag keys with non-zero counts are included.
16641
+ * Strict: unknown keys are rejected — only Flag values are valid keys.
16642
+ */
16643
+ flagRollup: external_exports.object({
16644
+ update: external_exports.number().int().nonnegative(),
16645
+ stale: external_exports.number().int().nonnegative(),
16646
+ conflict: external_exports.number().int().nonnegative(),
16647
+ unknown: external_exports.number().int().nonnegative(),
16648
+ change: external_exports.number().int().nonnegative(),
16649
+ untracked: external_exports.number().int().nonnegative(),
16650
+ risk: external_exports.number().int().nonnegative(),
16651
+ findings: external_exports.number().int().nonnegative()
16652
+ }).partial().strict(),
16653
+ items: external_exports.array(AssetSummary)
16654
+ }).meta({ id: "AssetGroup" });
16655
+ var ListAssetsResponse = external_exports.object({ groups: external_exports.array(AssetGroup) }).meta({ id: "ListAssetsResponse" });
16656
+ var McpTool = external_exports.object({
16657
+ name: external_exports.string(),
16658
+ signature: external_exports.string(),
16659
+ description: external_exports.string(),
16660
+ write: external_exports.boolean(),
16661
+ /** Non-null string when tool is dangerous / blocked; null otherwise. */
16662
+ risk: external_exports.string().nullable()
16663
+ }).meta({ id: "McpTool" });
16664
+ var AssetFindingRef = external_exports.object({
16665
+ id: external_exports.string(),
16666
+ title: external_exports.string(),
16667
+ note: external_exports.string()
16668
+ });
16669
+ var AssetDetail = AssetSummary.extend({
16670
+ /** string | null — null when no description is available. */
16671
+ description: external_exports.string().nullable(),
16672
+ /** trustLevel | null — null for non-MCP assets. */
16673
+ trust: TrustLevel.nullable(),
16674
+ /** Type-specific raw key/values — FE renders the grid. */
16675
+ meta: external_exports.record(external_exports.string(), external_exports.unknown()),
16676
+ /** always present — object when there is an active finding, null when absent. */
16677
+ finding: AssetFindingRef.nullable(),
16678
+ /** MCP exposed-tools list — omitted for non-mcp. */
16679
+ tools: external_exports.array(McpTool).optional()
16680
+ }).meta({ id: "AssetDetail" });
16681
+ var ListProjectsResponse = external_exports.object({ items: external_exports.array(ProjectSummary) }).meta({ id: "ListProjectsResponse" });
16682
+ var InventoryStats = external_exports.object({
16683
+ /** Total assets/projects with ≥1 flag or finding (drives the attention header chip). */
16684
+ attention: external_exports.number().int().nonnegative(),
16685
+ byType: external_exports.object({
16686
+ project: external_exports.number().int().nonnegative(),
16687
+ skill: external_exports.number().int().nonnegative(),
16688
+ mcp: external_exports.number().int().nonnegative(),
16689
+ hook: external_exports.number().int().nonnegative(),
16690
+ config: external_exports.number().int().nonnegative()
16691
+ }),
16692
+ harnesses: external_exports.number().int().nonnegative(),
16693
+ mcpTrust: external_exports.object({
16694
+ "known-good": external_exports.number().int().nonnegative(),
16695
+ risky: external_exports.number().int().nonnegative(),
16696
+ unapproved: external_exports.number().int().nonnegative()
16697
+ })
16698
+ }).meta({ id: "InventoryStats" });
16699
+ var FileSummary = external_exports.object({
16700
+ path: external_exports.string(),
16701
+ name: external_exports.string(),
16702
+ origin: Origin,
16703
+ /** Effective access (override applied). */
16704
+ access: AccessLevel,
16705
+ /** True when a file_access_override differs from the computed default. */
16706
+ isCustom: external_exports.boolean(),
16707
+ findings: external_exports.number().int().nonnegative(),
16708
+ /** When the file was auto-blocked by a detection; null when not blocked. */
16709
+ blockedAt: external_exports.iso.datetime().nullable().optional(),
16710
+ /** Why the file was blocked; null when absent. */
16711
+ note: external_exports.string().nullable().optional()
16712
+ }).meta({ id: "FileSummary" });
16713
+ var FolderSummary = external_exports.object({
16714
+ name: external_exports.string(),
16715
+ path: external_exports.string(),
16716
+ /** Rollup of effective access across all descendants. */
16717
+ accessCounts: AccessCounts
16718
+ }).meta({ id: "FolderSummary" });
16719
+ var ProjectTreeResponse = external_exports.object({
16720
+ project: external_exports.object({
16721
+ id: external_exports.string(),
16722
+ repo: external_exports.string(),
16723
+ visibility: Visibility
16724
+ }),
16725
+ path: external_exports.string(),
16726
+ /** Browse mode: one-level folders at the current path. Omitted in search mode. */
16727
+ folders: external_exports.array(FolderSummary).optional(),
16728
+ files: external_exports.array(FileSummary)
16729
+ }).meta({ id: "ProjectTreeResponse" });
16730
+ var FileDetail = FileSummary.extend({
16731
+ project: external_exports.object({
16732
+ repo: external_exports.string(),
16733
+ visibility: Visibility,
16734
+ language: external_exports.string(),
16735
+ policyDefault: AccessLevel,
16736
+ updatedAt: external_exports.iso.datetime()
16737
+ }),
16738
+ findingsRefs: external_exports.array(external_exports.object({ id: external_exports.string(), title: external_exports.string() }))
16739
+ }).meta({ id: "FileDetail" });
16740
+ var SetFileAccessBody = external_exports.object({
16741
+ path: external_exports.string(),
16742
+ access: AccessLevel
16743
+ }).meta({ id: "SetFileAccessBody" });
16744
+ var SetFileAccessResponse = external_exports.object({
16745
+ file: FileSummary,
16746
+ accessCounts: AccessCounts
16747
+ }).meta({ id: "SetFileAccessResponse" });
16748
+ var SetMcpTrustBody = external_exports.object({ trust: TrustLevel }).meta({ id: "SetMcpTrustBody" });
16749
+ var HarnessEventItem = external_exports.object({
16750
+ kind: HarnessEventKind,
16751
+ title: external_exports.string(),
16752
+ detail: external_exports.string(),
16753
+ occurredAt: external_exports.iso.datetime(),
16754
+ findingId: external_exports.string().nullable().optional()
16755
+ }).meta({ id: "HarnessEventItem" });
16756
+ var HarnessEventsResponse = external_exports.object({
16757
+ counts: external_exports.object({
16758
+ block: external_exports.number().int().nonnegative(),
16759
+ redact: external_exports.number().int().nonnegative(),
16760
+ warn: external_exports.number().int().nonnegative()
16761
+ }),
16762
+ items: external_exports.array(HarnessEventItem)
16763
+ }).meta({ id: "HarnessEventsResponse" });
16764
+ var RescanResponse = external_exports.object({
16765
+ jobId: external_exports.string(),
16766
+ startedAt: external_exports.iso.datetime()
16767
+ }).meta({ id: "RescanResponse" });
16768
+ var ConnectProjectBody = external_exports.object({ repo: external_exports.string() }).meta({ id: "ConnectProjectBody" });
16769
+ var ListAssetsQuery = external_exports.object({
16770
+ /** Filter by one or more AssetType values; absent means all types. */
16771
+ type: external_exports.array(AssetType).optional(),
16772
+ /** Free-text search term. */
16773
+ q: external_exports.string().optional()
16774
+ });
16775
+ var GetProjectTreeQuery = external_exports.object({
16776
+ /** Subtree root path; defaults to repository root when absent. */
16777
+ path: external_exports.string().optional(),
16778
+ /** Free-text filter applied to file paths. */
16779
+ q: external_exports.string().optional(),
16780
+ /**
16781
+ * Special listing mode. `blocked` returns every effectively-blocked, auto-blocked
16782
+ * file across the whole repo (folders omitted, most-recent first), ignoring
16783
+ * `path`/`q` — powers the project-wide "recently blocked" strip.
16784
+ */
16785
+ filter: external_exports.enum(["blocked"]).optional()
16786
+ });
16787
+ var GetProjectFileQuery = external_exports.object({
16788
+ /** Repository-relative file path; absent or empty → 400. */
16789
+ path: external_exports.string()
16790
+ });
16791
+ var GetHarnessEventsQuery = external_exports.object({
16792
+ /** Maximum number of events to return. Range: 1–50; default: 7. */
16793
+ limit: external_exports.coerce.number().int().min(1).max(50).default(7)
16794
+ });
17029
16795
 
17030
16796
  // ../../packages/schema/src/zod/shares.ts
17031
16797
  var DestinationKind = external_exports.enum(["provider", "internal", "external", "ip"]).meta({ id: "DestinationKind" });
@@ -17161,77 +16927,198 @@ var ListShareDestinationsQuery = external_exports.object({
17161
16927
  */
17162
16928
  review: external_exports.stringbool().default(false)
17163
16929
  });
17164
- var ExportSharesQuery = external_exports.object({
17165
- format: external_exports.enum(["csv", "json"]).default("csv"),
17166
- q: external_exports.string().optional(),
17167
- kind: external_exports.array(DestinationKind).optional()
16930
+ var ExportSharesQuery = external_exports.object({
16931
+ format: external_exports.enum(["csv", "json"]).default("csv"),
16932
+ q: external_exports.string().optional(),
16933
+ kind: external_exports.array(DestinationKind).optional()
16934
+ });
16935
+
16936
+ // ../../packages/schema/src/zod/egress-extraction.ts
16937
+ var EgressEcosystem = external_exports.enum(["npm", "pypi", "go", "maven", "rubygems", "cargo", "composer", "nuget"]).meta({ id: "EgressEcosystem" });
16938
+ var ProviderRegistryEntry = external_exports.object({
16939
+ id: external_exports.string(),
16940
+ name: external_exports.string(),
16941
+ category: external_exports.string(),
16942
+ /** Suffix-matched: 'stripe.com' matches api.stripe.com, never evilstripe.com. */
16943
+ hostSuffixes: external_exports.array(external_exports.string()).min(1),
16944
+ /** Canonical API base URL recorded for manifest-derived (method 'SDK') endpoints. */
16945
+ apiBase: external_exports.string(),
16946
+ /** Most-sensitive first; index 0 becomes the endpoint dataClass. */
16947
+ defaultDataClasses: external_exports.array(DataClass).min(1),
16948
+ /** SDK identifiers per ecosystem ('go' prefix-matched by path, 'maven' by group-id prefix). */
16949
+ sdks: external_exports.partialRecord(EgressEcosystem, external_exports.array(external_exports.string()))
16950
+ }).meta({ id: "ProviderRegistryEntry" });
16951
+ var EgressCallSiteHit = external_exports.object({
16952
+ file: external_exports.string(),
16953
+ line: external_exports.number().int().positive(),
16954
+ snippet: external_exports.string(),
16955
+ dynamic: external_exports.boolean(),
16956
+ vendored: external_exports.boolean()
16957
+ }).meta({ id: "EgressCallSiteHit" });
16958
+ var ResolvedEgressHit = external_exports.object({
16959
+ host: external_exports.string(),
16960
+ kind: DestinationKind,
16961
+ name: external_exports.string(),
16962
+ category: external_exports.string(),
16963
+ trust: ShareTrustLevel,
16964
+ network: DestinationNetwork.nullable(),
16965
+ method: HttpMethod,
16966
+ transport: Transport,
16967
+ url: external_exports.string(),
16968
+ template: external_exports.boolean(),
16969
+ dataClass: DataClass,
16970
+ site: EgressCallSiteHit
16971
+ }).meta({ id: "ResolvedEgressHit" });
16972
+ var EgressReconcile = external_exports.discriminatedUnion("mode", [
16973
+ external_exports.object({ mode: external_exports.literal("walk"), walkedPrefix: external_exports.string() }),
16974
+ external_exports.object({
16975
+ mode: external_exports.literal("ledger"),
16976
+ scannedFiles: external_exports.array(external_exports.string()),
16977
+ deletedFiles: external_exports.array(external_exports.string())
16978
+ })
16979
+ ]).meta({ id: "EgressReconcile" });
16980
+ var RecordProjectEgressInput = external_exports.object({
16981
+ /** Stable reconcile key: 'git:<repo identity>' or 'path:<abs root>' (non-git). */
16982
+ projectKey: external_exports.string().min(1),
16983
+ /** Display name only — never keys reconciliation. */
16984
+ project: external_exports.string(),
16985
+ projectId: external_exports.string().nullable(),
16986
+ reconcile: EgressReconcile,
16987
+ hits: external_exports.array(ResolvedEgressHit)
16988
+ }).meta({ id: "RecordProjectEgressInput" });
16989
+ var EgressWriteSummary = external_exports.object({
16990
+ destinations: external_exports.number().int().nonnegative(),
16991
+ endpoints: external_exports.number().int().nonnegative(),
16992
+ callSites: external_exports.number().int().nonnegative(),
16993
+ truncated: external_exports.boolean(),
16994
+ /**
16995
+ * Files the cap dropped whole. Their stored rows were left untouched, so a
16996
+ * ledger-keeping caller must withhold their ledger entries and read them
16997
+ * again next scan.
16998
+ */
16999
+ droppedFiles: external_exports.array(external_exports.string()).default([])
17000
+ }).meta({ id: "EgressWriteSummary" });
17001
+
17002
+ // ../../packages/schema/src/zod/event.ts
17003
+ var EventKind = external_exports.enum(["prompt", "response", "code_change", "tool_use"]).meta({ id: "EventKind" });
17004
+ var CAPTURE_EVENT_TYPES_SQL = EventKind.options.map((k) => `'${k}'`).join(",");
17005
+ var EventMetadata = external_exports.object({
17006
+ sessionId: external_exports.string().optional(),
17007
+ repo: external_exports.string().optional(),
17008
+ filePath: external_exports.string().optional(),
17009
+ // The host tool whose input/output was scanned (e.g. 'Bash', 'WebFetch'),
17010
+ // set by the tool-scanning hooks. The tool NAME only — never the tool's
17011
+ // arguments or output, which can carry the very value a finding masked
17012
+ // (metadata is stored unredacted). Gives findings on non-file captures a
17013
+ // display location ("via Bash") when no filePath exists.
17014
+ toolName: external_exports.string().optional(),
17015
+ // Set (true) by the worktree scanner when the file is excluded by the
17016
+ // repo's .gitignore. Gitignored files ARE still scanned — local scratch and
17017
+ // generated code can leak real secrets — but the provenance is recorded so
17018
+ // policy/dashboards can treat those findings as informational rather than
17019
+ // blocking. Omitted (not false) for tracked files and non-scan events.
17020
+ gitignored: external_exports.boolean().optional(),
17021
+ // Set (true) ONLY when the event's `content` is the COMPLETE file at
17022
+ // capture time (a worktree scan reading from disk). Hook-captured edits
17023
+ // (e.g. an Edit tool's new_string) are partial fragments and MUST NOT set
17024
+ // this. The resolver-on-ingest keys its fixed-at-source dropout
17025
+ // diff on this marker: only a whole-file snapshot can prove a previously
17026
+ // open finding is gone; a fragment's absence proves nothing (the secret
17027
+ // may live outside the hunk). Omitted (not false) for fragments and
17028
+ // non-scan events, so pre-marker clients safely default to the
17029
+ // non-authoritative path.
17030
+ wholeFile: external_exports.boolean().optional(),
17031
+ model: external_exports.string().optional(),
17032
+ turnIndex: external_exports.number().int().nonnegative().optional(),
17033
+ // Distributed-tracing correlation. `correlationId` ties a recorded event back
17034
+ // to the request that captured/ingested it (a UUID, generated independently of
17035
+ // the trace id); `traceId` is the W3C trace id (32 lowercase hex chars) of the
17036
+ // originating span when telemetry is enabled. Both optional + backward
17037
+ // compatible — populated by the plugin (see @akasecurity/plugin-sdk).
17038
+ correlationId: external_exports.uuid().optional(),
17039
+ traceId: external_exports.string().regex(/^[0-9a-f]{32}$/).optional(),
17040
+ // Ids of the detection exceptions that downgraded findings in this capture
17041
+ // to 'allow' — the enforcement audit trail's link back to the grant that
17042
+ // authorized the bypass. Absent on captures where no exception applied.
17043
+ exceptionIds: external_exports.array(external_exports.guid()).optional()
17044
+ }).meta({ id: "EventMetadata" });
17045
+ var Event = external_exports.object({
17046
+ id: external_exports.guid(),
17047
+ sourceTool: SourceTool,
17048
+ kind: EventKind,
17049
+ occurredAt: external_exports.iso.datetime(),
17050
+ contentHash: external_exports.string(),
17051
+ content: external_exports.string(),
17052
+ metadata: EventMetadata.optional()
17053
+ }).meta({ id: "Event" });
17054
+ var IngestEvent = Event.meta({ id: "IngestEvent" });
17055
+ var IngestBatch = external_exports.object({
17056
+ events: external_exports.array(IngestEvent).min(1).max(100),
17057
+ // Dedup policy for this batch. Id-dedup ALWAYS applies. 'content-hash'
17058
+ // additionally rejects any event whose contentHash the store has already
17059
+ // recorded — for re-runnable bulk ingest (worktree scan, transcript
17060
+ // backfill), where a re-run mints fresh event ids for identical content and
17061
+ // would otherwise accumulate duplicates. Live hook traffic must NOT set it:
17062
+ // two genuinely separate prompts can be byte-identical and both belong on
17063
+ // the timeline.
17064
+ dedupe: external_exports.literal("content-hash").optional()
17065
+ }).meta({ id: "IngestBatch" });
17066
+
17067
+ // ../../packages/schema/src/zod/exception.ts
17068
+ var ExceptionScope = external_exports.enum(["once", "temporary", "permanent"]);
17069
+ var ExceptionConditions = external_exports.object({
17070
+ repo: external_exports.string().optional(),
17071
+ sourceTool: external_exports.string().optional(),
17072
+ provider: external_exports.string().optional()
17073
+ }).strict();
17074
+ var ExceptionCapability = external_exports.enum(["suppress", "reveal_to_model"]);
17075
+ var DetectionException = external_exports.object({
17076
+ id: external_exports.guid(),
17077
+ ruleId: external_exports.string(),
17078
+ // Denormalized from the rule, for reporting — never matched on.
17079
+ category: DetectionCategory,
17080
+ // HMAC-SHA256 hex of the raw match under a machine-local key: a KEYED
17081
+ // fingerprint, never the raw value, and never reversible. Matching recomputes
17082
+ // the fingerprint from a fresh capture; the value itself is never stored.
17083
+ // Shape-constrained so a malformed — or accidentally raw — value is rejected
17084
+ // at the boundary rather than persisted.
17085
+ valueFingerprint: external_exports.string().regex(/^[0-9a-f]{64}$/),
17086
+ // Version of the fingerprint key the grant was written under; a rotated key
17087
+ // invalidates old grants rather than silently mismatching them.
17088
+ keyVersion: external_exports.number().int().positive(),
17089
+ // maskMatch() preview of the approved value — never the raw value.
17090
+ maskedValue: external_exports.string(),
17091
+ capability: ExceptionCapability.default("suppress"),
17092
+ scope: ExceptionScope,
17093
+ expiresAt: external_exports.iso.datetime().nullable(),
17094
+ maxUses: external_exports.number().int().positive().nullable(),
17095
+ useCount: external_exports.number().int().nonnegative(),
17096
+ lastUsedAt: external_exports.iso.datetime().nullable(),
17097
+ // Mandatory: every grant carries the human reason it exists.
17098
+ justification: external_exports.string().min(1),
17099
+ conditions: ExceptionConditions.nullable(),
17100
+ createdBy: external_exports.string(),
17101
+ createdVia: external_exports.enum(["cli-approve", "cli-add", "web-approve", "web-add", "api", "setup-triage"]),
17102
+ createdAt: external_exports.iso.datetime(),
17103
+ updatedAt: external_exports.iso.datetime(),
17104
+ // Revocation is terminal and retained — consumed/expired/revoked rows are
17105
+ // audit evidence; nothing in the exception lifecycle hard-deletes.
17106
+ revokedAt: external_exports.iso.datetime().nullable(),
17107
+ revokedBy: external_exports.string().nullable(),
17108
+ revokeReason: external_exports.string().nullable()
17109
+ });
17110
+ var ExceptionBundleEntry = DetectionException.pick({
17111
+ id: true,
17112
+ ruleId: true,
17113
+ valueFingerprint: true,
17114
+ keyVersion: true,
17115
+ capability: true,
17116
+ expiresAt: true,
17117
+ maxUses: true,
17118
+ useCount: true,
17119
+ conditions: true
17168
17120
  });
17169
-
17170
- // ../../packages/schema/src/zod/egress-extraction.ts
17171
- var EgressEcosystem = external_exports.enum(["npm", "pypi", "go", "maven", "rubygems", "cargo", "composer", "nuget"]).meta({ id: "EgressEcosystem" });
17172
- var ProviderRegistryEntry = external_exports.object({
17173
- id: external_exports.string(),
17174
- name: external_exports.string(),
17175
- category: external_exports.string(),
17176
- /** Suffix-matched: 'stripe.com' matches api.stripe.com, never evilstripe.com. */
17177
- hostSuffixes: external_exports.array(external_exports.string()).min(1),
17178
- /** Canonical API base URL recorded for manifest-derived (method 'SDK') endpoints. */
17179
- apiBase: external_exports.string(),
17180
- /** Most-sensitive first; index 0 becomes the endpoint dataClass. */
17181
- defaultDataClasses: external_exports.array(DataClass).min(1),
17182
- /** SDK identifiers per ecosystem ('go' prefix-matched by path, 'maven' by group-id prefix). */
17183
- sdks: external_exports.partialRecord(EgressEcosystem, external_exports.array(external_exports.string()))
17184
- }).meta({ id: "ProviderRegistryEntry" });
17185
- var EgressCallSiteHit = external_exports.object({
17186
- file: external_exports.string(),
17187
- line: external_exports.number().int().positive(),
17188
- snippet: external_exports.string(),
17189
- dynamic: external_exports.boolean(),
17190
- vendored: external_exports.boolean()
17191
- }).meta({ id: "EgressCallSiteHit" });
17192
- var ResolvedEgressHit = external_exports.object({
17193
- host: external_exports.string(),
17194
- kind: DestinationKind,
17195
- name: external_exports.string(),
17196
- category: external_exports.string(),
17197
- trust: ShareTrustLevel,
17198
- network: DestinationNetwork.nullable(),
17199
- method: HttpMethod,
17200
- transport: Transport,
17201
- url: external_exports.string(),
17202
- template: external_exports.boolean(),
17203
- dataClass: DataClass,
17204
- site: EgressCallSiteHit
17205
- }).meta({ id: "ResolvedEgressHit" });
17206
- var EgressReconcile = external_exports.discriminatedUnion("mode", [
17207
- external_exports.object({ mode: external_exports.literal("walk"), walkedPrefix: external_exports.string() }),
17208
- external_exports.object({
17209
- mode: external_exports.literal("ledger"),
17210
- scannedFiles: external_exports.array(external_exports.string()),
17211
- deletedFiles: external_exports.array(external_exports.string())
17212
- })
17213
- ]).meta({ id: "EgressReconcile" });
17214
- var RecordProjectEgressInput = external_exports.object({
17215
- /** Stable reconcile key: 'git:<repo identity>' or 'path:<abs root>' (non-git). */
17216
- projectKey: external_exports.string().min(1),
17217
- /** Display name only — never keys reconciliation. */
17218
- project: external_exports.string(),
17219
- projectId: external_exports.string().nullable(),
17220
- reconcile: EgressReconcile,
17221
- hits: external_exports.array(ResolvedEgressHit)
17222
- }).meta({ id: "RecordProjectEgressInput" });
17223
- var EgressWriteSummary = external_exports.object({
17224
- destinations: external_exports.number().int().nonnegative(),
17225
- endpoints: external_exports.number().int().nonnegative(),
17226
- callSites: external_exports.number().int().nonnegative(),
17227
- truncated: external_exports.boolean(),
17228
- /**
17229
- * Files the cap dropped whole. Their stored rows were left untouched, so a
17230
- * ledger-keeping caller must withhold their ledger entries and read them
17231
- * again next scan.
17232
- */
17233
- droppedFiles: external_exports.array(external_exports.string()).default([])
17234
- }).meta({ id: "EgressWriteSummary" });
17121
+ var ExceptionDescriptor = DetectionException.omit({ valueFingerprint: true });
17235
17122
 
17236
17123
  // ../../packages/schema/src/zod/exception-action.ts
17237
17124
  var confirmation = external_exports.string().optional();
@@ -17444,7 +17331,13 @@ var VaultConsent = external_exports.object({
17444
17331
 
17445
17332
  // ../../packages/schema/src/zod/local.ts
17446
17333
  var WORKSPACE_SETTINGS_SPEC_VERSION = 5;
17447
- var RunMode = external_exports.enum(["standalone"]);
17334
+ var RunMode = external_exports.enum(["standalone", "attached"]);
17335
+ var ControlPlaneConnection = external_exports.object({
17336
+ endpoint: external_exports.string().min(1),
17337
+ // Display name for the deployment, shown instead of the raw endpoint.
17338
+ label: external_exports.string().min(1).optional(),
17339
+ attachedAt: external_exports.iso.datetime()
17340
+ }).meta({ id: "ControlPlaneConnection" });
17448
17341
  var SimpleDetectionPolicy = external_exports.enum(["redact", "warn"]);
17449
17342
  var HistoricalAccess = external_exports.enum(["full", "session-only"]);
17450
17343
  var ModelJudgeConsent = external_exports.object({
@@ -17453,12 +17346,10 @@ var ModelJudgeConsent = external_exports.object({
17453
17346
  });
17454
17347
  var WorkspaceSettings = external_exports.object({
17455
17348
  specVersion: external_exports.number().int().positive().default(WORKSPACE_SETTINGS_SPEC_VERSION),
17456
- // Settings files written by earlier releases may carry the retired 'attached'
17457
- // value; it parses as 'standalone' so those files keep loading.
17458
- runMode: external_exports.preprocess(
17459
- (v) => v === "attached" ? "standalone" : v,
17460
- RunMode.default("standalone")
17461
- ),
17349
+ runMode: RunMode.default("standalone"),
17350
+ // Present only while attached; a detach clears it. Its presence is what makes
17351
+ // `runMode: 'attached'` mean anything — see isAttached.
17352
+ controlPlane: ControlPlaneConnection.optional(),
17462
17353
  policy: SimpleDetectionPolicy.default("redact"),
17463
17354
  // Consent for scanning pre-install surfaces; opt-in (see HistoricalAccess).
17464
17355
  historicalAccess: HistoricalAccess.default("session-only"),
@@ -17484,6 +17375,195 @@ var WorkspaceSettings = external_exports.object({
17484
17375
  modelJudgeConsent: ModelJudgeConsent.optional()
17485
17376
  });
17486
17377
 
17378
+ // ../../packages/schema/src/zod/managed.ts
17379
+ var MANAGED_SETTINGS_SPEC_VERSION = 1;
17380
+ var ManagedSettingKey = external_exports.enum([
17381
+ "runMode",
17382
+ "historicalAccess",
17383
+ "vaultConsent",
17384
+ "vaultKeyCustody",
17385
+ "vaultInlineReveal",
17386
+ "modelJudgeConsent",
17387
+ "dataSharesInPlace"
17388
+ ]).meta({ id: "ManagedSettingKey" });
17389
+ var ManagedSettingsValues = external_exports.object({
17390
+ runMode: external_exports.enum(["standalone", "attached"]).optional(),
17391
+ controlPlane: external_exports.object({
17392
+ endpoint: external_exports.string().min(1),
17393
+ label: external_exports.string().min(1).optional()
17394
+ }).optional(),
17395
+ historicalAccess: external_exports.enum(["full", "session-only"]).optional(),
17396
+ vaultConsent: external_exports.boolean().optional(),
17397
+ vaultKeyCustody: external_exports.enum(["file", "keychain"]).optional(),
17398
+ vaultInlineReveal: external_exports.enum(["masked", "full", "off"]).optional(),
17399
+ modelJudgeConsent: external_exports.boolean().optional(),
17400
+ dataSharesInPlace: external_exports.boolean().optional()
17401
+ }).meta({ id: "ManagedSettingsValues" });
17402
+ var ManagedSettings = external_exports.object({
17403
+ specVersion: external_exports.number().int().positive().default(MANAGED_SETTINGS_SPEC_VERSION),
17404
+ // Shown on every locked control, so the user can tell an administrative
17405
+ // decision from a bug. Absent renders as a generic "your organization".
17406
+ organization: external_exports.string().min(1).optional(),
17407
+ // What the administrator pinned.
17408
+ values: ManagedSettingsValues.default({}),
17409
+ // Which of those the user may not change. A key here with no matching value
17410
+ // freezes whatever the user last chose; a value with no lock is a DEFAULT
17411
+ // the user may still override. The two are separable on purpose.
17412
+ lockedFields: external_exports.array(ManagedSettingKey).default([])
17413
+ }).meta({ id: "ManagedSettings" });
17414
+
17415
+ // ../../packages/schema/src/zod/policy.ts
17416
+ var PolicyScope = external_exports.enum(["global", "repo", "user"]).meta({ id: "PolicyScope" });
17417
+ var PolicyTarget = external_exports.union([external_exports.object({ ruleId: external_exports.string() }), external_exports.object({ category: DetectionCategory })]).meta({ id: "PolicyTarget" });
17418
+ var Policy = external_exports.object({
17419
+ id: external_exports.guid(),
17420
+ scope: PolicyScope,
17421
+ target: PolicyTarget,
17422
+ action: ActionTaken,
17423
+ enabled: external_exports.boolean().default(true),
17424
+ customKeywords: external_exports.array(external_exports.string()).optional(),
17425
+ // Display name — optional so older policy rows without name still parse.
17426
+ // Added for the findings API (policy.name column migration).
17427
+ name: external_exports.string().optional()
17428
+ }).meta({ id: "Policy" });
17429
+ var PolicyBundle = external_exports.object({
17430
+ version: external_exports.string(),
17431
+ policies: external_exports.array(Policy),
17432
+ // Rules from the installed marketplace packs (snapshotted by the
17433
+ // control plane). The plugin registers these in addition to its bundled
17434
+ // packs. Optional so older backends — and older on-disk caches — that omit
17435
+ // the field still parse; consumers read `bundle.rules ?? []`.
17436
+ rules: external_exports.array(Rule).optional(),
17437
+ // When true, `rules` IS the complete effective ruleset and the runtime must
17438
+ // NOT merge its compiled-in bundled packs — the standalone gateway sets this
17439
+ // after reading the user's installed snapshot (installed_packs, enabled
17440
+ // packs only), which is how detection updates stay manual: new bundled
17441
+ // rules run only after the user applies the pack update. Absent/false keeps
17442
+ // the historical composition (bundled packs + rules) — older caches.
17443
+ rulesComplete: external_exports.boolean().optional(),
17444
+ // Active detection exceptions, evaluation subset only (see
17445
+ // ExceptionBundleEntry). Optional so older bundle producers — and older
17446
+ // on-disk caches — that omit the field still parse; consumers read
17447
+ // `bundle.exceptions ?? []`.
17448
+ exceptions: external_exports.array(ExceptionBundleEntry).optional(),
17449
+ // Rule ids whose pack is assigned a REVERSIBLE archetype (Redact & Vault).
17450
+ // A second axis over the same `redact` action, carried beside the policies
17451
+ // rather than on them: nothing writes ruleId-targeted policies to disk, so
17452
+ // widening Policy itself would change a persisted shape to express something
17453
+ // only the in-memory bundle needs. Optional so an older producer — or an
17454
+ // older on-disk cache — still parses; consumers read `?? []` and get the
17455
+ // pre-existing one-way behaviour, which is the safe direction to default.
17456
+ reversibleRuleIds: external_exports.array(external_exports.string()).optional(),
17457
+ // Installed pack version, keyed by ruleId, for rules in `rules` that came
17458
+ // from a versioned installed pack. Optional so older backends — and older
17459
+ // on-disk caches — that omit the field still parse; consumers fall back to
17460
+ // the rule's own spec version. NOT the bundle version above — see
17461
+ // installedRuleset's ruleVersions for the source of truth.
17462
+ ruleVersions: external_exports.record(external_exports.string(), external_exports.string()).optional(),
17463
+ customKeywords: external_exports.array(external_exports.string()),
17464
+ fetchedAt: external_exports.iso.datetime()
17465
+ }).meta({ id: "PolicyBundle" });
17466
+ var OBSERVE_ONLY_CATEGORIES = ["config"];
17467
+ var ENFORCEABLE_CATEGORIES = DetectionCategory.options.filter((c) => !OBSERVE_ONLY_CATEGORIES.includes(c));
17468
+ var CATEGORY_PEAK_SEVERITY = {
17469
+ secret: "critical",
17470
+ financial: "critical",
17471
+ // core-financial/credit-card
17472
+ code_flaw: "critical",
17473
+ pii: "high",
17474
+ phi: "high",
17475
+ custom: "high",
17476
+ // user-defined; conservative
17477
+ code_context: "low",
17478
+ config: "low"
17479
+ // observe-only; floors to monitor regardless
17480
+ };
17481
+ function severityFloorPolicy(category) {
17482
+ if (OBSERVE_ONLY_CATEGORIES.includes(category)) return "monitor";
17483
+ const peak = CATEGORY_PEAK_SEVERITY[category];
17484
+ return peak === "critical" || peak === "high" ? "warn" : "monitor";
17485
+ }
17486
+ var PolicyKind = external_exports.enum(["builtin", "custom"]).meta({ id: "PolicyKind" });
17487
+ var KNOWN_BUILTIN_IDS = ["monitor", "warn", "redact", "vault", "block"];
17488
+ var BuiltinPolicyId = external_exports.enum(KNOWN_BUILTIN_IDS).meta({ id: "BuiltinPolicyId" });
17489
+ var BUILTIN_POLICY_SPECS = {
17490
+ monitor: {
17491
+ name: "Monitor",
17492
+ action: "log",
17493
+ reversible: false,
17494
+ description: "Log every match for audit. The request is allowed through untouched."
17495
+ },
17496
+ warn: {
17497
+ name: "Warn",
17498
+ action: "warn",
17499
+ reversible: false,
17500
+ description: "Allow the request, but warn the user inline before it is sent."
17501
+ },
17502
+ redact: {
17503
+ name: "Redact",
17504
+ action: "redact",
17505
+ reversible: false,
17506
+ description: "Strip the matched value from the request and destroy it, then continue. What was removed cannot be recovered."
17507
+ },
17508
+ vault: {
17509
+ name: "Redact & Vault",
17510
+ action: "redact",
17511
+ reversible: true,
17512
+ description: "Strip the matched value from the request and keep an encrypted, recoverable copy in the local vault, leaving a pointer in its place. Needs the vault consent granted under Settings; without it this behaves as Redact."
17513
+ },
17514
+ block: {
17515
+ name: "Block",
17516
+ action: "block",
17517
+ reversible: false,
17518
+ description: "Refuse the request entirely whenever any rule in this detection matches."
17519
+ }
17520
+ };
17521
+ function builtinPolicyToAction(id) {
17522
+ return BUILTIN_POLICY_SPECS[id].action;
17523
+ }
17524
+ var CATEGORY_EXPRESSIBLE_IDS = KNOWN_BUILTIN_IDS.filter(
17525
+ (id) => !BUILTIN_POLICY_SPECS[id].reversible
17526
+ );
17527
+ var CATEGORY_INEXPRESSIBLE_IDS = KNOWN_BUILTIN_IDS.filter(
17528
+ (id) => BUILTIN_POLICY_SPECS[id].reversible
17529
+ );
17530
+ var CategoryPolicyId = external_exports.enum(CATEGORY_EXPRESSIBLE_IDS).meta({ id: "CategoryPolicyId" });
17531
+ var DEFAULT_ACTIONS = Object.fromEntries(
17532
+ DetectionCategory.options.map((c) => [c, builtinPolicyToAction(severityFloorPolicy(c))])
17533
+ );
17534
+ var BUILTIN_POLICIES = Object.fromEntries(
17535
+ KNOWN_BUILTIN_IDS.map((id) => [id, { id, ...BUILTIN_POLICY_SPECS[id] }])
17536
+ );
17537
+ var UsedByItem = external_exports.object({
17538
+ id: external_exports.string(),
17539
+ name: external_exports.string(),
17540
+ ruleCount: external_exports.number().int().nonnegative(),
17541
+ enabled: external_exports.boolean()
17542
+ }).meta({ id: "UsedByItem" });
17543
+ var PolicyListItem = external_exports.object({
17544
+ id: external_exports.string(),
17545
+ kind: PolicyKind,
17546
+ name: external_exports.string(),
17547
+ enabled: external_exports.boolean(),
17548
+ usedByCount: external_exports.number().int().nonnegative()
17549
+ }).meta({ id: "PolicyListItem" });
17550
+ var ListPoliciesResponse = external_exports.object({ items: external_exports.array(PolicyListItem) }).meta({ id: "ListPoliciesResponse" });
17551
+ var PolicyDetail = external_exports.object({
17552
+ specVersion: external_exports.literal(1),
17553
+ id: external_exports.string(),
17554
+ kind: PolicyKind,
17555
+ name: external_exports.string(),
17556
+ enabled: external_exports.boolean(),
17557
+ description: external_exports.string(),
17558
+ usedBy: external_exports.array(UsedByItem)
17559
+ }).meta({ id: "PolicyDetail" });
17560
+ var PolicyStatsResponse = external_exports.object({
17561
+ policies: external_exports.number().int().nonnegative(),
17562
+ builtin: external_exports.number().int().nonnegative(),
17563
+ custom: external_exports.number().int().nonnegative(),
17564
+ detectionsGoverned: external_exports.number().int().nonnegative()
17565
+ }).meta({ id: "PolicyStatsResponse" });
17566
+
17487
17567
  // ../../packages/schema/src/zod/project-files.ts
17488
17568
  var ProjectFileInput = external_exports.object({
17489
17569
  path: external_exports.string().min(1),
@@ -17556,44 +17636,6 @@ var BatchedRemediation = external_exports.discriminatedUnion("kind", [
17556
17636
  NoRemediationDecision
17557
17637
  ]);
17558
17638
 
17559
- // ../../packages/schema/src/zod/rule-test.ts
17560
- var TestRulesRequest = external_exports.object({
17561
- rules: external_exports.array(Rule).min(1).max(100),
17562
- text: external_exports.string().max(5e4).optional(),
17563
- fixtures: external_exports.array(RuleFixture).max(200).optional()
17564
- }).refine((v) => v.text !== void 0 || (v.fixtures?.length ?? 0) > 0, {
17565
- message: "Provide `text`, `fixtures`, or both \u2014 there must be something to test"
17566
- }).meta({ id: "TestRulesRequest" });
17567
- var RuleTestMatch = external_exports.object({
17568
- ruleId: external_exports.string(),
17569
- category: DetectionCategory,
17570
- severity: Severity,
17571
- span: Span,
17572
- confidence: external_exports.number().min(0).max(1),
17573
- match: external_exports.string()
17574
- }).meta({ id: "RuleTestMatch" });
17575
- var FixtureResult = external_exports.object({
17576
- label: external_exports.string(),
17577
- shouldMatch: external_exports.boolean(),
17578
- didMatch: external_exports.boolean(),
17579
- passed: external_exports.boolean(),
17580
- matches: external_exports.array(RuleTestMatch)
17581
- }).meta({ id: "FixtureResult" });
17582
- var TestRulesResponse = external_exports.object({
17583
- // Present only when the request supplied `text`.
17584
- adhoc: external_exports.object({ matches: external_exports.array(RuleTestMatch) }).optional(),
17585
- fixtures: external_exports.array(FixtureResult),
17586
- summary: external_exports.object({
17587
- total: external_exports.number().int().nonnegative(),
17588
- passed: external_exports.number().int().nonnegative(),
17589
- failed: external_exports.number().int().nonnegative()
17590
- }),
17591
- // Ids of rules whose matcher type the engine cannot evaluate today (e.g.
17592
- // `validator`), so they silently never match. Surfaced so an author is not
17593
- // misled by a green run that actually skipped a rule.
17594
- unsupportedRuleIds: external_exports.array(external_exports.string())
17595
- }).meta({ id: "TestRulesResponse" });
17596
-
17597
17639
  // ../../packages/schema/src/zod/security.ts
17598
17640
  var SeveritySummaryItem = external_exports.object({
17599
17641
  severity: Severity,
@@ -17691,10 +17733,22 @@ var TopSourcesQuery = external_exports.object({
17691
17733
  // Omit for both kinds.
17692
17734
  kind: external_exports.enum(SOURCE_KINDS).optional()
17693
17735
  });
17694
- var Provider = external_exports.enum(["claudecode", "cursor", "codex", "antigravity", "claudeai", "chatgpt", "copilot", "api"]).meta({ id: "Provider" });
17736
+ var Provider = Harness.extract([
17737
+ "ClaudeCode",
17738
+ "Cursor",
17739
+ "Codex",
17740
+ "Antigravity",
17741
+ "ClaudeAi",
17742
+ "ChatGpt",
17743
+ "Copilot",
17744
+ "Api"
17745
+ ]).meta({ id: "Provider" });
17695
17746
  var ScanCoverageProvider = external_exports.object({
17696
17747
  provider: Provider,
17697
- // Percent of that provider's traffic scanned in the window. 0 when unsupported.
17748
+ // Percent of that provider's traffic the shipped capture surface reaches.
17749
+ // A curated business fact, constant across every `range` — not a measured
17750
+ // per-window metric. 0 exactly when `supported` is false. See the comment
17751
+ // above the block for where these numbers are decided.
17698
17752
  coverage: external_exports.number().int().min(0).max(100),
17699
17753
  supported: external_exports.boolean()
17700
17754
  }).meta({ id: "ScanCoverageProvider" });
@@ -17748,6 +17802,18 @@ var ApplyRecommendedActionResponse = external_exports.object({
17748
17802
  var DismissRecommendedActionResponse = external_exports.object({ id: external_exports.string(), status: external_exports.literal("dismissed") }).meta({ id: "DismissRecommendedActionResponse" });
17749
17803
  var RecommendedActionIdParam = external_exports.object({ id: external_exports.string() });
17750
17804
 
17805
+ // ../../packages/schema/src/zod/settings-action.ts
17806
+ var SaveSettingsInput = external_exports.object({
17807
+ historicalAccess: external_exports.string(),
17808
+ modelJudgeConsent: external_exports.boolean(),
17809
+ vaultConsent: external_exports.string(),
17810
+ vaultInlineReveal: external_exports.string()
17811
+ });
17812
+ var AttachInput = external_exports.object({
17813
+ endpoint: external_exports.string(),
17814
+ label: external_exports.string().optional()
17815
+ });
17816
+
17751
17817
  // ../../packages/schema/src/zod/triage.ts
17752
17818
  var TriageHit = external_exports.object({
17753
17819
  ruleId: external_exports.string(),
@@ -17762,7 +17828,7 @@ var TriageHit = external_exports.object({
17762
17828
  valueFingerprint: external_exports.string().optional(),
17763
17829
  keyVersion: external_exports.number().int().nonnegative().optional()
17764
17830
  });
17765
- var TriagePolicy = BuiltinPolicyId;
17831
+ var TriagePolicy = CategoryPolicyId;
17766
17832
  var TriageCategoryRec = external_exports.object({
17767
17833
  category: DetectionCategory,
17768
17834
  action: TriagePolicy,
@@ -18000,24 +18066,38 @@ function probesFor(rule) {
18000
18066
  return [...derived, ...EXPONENTIAL_PROBES, ...POLYNOMIAL_PROBES];
18001
18067
  }
18002
18068
  var wallClock = () => performance.now();
18003
- function worstProbeMs(rule, now = wallClock) {
18069
+ function worstProbeMs(rule, now = wallClock, corroborate) {
18004
18070
  let ms = 0;
18005
18071
  let probe = "";
18072
+ let corroboratedMs;
18006
18073
  for (const text of probesFor(rule)) {
18007
18074
  const start = now();
18075
+ const corroborateStart = corroborate?.();
18008
18076
  scan(text, [rule]);
18009
18077
  const elapsed = now() - start;
18078
+ const corroborateEnd = corroborate?.();
18010
18079
  if (elapsed > ms) {
18011
18080
  ms = elapsed;
18012
18081
  probe = text;
18082
+ corroboratedMs = corroborateStart === void 0 || corroborateEnd === void 0 ? void 0 : corroborateEnd - corroborateStart;
18013
18083
  }
18014
18084
  if (ms >= BUDGET_MS) break;
18015
18085
  }
18016
- return { ms, probe };
18086
+ return { ms, probe, corroboratedMs };
18017
18087
  }
18018
- function checkRuleTiming(rule) {
18019
- const { ms, probe } = worstProbeMs(rule);
18020
- return { safe: ms < BUDGET_MS, worstMs: ms, probe };
18088
+ var CPU_CORROBORATION_SHARE = 0.2;
18089
+ var CORROBORATION_FLOOR_MS = BUDGET_MS * CPU_CORROBORATION_SHARE;
18090
+ function checkRuleTiming(rule, corroborate) {
18091
+ const { ms, probe, corroboratedMs } = worstProbeMs(rule, wallClock, corroborate);
18092
+ const work = corroboratedMs ?? 0;
18093
+ const verdict = ms < BUDGET_MS ? "safe" : work >= CORROBORATION_FLOOR_MS ? "over-budget" : "uncorroborated";
18094
+ return { verdict, worstMs: ms, corroboratedMs: work, probe };
18095
+ }
18096
+
18097
+ // ../../packages/plugin-sdk/src/work-clock.ts
18098
+ function workClockMs() {
18099
+ const usage = typeof process.threadCpuUsage === "function" ? process.threadCpuUsage() : process.cpuUsage();
18100
+ return (usage.user + usage.system) / 1e3;
18021
18101
  }
18022
18102
 
18023
18103
  // ../../packages/plugin-sdk/src/scan-worker.ts
@@ -18031,8 +18111,8 @@ function post(message) {
18031
18111
  port.on("message", (job) => {
18032
18112
  try {
18033
18113
  if (job.kind === "probe") {
18034
- const { safe, worstMs } = checkRuleTiming(job.rule);
18035
- post({ kind: "probed", id: job.id, safe, worstMs });
18114
+ const { verdict, worstMs, corroboratedMs } = checkRuleTiming(job.rule, workClockMs);
18115
+ post({ kind: "probed", id: job.id, verdict, worstMs, corroboratedMs });
18036
18116
  return;
18037
18117
  }
18038
18118
  const context = job.filePath === void 0 ? void 0 : { filePath: job.filePath };