@akasecurity/ai-tc-claude-code 0.9.10 → 0.9.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/scripts/intro.js CHANGED
@@ -50,7 +50,7 @@ var require_ignore = __commonJS({
50
50
  var REGEX_SPLITALL_CRLF = /\r?\n/g;
51
51
  var REGEX_TEST_INVALID_PATH = /^\.{0,2}\/|^\.{1,2}$/;
52
52
  var REGEX_TEST_TRAILING_SLASH = /\/$/;
53
- var SLASH = "/";
53
+ var SLASH2 = "/";
54
54
  var TMP_KEY_IGNORE = "node-ignore";
55
55
  if (typeof Symbol !== "undefined") {
56
56
  TMP_KEY_IGNORE = /* @__PURE__ */ Symbol.for("node-ignore");
@@ -422,11 +422,11 @@ var require_ignore = __commonJS({
422
422
  if (!REGEX_TEST_TRAILING_SLASH.test(path)) {
423
423
  return this.test(path);
424
424
  }
425
- const slices = path.split(SLASH).filter(Boolean);
425
+ const slices = path.split(SLASH2).filter(Boolean);
426
426
  slices.pop();
427
427
  if (slices.length) {
428
428
  const parent = this._t(
429
- slices.join(SLASH) + SLASH,
429
+ slices.join(SLASH2) + SLASH2,
430
430
  this._testCache,
431
431
  true,
432
432
  slices
@@ -442,14 +442,14 @@ var require_ignore = __commonJS({
442
442
  return cache[path];
443
443
  }
444
444
  if (!slices) {
445
- slices = path.split(SLASH).filter(Boolean);
445
+ slices = path.split(SLASH2).filter(Boolean);
446
446
  }
447
447
  slices.pop();
448
448
  if (!slices.length) {
449
449
  return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE);
450
450
  }
451
451
  const parent = this._t(
452
- slices.join(SLASH) + SLASH,
452
+ slices.join(SLASH2) + SLASH2,
453
453
  cache,
454
454
  checkUnignored,
455
455
  slices
@@ -492,7 +492,15 @@ var require_ignore = __commonJS({
492
492
  });
493
493
 
494
494
  // src/intro.ts
495
- import { readFileSync as readFileSync14 } from "fs";
495
+ import { readFileSync as readFileSync17 } from "fs";
496
+
497
+ // ../../packages/schema/src/drizzle/deferred-migrations.ts
498
+ var DEFERRED_MIGRATION_TAGS = [
499
+ "0031_audit_capture_by_time_index",
500
+ "0032_audit_capture_by_id_index",
501
+ "0033_audit_capture_location_index",
502
+ "0034_findings_read_indexes"
503
+ ];
496
504
 
497
505
  // ../../packages/schema/src/exception-scope.ts
498
506
  var MINUTE_MS = 6e4;
@@ -20306,6 +20314,15 @@ var FindingCategory = external_exports.enum([
20306
20314
  ]).meta({ id: "FindingCategory" });
20307
20315
  var FindingOrigin = external_exports.enum(["in-flight", "at-rest"]).meta({ id: "FindingOrigin" });
20308
20316
  var FindingStatus = external_exports.enum(["open", "handled", "resolved", "dismissed"]).meta({ id: "FindingStatus" });
20317
+ var SyncFailureReason = external_exports.enum(["deployment_refused", "payload_invalid", "detached_undelivered"]).meta({ id: "SyncFailureReason" });
20318
+ var FindingDeliveryState = external_exports.enum(["sent", "queued", "not_sent", "never_offered", "local_scan"]).meta({ id: "FindingDeliveryState" });
20319
+ var FindingDelivery = external_exports.object({
20320
+ state: FindingDeliveryState,
20321
+ // The delivery time for `sent`; the failure time for `not_sent` when recorded.
20322
+ at: external_exports.iso.datetime().optional(),
20323
+ // Only on `not_sent`, and only when a known reason was recorded.
20324
+ reason: SyncFailureReason.optional()
20325
+ }).meta({ id: "FindingDelivery" });
20309
20326
  var ResolutionMethod = external_exports.enum([
20310
20327
  "enforced-in-flight",
20311
20328
  "fixed-at-source",
@@ -20362,7 +20379,10 @@ var FindingInstance = external_exports.object({
20362
20379
  // The session that event belongs to, when it has one — the seam a
20363
20380
  // per-instance "view session" link needs. Absent for events captured
20364
20381
  // outside a session.
20365
- sessionId: external_exports.string().optional()
20382
+ sessionId: external_exports.string().optional(),
20383
+ // The delivery state of the event above (see FindingDelivery). Optional so
20384
+ // readers that do not project it stay valid.
20385
+ delivery: FindingDelivery.optional()
20366
20386
  }).meta({ id: "FindingInstance" });
20367
20387
  var FindingGroup = external_exports.object({
20368
20388
  id: external_exports.string(),
@@ -20379,13 +20399,11 @@ var FindingGroup = external_exports.object({
20379
20399
  latestDetectedAt: external_exports.iso.datetime(),
20380
20400
  instances: external_exports.array(FindingInstance),
20381
20401
  // Derived from instances' statuses with open-dominates precedence (see
20382
- // buildFindingGroups). Undefined only when no instance carries a status.
20402
+ // foldGroupStatus). Undefined only when no instance carries a status.
20383
20403
  status: FindingStatus.optional(),
20384
- // The distinct people across the WHOLE group, not just the `instances`
20385
- // preview — from the store's whole-group aggregate when it supplies one,
20386
- // else folded from the rows (see buildFindingGroups). Undefined when no
20387
- // instance carries a user, or when the store supplied whole-group folds
20388
- // without one.
20404
+ // The distinct people across the WHOLE group, not just the instances
20405
+ // carried here. Undefined when no instance carries a user, or when the
20406
+ // store supplied whole-group folds without one.
20389
20407
  users: external_exports.array(FindingUser).optional()
20390
20408
  }).meta({ id: "FindingGroup" });
20391
20409
  var FindingStats = external_exports.object({
@@ -20414,20 +20432,33 @@ var FindingFacets = external_exports.object({
20414
20432
  // counted under no value.
20415
20433
  status: external_exports.array(FindingFacetItem),
20416
20434
  // Host tool (attributes.tool_name). Present only on the instance-level
20417
- // reads, which can filter by it; the grouped read omits the dimension
20435
+ // reads, which can filter by it; the type-level read omits the dimension
20418
20436
  // because a group spans tools.
20419
- tool: external_exports.array(FindingFacetItem).optional()
20437
+ tool: external_exports.array(FindingFacetItem).optional(),
20438
+ // Delivery states (FindingDeliveryState). Present only on the
20439
+ // instance-level reads, like `tool`.
20440
+ deployment: external_exports.array(FindingFacetItem).optional()
20420
20441
  }).meta({ id: "FindingFacets" });
20421
- var ListGroupedFindingsQuery = external_exports.object({
20442
+ var FindingTypeSummary = FindingGroup.omit({ instances: true, match: true }).meta({
20443
+ id: "FindingTypeSummary"
20444
+ });
20445
+ var MAX_FINDING_TYPES_LIMIT = 100;
20446
+ var ListFindingTypesQuery = external_exports.object({
20422
20447
  // NOTE: severity filters by Severity (critical/high/medium/low), not by
20423
- // FindingAction.
20448
+ // FindingAction. It narrows TYPES: a type's severity is the one its newest
20449
+ // firing version carries, and this list pages types.
20450
+ //
20451
+ // That is NOT a claim the findings of a type share it. A rule can hold several
20452
+ // definition versions at different severities, so a type kept by this filter
20453
+ // can hold findings that individually do not match — see totals.findings on
20454
+ // ListFindingTypesResponse, which counts them all.
20424
20455
  severity: external_exports.array(Severity).optional(),
20425
20456
  subtype: external_exports.array(external_exports.string()).optional(),
20426
20457
  provider: external_exports.array(FindingProvider).optional(),
20427
20458
  action: external_exports.array(FindingAction).optional(),
20428
- // Matches a group's DERIVED status (see FindingGroup.status), not its
20429
- // individual instances' — so a filtered group's Status column always reads
20430
- // one of the requested values.
20459
+ // Matches a type's DERIVED status (see FindingGroup.status), not its
20460
+ // individual findings' — so a filtered row's status always reads one of the
20461
+ // requested values.
20431
20462
  status: external_exports.array(FindingStatus).optional(),
20432
20463
  q: external_exports.string().optional(),
20433
20464
  // Scope to findings whose event carries this session id (the Activity page's
@@ -20437,23 +20468,37 @@ var ListGroupedFindingsQuery = external_exports.object({
20437
20468
  // from a time-scoped page (Activity's range) can carry that scope. Absent
20438
20469
  // means all time — this list has no default window.
20439
20470
  from: external_exports.iso.datetime().optional(),
20440
- // A group or instance id that must appear in the page even when the cursor
20441
- // has already advanced past its sort position. This is what keeps the
20442
- // Findings page's one-shot ?finding= deep link resolving once the list
20443
- // paginates: the target group is appended out of sort order rather than
20444
- // scanning forward for it. Never affects totals, facets or the cursor.
20471
+ // A RULE id that must appear in the page even when the cursor has already
20472
+ // advanced past its sort position. This is what keeps the selected type
20473
+ // visible in the list once it paginates: the target is appended out of sort
20474
+ // order rather than scanned forward for. Never affects totals, facets or the
20475
+ // cursor. Unlike the grouped read this replaces, it names a rule only — an
20476
+ // instance id is resolved by `findingInstance`, which is a primary-key seek
20477
+ // and so is not bounded by what any page happens to hold.
20445
20478
  includeId: external_exports.string().optional(),
20446
- groupBy: external_exports.literal("type").optional(),
20447
- limit: external_exports.coerce.number().int().min(1).max(100).optional(),
20479
+ limit: external_exports.coerce.number().int().min(1).max(MAX_FINDING_TYPES_LIMIT).optional(),
20448
20480
  cursor: external_exports.string().optional()
20449
20481
  });
20450
- var ListGroupedFindingsResponse = external_exports.object({
20482
+ var ListFindingTypesResponse = external_exports.object({
20451
20483
  totals: external_exports.object({
20484
+ // Findings belonging to the matching TYPES — not findings that each match
20485
+ // the filters. The filters here select types, so a type that survives
20486
+ // contributes its whole instanceCount.
20487
+ //
20488
+ // `status` is the one exception, narrowed per finding via
20489
+ // countInstancesByStatus. `severity`, `provider` and `action` are not, so
20490
+ // this can exceed what the instance read reports for the same filters: a
20491
+ // rule whose severity moved between versions is kept on its newest and
20492
+ // still counts its older findings. Narrowing the other three needs
20493
+ // per-dimension counts the aggregate does not carry today.
20452
20494
  findings: external_exports.number().int().nonnegative(),
20453
- groups: external_exports.number().int().nonnegative()
20495
+ // Counts TYPES, which is the unit this read pages. The instance read's
20496
+ // own totals count findings; the two deliberately answer different
20497
+ // questions and are never summed.
20498
+ types: external_exports.number().int().nonnegative()
20454
20499
  }),
20455
20500
  facets: FindingFacets,
20456
- items: external_exports.array(FindingGroup),
20501
+ items: external_exports.array(FindingTypeSummary),
20457
20502
  nextCursor: external_exports.string().nullable(),
20458
20503
  // Present only on session-scoped queries (`sessionId` set): per ruleId, how
20459
20504
  // many times that rule fired in the session's persisted transcript. Findings
@@ -20461,7 +20506,7 @@ var ListGroupedFindingsResponse = external_exports.object({
20461
20506
  // every firing, so the two numbers legitimately differ — this map lets a
20462
20507
  // session-scoped view show both.
20463
20508
  sessionFirings: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()).optional()
20464
- }).meta({ id: "ListGroupedFindingsResponse" });
20509
+ }).meta({ id: "ListFindingTypesResponse" });
20465
20510
  var ApplyFindingActionRequest = external_exports.object({
20466
20511
  // 'quarantined' is system-assigned (see FindingAction) — clients may not set
20467
20512
  // it, so it is excluded from the request contract. The mapping helper
@@ -20490,16 +20535,19 @@ var FindingInstanceDetail = FindingInstance.extend({
20490
20535
  var MAX_FLAT_FINDINGS_LIMIT = 200;
20491
20536
  var ListFindingInstancesQuery = external_exports.object({
20492
20537
  severity: external_exports.array(Severity).optional(),
20493
- // Rule ids, the same vocabulary the grouped list's `subtype` carries.
20538
+ // Rule ids, the same vocabulary the types list's `subtype` carries. Pinning
20539
+ // ONE of them is how the master/detail view scopes its right-hand panel.
20494
20540
  subtype: external_exports.array(external_exports.string()).optional(),
20495
20541
  provider: external_exports.array(FindingProvider).optional(),
20496
20542
  action: external_exports.array(FindingAction).optional(),
20497
20543
  // Matches each instance's OWN derived status (deriveFindingStatus), unlike
20498
- // the grouped query's group-level fold.
20544
+ // the types query's type-level fold.
20499
20545
  status: external_exports.array(FindingStatus).optional(),
20500
20546
  // Exact host-tool names (attributes.tool_name, e.g. 'Bash'). A real filter,
20501
20547
  // where the free-text `q` can only match the rendered "via Bash" label.
20502
20548
  tool: external_exports.array(external_exports.string()).optional(),
20549
+ // The delivery state of each finding's event (see FindingDelivery).
20550
+ deployment: external_exports.array(FindingDeliveryState).optional(),
20503
20551
  // Exact repository / file-path matches, for the drill-down out of the
20504
20552
  // locations view. A row whose event carries no repo/file matches neither.
20505
20553
  repo: external_exports.string().optional(),
@@ -20512,37 +20560,50 @@ var ListFindingInstancesQuery = external_exports.object({
20512
20560
  });
20513
20561
  var ListFindingInstancesResponse = external_exports.object({
20514
20562
  // Instances matching the filters across the whole scope, not just this
20515
- // page — cursor-independent, like the grouped list's totals.
20563
+ // page — cursor-independent, like the types list's totals.
20516
20564
  totals: external_exports.object({ findings: external_exports.number().int().nonnegative() }),
20517
- // Counts in INSTANCES here, where the grouped response counts groups. Each
20565
+ // Counts in INSTANCES here, where the types response counts types. Each
20518
20566
  // dimension still excludes its own filter.
20519
20567
  facets: FindingFacets,
20520
20568
  items: external_exports.array(FindingInstanceDetail),
20521
20569
  nextCursor: external_exports.string().nullable()
20522
20570
  }).meta({ id: "ListFindingInstancesResponse" });
20523
- var FindingLocationFile = external_exports.object({
20524
- // Empty when the instances carried no file path (a prompt or a tool call
20525
- // with no file attribution).
20526
- file: external_exports.string(),
20527
- instanceCount: external_exports.number().int().nonnegative(),
20528
- maxSeverity: Severity,
20529
- latestDetectedAt: external_exports.iso.datetime(),
20530
- // Folded from the instances' derived statuses with the same
20531
- // open-dominates precedence a group uses.
20532
- status: FindingStatus.optional(),
20533
- // Distinct rules seen at this location, capped — the row shows them as
20534
- // chips, and the count is what conveys scale.
20535
- ruleIds: external_exports.array(external_exports.string())
20536
- }).meta({ id: "FindingLocationFile" });
20537
- var FindingLocationRepo = external_exports.object({
20571
+ var ListFindingInstancesPage = external_exports.object({
20572
+ items: external_exports.array(FindingInstanceDetail),
20573
+ nextCursor: external_exports.string().nullable()
20574
+ }).meta({ id: "ListFindingInstancesPage" });
20575
+ var FindingLocationSummary = external_exports.object({
20576
+ // Opaque, stable, minted from the pair by encodeLocationId. It exists
20577
+ // because a location's identity is two values and a URL param carries one:
20578
+ // `?loc=` names a location the way `?rule=` names a type. Only ever compared
20579
+ // for EQUALITY — the page's selection check, this read's `includeId`, the
20580
+ // client's page dedupe — never decoded, and never a sort key.
20581
+ id: external_exports.string(),
20538
20582
  /** Empty when the instances carried no repo attribute. */
20539
20583
  repo: external_exports.string(),
20584
+ // Empty when the instances carried no file path (a prompt, or a tool call
20585
+ // with no file attribution). Both halves empty is a real location — usually
20586
+ // the largest one in a store — and is selectable like any other.
20587
+ file: external_exports.string(),
20540
20588
  instanceCount: external_exports.number().int().nonnegative(),
20589
+ // The WORST severity present, not the first row's. It is this list's primary
20590
+ // sort key, so it is also what explains why a row is where it is, and it is
20591
+ // how a reader decides what to open without opening everything.
20541
20592
  maxSeverity: Severity,
20542
20593
  latestDetectedAt: external_exports.iso.datetime(),
20594
+ // Folded from the instances' derived statuses with the same open-dominates
20595
+ // precedence a group uses, so it answers "is anything left to do here" and
20596
+ // not much more: a location holding 1 open among 40 resolved reads like one
20597
+ // holding 40 open. That loss is accepted — the panel beside this list
20598
+ // carries each finding's own status, and instanceCount sits next to the
20599
+ // badge.
20543
20600
  status: FindingStatus.optional(),
20544
- files: external_exports.array(FindingLocationFile)
20545
- }).meta({ id: "FindingLocationRepo" });
20601
+ // Every distinct rule seen at this location, UNCAPPED — so the length is a
20602
+ // tally rather than a sample and a row can say how many there are. Bounded
20603
+ // by the ruleset, not by the store. The view bounds what it DISPLAYS.
20604
+ ruleIds: external_exports.array(external_exports.string())
20605
+ }).meta({ id: "FindingLocationSummary" });
20606
+ var MAX_FINDING_LOCATIONS_LIMIT = 100;
20546
20607
  var ListFindingLocationsQuery = external_exports.object({
20547
20608
  severity: external_exports.array(Severity).optional(),
20548
20609
  subtype: external_exports.array(external_exports.string()).optional(),
@@ -20552,21 +20613,47 @@ var ListFindingLocationsQuery = external_exports.object({
20552
20613
  // instances that match, and folds its status from those.
20553
20614
  status: external_exports.array(FindingStatus).optional(),
20554
20615
  tool: external_exports.array(external_exports.string()).optional(),
20616
+ // The delivery state of each finding's event (see FindingDelivery).
20617
+ deployment: external_exports.array(FindingDeliveryState).optional(),
20555
20618
  q: external_exports.string().optional(),
20556
20619
  sessionId: external_exports.string().optional(),
20557
20620
  from: external_exports.iso.datetime().optional(),
20558
- limit: external_exports.coerce.number().int().min(1).max(500).optional()
20621
+ // A LOCATION id (see FindingLocationSummary.id) that must appear in the page
20622
+ // even when the cursor has already advanced past its sort position — the
20623
+ // counterpart of ListFindingTypesQuery.includeId, and needed far more often
20624
+ // here. Selecting a row pushes the URL, which re-renders the server and resets
20625
+ // the client's page cache to page 0; with distinct (repo, file) pairs running
20626
+ // into the thousands, a selection sitting off page 0 is the ordinary case
20627
+ // rather than a deep-link corner. Never affects totals, facets or the cursor.
20628
+ includeId: external_exports.string().optional(),
20629
+ limit: external_exports.coerce.number().int().min(1).max(MAX_FINDING_LOCATIONS_LIMIT).optional(),
20630
+ cursor: external_exports.string().optional()
20559
20631
  });
20560
20632
  var ListFindingLocationsResponse = external_exports.object({
20561
20633
  totals: external_exports.object({
20634
+ // Findings matching the filters across the whole scope. Unlike the types
20635
+ // read's same-named field this needs no caveat: the filters here narrow
20636
+ // per finding, so this is the sum of every row's instanceCount.
20562
20637
  findings: external_exports.number().int().nonnegative(),
20563
- repos: external_exports.number().int().nonnegative(),
20564
- files: external_exports.number().int().nonnegative()
20638
+ // Counts LOCATIONS, the unit this read pages — the number the paginator
20639
+ // states. The facets beside it count FINDINGS (see below); a surface
20640
+ // showing both says which is which.
20641
+ locations: external_exports.number().int().nonnegative()
20565
20642
  }),
20566
- /** Sorted by max severity, then most recent. */
20567
- items: external_exports.array(FindingLocationRepo),
20568
- /** Whether `limit` truncated the repo list. */
20569
- hasMore: external_exports.boolean()
20643
+ // Counts in FINDINGS, where the types response counts types, each dimension
20644
+ // still excluding its own filter. Deliberately not locations: counting those
20645
+ // needs a set of location keys per dimension per value — memory tracking the
20646
+ // store times the vocabulary, in a read whose scan promises flat memory —
20647
+ // and the cheap per-location version is not an approximation but WRONG. A
20648
+ // location holding {claudecode, block} and {codex, warn} would survive
20649
+ // provider=claudecode AND action=warn, under which no single finding
20650
+ // matches, so the facet would contradict the instanceCount this whole view
20651
+ // rests on. Findings also keep the toolbar in the same unit as the page
20652
+ // tally and the panel it sits above.
20653
+ facets: FindingFacets,
20654
+ /** Sorted by max severity, then most recent, then (repo, file). */
20655
+ items: external_exports.array(FindingLocationSummary),
20656
+ nextCursor: external_exports.string().nullable()
20570
20657
  }).meta({ id: "ListFindingLocationsResponse" });
20571
20658
 
20572
20659
  // ../../packages/schema/src/zod/meta.ts
@@ -20730,6 +20817,10 @@ var CaptureAttributes = external_exports.object({
20730
20817
  // to 'allow' — the enforcement audit trail's link back to the grant that
20731
20818
  // authorized the bypass.
20732
20819
  exception_ids: external_exports.array(external_exports.guid()).optional(),
20820
+ // The persisted spellings of EventMetadata's messageId/conversationId — the
20821
+ // join back to the `llm_call` leaf for the same assistant turn.
20822
+ message_id: external_exports.string().optional(),
20823
+ conversation_id: external_exports.string().optional(),
20733
20824
  // Whole milliseconds this capture's inspection blocked its caller — the
20734
20825
  // plugin's own added latency (see EventMetadata.inspectionMs, whose value
20735
20826
  // this is). Promoted to the `inspection_ms` generated column so the facet is
@@ -20738,7 +20829,19 @@ var CaptureAttributes = external_exports.object({
20738
20829
  // inline json_extract and is not itself an optimization.
20739
20830
  // ABSENT on replayed captures (backfill / worktree scan) and on rows written
20740
20831
  // before the measurement shipped — never present as a placeholder 0.
20741
- inspection_ms: external_exports.number().int().nonnegative().optional()
20832
+ inspection_ms: external_exports.number().int().nonnegative().optional(),
20833
+ // What a `redact` this capture could not carry out became instead (see
20834
+ // EventMetadata.redactDegradedTo, whose value this is). Present only when a
20835
+ // degrade actually happened, so absence is the ordinary case rather than a
20836
+ // reader having to distinguish it from a zero.
20837
+ //
20838
+ // PER CAPTURE, while `inspection_findings.action_taken` is per finding —
20839
+ // so on a multi-finding row this does not say which finding degraded, and
20840
+ // its presence does not mean the fallback decided the capture's action. A
20841
+ // capture denied by another finding's own Block policy carries `block`
20842
+ // here too. The full statement is on EventMetadata.redactDegradedTo; it is
20843
+ // repeated rather than referenced because a store reader opens this file.
20844
+ redact_degraded_to: ActionTaken.optional()
20742
20845
  }).catchall(external_exports.unknown());
20743
20846
  var ToolCallInspection = external_exports.object({
20744
20847
  ruleId: external_exports.string().min(1),
@@ -20934,7 +21037,17 @@ var AuditEvent = external_exports.object({
20934
21037
  /** `share` to a first-party/internal destination. */
20935
21038
  internal: external_exports.boolean(),
20936
21039
  /** Event needs review (e.g. unverified egress). */
20937
- flagged: external_exports.boolean()
21040
+ flagged: external_exports.boolean(),
21041
+ /**
21042
+ * The body this event's `title` is drawn from was cleared by local body
21043
+ * expiry, so an EMPTY title here means "gone", not "never had one".
21044
+ *
21045
+ * A separate flag rather than a sentinel written into `title`: the title is
21046
+ * rendered text, and a store-layer module that invented display copy for it
21047
+ * would be choosing words the view is supposed to choose. Additive and
21048
+ * defaulted, so an older producer still validates.
21049
+ */
21050
+ bodyExpired: external_exports.boolean().default(false)
20938
21051
  }).meta({ id: "ActivityAuditEvent" });
20939
21052
  var ActivitySessionSummary = external_exports.object({
20940
21053
  id: external_exports.string(),
@@ -21731,6 +21844,14 @@ var ControlPlaneErrorBody = external_exports.object({
21731
21844
  message: external_exports.string().optional()
21732
21845
  }).optional()
21733
21846
  });
21847
+ var RemoteFailureKind = external_exports.enum([
21848
+ "unauthorized",
21849
+ "forbidden",
21850
+ "route-absent",
21851
+ "invalid-request",
21852
+ "rejected",
21853
+ "unreachable"
21854
+ ]);
21734
21855
  var AttachDeviceRequest = external_exports.object({
21735
21856
  // This machine's own continuity id, so re-attaching ROTATES the credential
21736
21857
  // on one machine record instead of producing a second one. Client-minted
@@ -22149,6 +22270,12 @@ var EventMetadata = external_exports.object({
22149
22270
  // to 'allow' — the enforcement audit trail's link back to the grant that
22150
22271
  // authorized the bypass. Absent on captures where no exception applied.
22151
22272
  exceptionIds: external_exports.array(external_exports.guid()).optional(),
22273
+ // The assistant message this capture belongs to, and the conversation it sits
22274
+ // in — set by the browser extension's network capture so a stored `response`
22275
+ // row can be joined to the `llm_call` leaf describing the same turn. Absent
22276
+ // on every other capture path, which has no such id.
22277
+ messageId: external_exports.string().optional(),
22278
+ conversationId: external_exports.string().optional(),
22152
22279
  // How long THIS capture's inspection blocked its caller, in whole
22153
22280
  // milliseconds — the plugin's own added latency, NOT the LLM call it sat in
22154
22281
  // front of. Measured inside `capture()` (@akasecurity/plugin-sdk) across
@@ -22161,7 +22288,37 @@ var EventMetadata = external_exports.object({
22161
22288
  // Absent is also what every pre-measurement client writes, and what a
22162
22289
  // clock failure degrades to — a reader must treat absence as "not measured"
22163
22290
  // and never as a zero, which would read as "inspection is free".
22164
- inspectionMs: external_exports.number().int().nonnegative().optional()
22291
+ inspectionMs: external_exports.number().int().nonnegative().optional(),
22292
+ // What a `redact` this capture COULD NOT CARRY OUT became instead — the
22293
+ // workspace's `redactFallback`, applied because the field could not be
22294
+ // masked in place (a shell command, a URL, or any argument on a host whose
22295
+ // hook contract offers no rewrite channel).
22296
+ //
22297
+ // It exists because the action alone cannot say why. A finding recorded as
22298
+ // `warn` reads identically whether its detection was ASSIGNED Warn or was
22299
+ // assigned Redact on a field that could not take one — and those are
22300
+ // different facts about the same row: the first is a policy the user chose,
22301
+ // the second is a masking the host could not perform. Absent means no
22302
+ // degrade happened, which is every ordinary capture.
22303
+ //
22304
+ // TWO LIMITS a reader of a stored row has to know, because the grain here
22305
+ // is the CAPTURE while `actionTaken` is per FINDING:
22306
+ //
22307
+ // - It does not say WHICH finding degraded. A capture carrying a degraded
22308
+ // `redact` alongside a finding ASSIGNED the same action stores both
22309
+ // identically and one reason for the pair; attributing it to both
22310
+ // describes the assigned one wrongly, and to neither loses the degrade.
22311
+ // - PRESENCE IS NOT CAUSATION. The value is the action the lost redact
22312
+ // became, not the reason the capture ended as it did — a capture denied
22313
+ // by some other finding's own Block policy still carries `block` here,
22314
+ // and clearing the workspace's fallback would not have let it through.
22315
+ // Gate on the value against what a fallback can produce; never read the
22316
+ // field's presence as "this was the fallback's doing".
22317
+ //
22318
+ // Both are pinned as behaviour in @akasecurity/plugin-sdk's runtime suite.
22319
+ // Closing either means moving the reason onto the finding row, which
22320
+ // already carries its own action.
22321
+ redactDegradedTo: ActionTaken.optional()
22165
22322
  }).meta({ id: "EventMetadata" });
22166
22323
  var Event = external_exports.object({
22167
22324
  id: external_exports.guid(),
@@ -22271,6 +22428,15 @@ var RotateKeyInput = external_exports.object({
22271
22428
  confirmation: external_exports.string()
22272
22429
  });
22273
22430
 
22431
+ // ../../packages/schema/src/zod/finding-delivery.ts
22432
+ var KNOWN_REASONS = SyncFailureReason.options;
22433
+
22434
+ // ../../packages/schema/src/zod/findings-group-build.ts
22435
+ function rankByOrder(members2) {
22436
+ return Object.fromEntries(members2.map((member, index) => [member, index]));
22437
+ }
22438
+ var SEVERITY_RANK = rankByOrder(Severity.options);
22439
+
22274
22440
  // ../../packages/schema/src/zod/installed-pack.ts
22275
22441
  var InstalledPack = external_exports.object({
22276
22442
  id: external_exports.guid(),
@@ -22337,6 +22503,11 @@ var Policy = external_exports.object({
22337
22503
  // test `prohibitedModels` passes and `reversibleRuleIds` fails.
22338
22504
  provenance: PolicyProvenance.optional()
22339
22505
  }).meta({ id: "Policy" });
22506
+ var KNOWN_BUILTIN_IDS = ["monitor", "warn", "redact", "vault", "block"];
22507
+ var BuiltinPolicyId = external_exports.enum(KNOWN_BUILTIN_IDS).meta({ id: "BuiltinPolicyId" });
22508
+ var RedactFallback = BuiltinPolicyId.extract(["monitor", "warn", "block"]).meta({
22509
+ id: "RedactFallback"
22510
+ });
22340
22511
  var PolicyBundle = external_exports.object({
22341
22512
  version: external_exports.string(),
22342
22513
  policies: external_exports.array(Policy),
@@ -22384,6 +22555,16 @@ var PolicyBundle = external_exports.object({
22384
22555
  // control plane), so no name resolution stands between the decision and the
22385
22556
  // comparison.
22386
22557
  prohibitedModels: external_exports.array(external_exports.string()).optional(),
22558
+ // What a resolved `redact` becomes on a field the host cannot rewrite, as
22559
+ // the ORGANIZATION would have it. Merged raise-only against the device's own
22560
+ // `WorkspaceSettings.redactFallback` (see strongerRedactFallback below), so
22561
+ // a control plane can tighten a machine and never loosen one — the same
22562
+ // direction `mergeRaiseOnly` enforces for policies.
22563
+ //
22564
+ // Optional so an older backend, and an older on-disk cache, still parses;
22565
+ // absent leaves the device's own setting in force, which is the behaviour
22566
+ // that predates the field and the safe direction to default.
22567
+ redactFallback: RedactFallback.optional(),
22387
22568
  customKeywords: external_exports.array(external_exports.string()),
22388
22569
  fetchedAt: external_exports.iso.datetime()
22389
22570
  }).meta({ id: "PolicyBundle" });
@@ -22413,11 +22594,6 @@ function severityFloorPolicy(category) {
22413
22594
  const peak = CATEGORY_PEAK_SEVERITY[category];
22414
22595
  return peak === "critical" || peak === "high" ? "warn" : "monitor";
22415
22596
  }
22416
- var KNOWN_BUILTIN_IDS = ["monitor", "warn", "redact", "vault", "block"];
22417
- var BuiltinPolicyId = external_exports.enum(KNOWN_BUILTIN_IDS).meta({ id: "BuiltinPolicyId" });
22418
- var RedactFallback = BuiltinPolicyId.extract(["monitor", "warn", "block"]).meta({
22419
- id: "RedactFallback"
22420
- });
22421
22597
  var BUILTIN_POLICY_SPECS = {
22422
22598
  monitor: {
22423
22599
  name: "Monitor",
@@ -22679,7 +22855,7 @@ var VaultConsent = external_exports.object({
22679
22855
  });
22680
22856
 
22681
22857
  // ../../packages/schema/src/zod/local.ts
22682
- var WORKSPACE_SETTINGS_SPEC_VERSION = 7;
22858
+ var WORKSPACE_SETTINGS_SPEC_VERSION = 8;
22683
22859
  var RunMode = external_exports.enum(["standalone", "attached"]);
22684
22860
  var ControlPlaneConnection = external_exports.object({
22685
22861
  endpoint: external_exports.string().min(1),
@@ -22698,6 +22874,15 @@ var HistorySyncConsent = external_exports.object({
22698
22874
  payloadVersion: external_exports.number().int().positive(),
22699
22875
  endpoint: external_exports.string()
22700
22876
  });
22877
+ var BODY_RETENTION_DEFAULT_DAYS = 30;
22878
+ var BodyRetention = external_exports.object({
22879
+ enabled: external_exports.boolean().default(false),
22880
+ // Never 0, and the ceiling is a fat-finger guard rather than a policy
22881
+ // limit — `enabled` is the real gate. A low value cannot reach a row the
22882
+ // sync ledger still owes: the sweep's age filter only ever NARROWS a
22883
+ // candidate set that is already bounded by "delivered, or never owed".
22884
+ retainDays: external_exports.number().int().min(1).max(3650).default(BODY_RETENTION_DEFAULT_DAYS)
22885
+ }).meta({ id: "BodyRetention" });
22701
22886
  var WorkspaceSettings = external_exports.object({
22702
22887
  specVersion: external_exports.number().int().positive().default(WORKSPACE_SETTINGS_SPEC_VERSION),
22703
22888
  runMode: RunMode.default("standalone"),
@@ -22741,12 +22926,18 @@ var WorkspaceSettings = external_exports.object({
22741
22926
  // covers the current payload and must be re-granted.
22742
22927
  modelJudgeConsent: ModelJudgeConsent.optional(),
22743
22928
  // Records that the user consented to the DEFERRED send — the outbox — along
22744
- // with the payload shape and the endpoint they agreed to. Since payload v2
22745
- // that covers both the pre-attach backlog and undelivered captures (which
22746
- // carry prompt/reply text in `content`); the key name predates the widening.
22747
- // Absent until granted, and a grant for a different endpoint or an older
22748
- // payload no longer counts.
22749
- historySyncConsent: HistorySyncConsent.optional()
22929
+ // with the payload shape and the endpoint they agreed to. Since payload v3
22930
+ // that covers the pre-attach backlog AND undelivered captures alike, and both
22931
+ // carry prompt/reply/tool-output text in `content`; the key name predates
22932
+ // both widenings. Absent until granted, and a grant for a different endpoint
22933
+ // or an older payload no longer counts.
22934
+ historySyncConsent: HistorySyncConsent.optional(),
22935
+ // Local body expiry (see BodyRetention). Off until switched on; expiring a
22936
+ // body never removes the row or its findings.
22937
+ bodyRetention: BodyRetention.default({
22938
+ enabled: false,
22939
+ retainDays: BODY_RETENTION_DEFAULT_DAYS
22940
+ })
22750
22941
  });
22751
22942
 
22752
22943
  // ../../packages/schema/src/zod/managed.ts
@@ -22759,10 +22950,22 @@ var ManagedSettingKey = external_exports.enum([
22759
22950
  "vaultInlineReveal",
22760
22951
  "modelJudgeConsent",
22761
22952
  "dataSharesInPlace",
22762
- "redactFallback"
22953
+ "redactFallback",
22954
+ // Pins the toggle and the day count together — see BodyRetention on why the
22955
+ // two are one unit. An administrator mandating a window wants the count
22956
+ // enforced with it, not one a user can widen while the toggle stays on.
22957
+ "bodyRetention"
22763
22958
  ]).meta({ id: "ManagedSettingKey" });
22959
+ function isManagedSettingKey(value) {
22960
+ return ManagedSettingKey.safeParse(value).success;
22961
+ }
22764
22962
  var ManagedSettingsValues = external_exports.object({
22765
22963
  runMode: external_exports.enum(["standalone", "attached"]).optional(),
22964
+ // `controlPlane` and `bodyRetention` are the two nested values, and both are
22965
+ // plain, non-strict objects: a key under either that this build does not know
22966
+ // is stripped and nothing reports it. The unknown-value split in
22967
+ // ManagedSettings below classifies top-level names only, so it stops at
22968
+ // these boundaries.
22766
22969
  controlPlane: external_exports.object({
22767
22970
  endpoint: external_exports.string().min(1),
22768
22971
  label: external_exports.string().min(1).optional()
@@ -22773,7 +22976,8 @@ var ManagedSettingsValues = external_exports.object({
22773
22976
  vaultInlineReveal: external_exports.enum(["masked", "full", "off"]).optional(),
22774
22977
  modelJudgeConsent: external_exports.boolean().optional(),
22775
22978
  dataSharesInPlace: external_exports.boolean().optional(),
22776
- redactFallback: RedactFallback.optional()
22979
+ redactFallback: RedactFallback.optional(),
22980
+ bodyRetention: BodyRetention.optional()
22777
22981
  }).meta({ id: "ManagedSettingsValues" });
22778
22982
  var ManagedSettings = external_exports.object({
22779
22983
  specVersion: external_exports.number().int().positive().default(MANAGED_SETTINGS_SPEC_VERSION),
@@ -22781,11 +22985,59 @@ var ManagedSettings = external_exports.object({
22781
22985
  // decision from a bug. Absent renders as a generic "your organization".
22782
22986
  organization: external_exports.string().min(1).optional(),
22783
22987
  // What the administrator pinned.
22784
- values: ManagedSettingsValues.default({}),
22988
+ //
22989
+ // Parsed as a RECORD rather than as the nested schema, and split below for
22990
+ // the same reason `lockedFields` is parsed as names: a plain `z.object`
22991
+ // drops an unrecognised key and succeeds, so a pin this build does not know
22992
+ // vanished and nothing anywhere said so. A pin with no lock is a supported
22993
+ // shape — it is a DEFAULT the user may still change — so that silence hit
22994
+ // exactly the file an administrator is most likely to write while a fleet
22995
+ // is mid-upgrade.
22996
+ //
22997
+ // Splitting here rather than calling `.strict()`: strict would REFUSE the
22998
+ // file, which is the outcome the lock half already rejected — an older
22999
+ // build then runs entirely unmanaged, every pin and lock gone. A bad KNOWN
23000
+ // value still fails, because the nested schema is re-run over the known
23001
+ // subset and its issues are re-raised on this parse.
23002
+ values: external_exports.record(external_exports.string(), external_exports.unknown()).default({}),
22785
23003
  // Which of those the user may not change. A key here with no matching value
22786
23004
  // freezes whatever the user last chose; a value with no lock is a DEFAULT
22787
23005
  // the user may still override. The two are separable on purpose.
22788
- lockedFields: external_exports.array(ManagedSettingKey).default([])
23006
+ //
23007
+ // Parsed as NAMES rather than as the enum, and split below: a name this
23008
+ // build does not know is dropped from the locked set and reported, never a
23009
+ // reason to refuse the file. The same shape reaches an older build whenever
23010
+ // an administrator locks a key a newer build added, and refusing it there
23011
+ // ran that build entirely unmanaged — every pin and lock gone — on exactly
23012
+ // the fleets most likely to carry a version skew. A name outside the enum
23013
+ // is still never HONOURED: the lockable set stays explicit above.
23014
+ lockedFields: external_exports.array(external_exports.string()).default([])
23015
+ }).transform(({ lockedFields, values, ...rest }, ctx) => {
23016
+ const known = [];
23017
+ const unknown2 = [];
23018
+ for (const name of lockedFields) {
23019
+ if (isManagedSettingKey(name)) known.push(name);
23020
+ else unknown2.push(name);
23021
+ }
23022
+ const knownValues = /* @__PURE__ */ Object.create(null);
23023
+ const unknownValues = [];
23024
+ for (const [name, value] of Object.entries(values)) {
23025
+ if (Object.hasOwn(ManagedSettingsValues.shape, name)) knownValues[name] = value;
23026
+ else unknownValues.push(name);
23027
+ }
23028
+ const pinned = ManagedSettingsValues.safeParse(knownValues);
23029
+ if (!pinned.success) {
23030
+ for (const issue2 of pinned.error.issues)
23031
+ ctx.addIssue({ ...issue2, path: ["values", ...issue2.path] });
23032
+ return external_exports.NEVER;
23033
+ }
23034
+ return {
23035
+ ...rest,
23036
+ values: pinned.data,
23037
+ lockedFields: known,
23038
+ ...unknown2.length > 0 ? { unknownLockedFields: unknown2 } : {},
23039
+ ...unknownValues.length > 0 ? { unknownValueFields: unknownValues } : {}
23040
+ };
22789
23041
  }).meta({ id: "ManagedSettings" });
22790
23042
 
22791
23043
  // ../../packages/schema/src/zod/project-files.ts
@@ -22903,7 +23155,11 @@ var FindingsTimeseriesPoint = external_exports.object({
22903
23155
  timestamp: external_exports.iso.date(),
22904
23156
  critical: external_exports.number().int().nonnegative(),
22905
23157
  high: external_exports.number().int().nonnegative(),
22906
- medium: external_exports.number().int().nonnegative()
23158
+ medium: external_exports.number().int().nonnegative(),
23159
+ // Optional and additive, so a producer written against the earlier
23160
+ // three-series contract keeps validating. A consumer plotting it resolves the
23161
+ // absent case itself — the chart point requires a number.
23162
+ low: external_exports.number().int().nonnegative().optional()
22907
23163
  }).meta({ id: "FindingsTimeseriesPoint" });
22908
23164
  var FindingsTimeseriesResponse = external_exports.object({
22909
23165
  range: TimeRange,
@@ -22929,6 +23185,10 @@ var ResolvedFeedItem = external_exports.object({
22929
23185
  findingKey: external_exports.string(),
22930
23186
  ruleId: external_exports.string(),
22931
23187
  severity: Severity,
23188
+ // Repository slug, and the file path RELATIVE to it. The pair is what
23189
+ // identifies the file: a bare path matches the same name in every repo.
23190
+ // Optional and additive; empty when the event carried no repo.
23191
+ repo: external_exports.string().optional(),
22932
23192
  path: external_exports.string(),
22933
23193
  // ISO-8601 datetime (matches FindingInstance.detectedAt / the rest of the
22934
23194
  // findings domain). The reader `.toISOString()`s the DB epoch-ms values.
@@ -23034,7 +23294,23 @@ var SaveSettingsInput = external_exports.object({
23034
23294
  modelJudgeConsent: ModelJudgeConsentChoice,
23035
23295
  historySyncConsent: HistorySyncConsentChoice,
23036
23296
  vaultConsent: external_exports.string(),
23037
- vaultInlineReveal: external_exports.string()
23297
+ vaultInlineReveal: external_exports.string(),
23298
+ // Widened to `string` like its neighbours rather than typed as
23299
+ // `RedactFallback`, on this module's own layering rule: shape here, VALUE at
23300
+ // the call site, so the domain check receives the type it was written for.
23301
+ //
23302
+ // NOT because a narrower schema would reject differently. `parseActionInput`
23303
+ // is a `safeParse` wrapper and throws for no field schema, so either spelling
23304
+ // reaches a recoverable `{ ok: false }` and there is no rejected promise to
23305
+ // trade against. The real cost runs the other way and is the part worth
23306
+ // knowing: a value this schema admits and the domain enum then rejects lands
23307
+ // on the action's shared refusal, which names NO field, where a shape
23308
+ // rejection reaches `malformedInput` and names the schema key.
23309
+ redactFallback: external_exports.string(),
23310
+ // Shape only, the way the enum fields above are strings only: the RANGE is
23311
+ // `BodyRetention`'s and the action checks it there, so there is one place
23312
+ // that decides what a legal horizon is rather than two that can drift.
23313
+ bodyRetention: external_exports.object({ enabled: external_exports.boolean(), retainDays: external_exports.number() })
23038
23314
  });
23039
23315
  var AttachInput = external_exports.object({
23040
23316
  endpoint: external_exports.string(),
@@ -23160,13 +23436,59 @@ var SetupHandoffOffer = external_exports.object({
23160
23436
  path: ["liveKeys"]
23161
23437
  });
23162
23438
 
23439
+ // ../../packages/schema/src/zod/web-capture.ts
23440
+ var WebUsageSource = external_exports.enum(["site", "estimated", "none"]);
23441
+ var WebUsage = external_exports.object({
23442
+ inputTokens: external_exports.number().int().nonnegative().optional(),
23443
+ outputTokens: external_exports.number().int().nonnegative().optional(),
23444
+ cacheReadInputTokens: external_exports.number().int().nonnegative().optional(),
23445
+ cacheCreationInputTokens: external_exports.number().int().nonnegative().optional()
23446
+ });
23447
+ var WebToolCall = external_exports.object({
23448
+ toolUseId: external_exports.string().min(1),
23449
+ toolName: external_exports.string().min(1),
23450
+ target: external_exports.string().optional(),
23451
+ isError: external_exports.boolean().optional(),
23452
+ inputSize: external_exports.number().int().nonnegative().optional(),
23453
+ outputSize: external_exports.number().int().nonnegative().optional()
23454
+ });
23455
+ var WebExchange = external_exports.object({
23456
+ messageId: external_exports.string().min(1),
23457
+ startedAt: external_exports.iso.datetime(),
23458
+ model: external_exports.string().optional(),
23459
+ usage: WebUsage.optional(),
23460
+ usageSource: WebUsageSource,
23461
+ stopReason: external_exports.string().optional(),
23462
+ conversationId: external_exports.string().optional(),
23463
+ turnIndex: external_exports.number().int().nonnegative().optional(),
23464
+ toolCalls: external_exports.array(WebToolCall).default([]),
23465
+ // Absent when the adapter recovered no text. Capped by the caller at
23466
+ // RESPONSE_TEXT_MAX_BYTES; `truncated` records that the cap was reached, so a
23467
+ // short capture is never mistaken for a short reply.
23468
+ responseText: external_exports.string().optional(),
23469
+ truncated: external_exports.boolean().default(false)
23470
+ });
23471
+ var RESPONSE_TEXT_MAX_BYTES = 2 * 1024 * 1024;
23472
+ var WebCaptureStatus = external_exports.object({
23473
+ patched: external_exports.boolean(),
23474
+ live: external_exports.boolean(),
23475
+ blind: external_exports.boolean(),
23476
+ sendsSeenDom: external_exports.number().int().nonnegative(),
23477
+ exchangesSeenNet: external_exports.number().int().nonnegative(),
23478
+ parseFailures: external_exports.number().int().nonnegative(),
23479
+ unparsedBodies: external_exports.number().int().nonnegative(),
23480
+ // The adapter-declared JSON key paths that were absent from a real payload —
23481
+ // the earliest signal that a site's contract moved.
23482
+ shapeMisses: external_exports.array(external_exports.string()).default([])
23483
+ });
23484
+
23163
23485
  // src/provenance.ts
23164
23486
  import { execFileSync } from "child_process";
23165
23487
  var USE_SHELL = process.platform === "win32";
23166
23488
 
23167
23489
  // ../../packages/plugin-sdk/src/config.ts
23168
- import { existsSync as existsSync7 } from "fs";
23169
- import { join as join13 } from "path";
23490
+ import { existsSync as existsSync8 } from "fs";
23491
+ import { join as join16 } from "path";
23170
23492
 
23171
23493
  // ../../packages/persistence/src/attached-derived.ts
23172
23494
  import { rmSync } from "fs";
@@ -23204,6 +23526,32 @@ var STALE_PARTIAL_MS = 5 * 6e4;
23204
23526
  var SNAPSHOT_STAGING_SUFFIX = ".partial";
23205
23527
  var STAGED_NAME_SUFFIX = `.bak${SNAPSHOT_STAGING_SUFFIX}`;
23206
23528
 
23529
+ // ../../packages/persistence/src/internal/sql-functions.ts
23530
+ var utf8 = new TextDecoder();
23531
+
23532
+ // ../../packages/persistence/src/internal/outbox-lane.ts
23533
+ var OUTBOX_CAPTURE_EVENT_TYPES = ["prompt", "response", "tool_use"];
23534
+ var OUTBOX_CAPTURE_TYPE_LIST = OUTBOX_CAPTURE_EVENT_TYPES.map((t) => `'${t}'`).join(", ");
23535
+
23536
+ // ../../packages/persistence/src/sync-failure.ts
23537
+ var SYNC_FAILURE_REASONS = SyncFailureReason.options;
23538
+
23539
+ // ../../packages/persistence/src/repositories/history-sync.ts
23540
+ var STRUCTURAL_EVENT_TYPES = ["session", "llm_call", "tool_call"];
23541
+ var TYPE_LIST = STRUCTURAL_EVENT_TYPES.map((t) => `'${t}'`).join(", ");
23542
+ var COUNTED_EVENT_TYPES = [
23543
+ ...STRUCTURAL_EVENT_TYPES,
23544
+ ...OUTBOX_CAPTURE_EVENT_TYPES
23545
+ ];
23546
+ var COUNTED_TYPE_LIST = COUNTED_EVENT_TYPES.map((t) => `'${t}'`).join(", ");
23547
+ var COUNTED_SCOPE = `
23548
+ WHERE event_type IN (${COUNTED_TYPE_LIST})
23549
+ AND (
23550
+ event_type IN (${TYPE_LIST})
23551
+ OR synced_at IS NOT NULL
23552
+ OR outbox_owed = 1
23553
+ )`;
23554
+
23207
23555
  // ../../packages/persistence/src/repositories/activity.ts
23208
23556
  var LIVE_ACTIVITY_WINDOW_MS = 30 * 6e4;
23209
23557
  var DB_EVENT_TYPE_TO_KIND = {
@@ -23233,11 +23581,34 @@ var ACTIVE_REVEAL_GRANT_PREDICATE = `capability = 'reveal_to_model'
23233
23581
  AND conditions IS NULL
23234
23582
  AND ${ACTIVE_PREDICATE}`;
23235
23583
 
23236
- // ../../packages/persistence/src/repositories/history-sync.ts
23237
- var STRUCTURAL_EVENT_TYPES = ["session", "llm_call", "tool_call"];
23238
- var TYPE_LIST = STRUCTURAL_EVENT_TYPES.map((t) => `'${t}'`).join(", ");
23239
- var OUTBOX_CAPTURE_EVENT_TYPES = ["prompt", "response", "tool_use"];
23240
- var CAPTURE_TYPE_LIST = OUTBOX_CAPTURE_EVENT_TYPES.map((t) => `'${t}'`).join(", ");
23584
+ // ../../packages/persistence/src/repositories/resolution-sql.ts
23585
+ function latestResolutionColumnSql(column, findingsAlias) {
23586
+ return `(
23587
+ SELECT fr.${column} FROM finding_resolution fr
23588
+ WHERE fr.finding_key = ${findingsAlias}.finding_key
23589
+ ORDER BY fr.created_at DESC, fr.rowid DESC
23590
+ LIMIT 1
23591
+ )`;
23592
+ }
23593
+ function latestResolutionStatusSql(findingsAlias) {
23594
+ return latestResolutionColumnSql("status", findingsAlias);
23595
+ }
23596
+
23597
+ // ../../packages/persistence/src/repositories/findings.ts
23598
+ var FINDING_ROW_COLUMNS_SQL = `f.id AS id, d.rule_id AS rule_id, d.category AS category,
23599
+ d.severity AS severity, f.masked_match AS masked_match,
23600
+ f.action_taken AS action_taken, f.confidence AS confidence,
23601
+ e.started_at AS occurred_at,
23602
+ e.source_tool AS source_tool,
23603
+ e.repo AS repo,
23604
+ e.file_path AS file,
23605
+ e.tool_name AS tool_name,
23606
+ f.audit_event_id AS event_id, e.root_session_id AS session_id,
23607
+ e.event_type AS kind, f.finding_key AS finding_key,
23608
+ ${latestResolutionStatusSql("f")} AS latest_status,
23609
+ e.synced_at AS synced_at, e.sync_claimed_at AS sync_claimed_at,
23610
+ e.sync_failed_at AS sync_failed_at, e.sync_failure AS sync_failure,
23611
+ e.outbox_owed AS outbox_owed`;
23241
23612
 
23242
23613
  // ../../packages/persistence/src/repositories/installed-packs.ts
23243
23614
  import { createHash as createHash2, randomUUID as randomUUID4 } from "crypto";
@@ -23321,9 +23692,14 @@ import { randomUUID as randomUUID10 } from "crypto";
23321
23692
 
23322
23693
  // ../../packages/persistence/src/database.ts
23323
23694
  var CAPTURE_GRAIN = new Set(EventKind.options);
23695
+ var DEFERRED_TAGS = new Set(DEFERRED_MIGRATION_TAGS);
23324
23696
 
23325
- // ../../packages/persistence/src/finding-key.ts
23697
+ // ../../packages/persistence/src/egress-wire.ts
23326
23698
  import { createHash as createHash3 } from "crypto";
23699
+ var SLASH = "/".charCodeAt(0);
23700
+
23701
+ // ../../packages/persistence/src/finding-key.ts
23702
+ import { createHash as createHash4 } from "crypto";
23327
23703
 
23328
23704
  // ../../packages/persistence/src/fingerprint.ts
23329
23705
  import { createHmac, randomBytes } from "crypto";
@@ -23331,14 +23707,26 @@ import { existsSync as existsSync3, readFileSync as readFileSync6 } from "fs";
23331
23707
  import { join as join8 } from "path";
23332
23708
  import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
23333
23709
 
23334
- // ../../packages/persistence/src/history-preview.ts
23335
- import { existsSync as existsSync4 } from "fs";
23710
+ // ../../packages/persistence/src/forward-health.ts
23711
+ import { readFileSync as readFileSync7 } from "fs";
23336
23712
  import { join as join9 } from "path";
23713
+
23714
+ // ../../packages/persistence/src/history-backfill.ts
23715
+ import { existsSync as existsSync4 } from "fs";
23716
+ import { join as join10 } from "path";
23717
+
23718
+ // ../../packages/persistence/src/history-preview.ts
23719
+ import { existsSync as existsSync5 } from "fs";
23720
+ import { join as join11 } from "path";
23337
23721
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
23338
23722
 
23723
+ // ../../packages/persistence/src/history-sync-state.ts
23724
+ import { readFileSync as readFileSync8 } from "fs";
23725
+ import { join as join12 } from "path";
23726
+
23339
23727
  // ../../packages/persistence/src/store-symlinks.ts
23340
- import { existsSync as existsSync5, lstatSync as lstatSync3, readlinkSync, realpathSync, statSync as statSync4 } from "fs";
23341
- import { dirname as dirname3, join as join10, resolve } from "path";
23728
+ import { existsSync as existsSync6, lstatSync as lstatSync3, readlinkSync, realpathSync, statSync as statSync4 } from "fs";
23729
+ import { dirname as dirname3, join as join13, resolve } from "path";
23342
23730
 
23343
23731
  // ../../packages/persistence/src/vault/crypto.ts
23344
23732
  import {
@@ -23352,15 +23740,15 @@ import {
23352
23740
  // ../../packages/persistence/src/vault/key-provider.ts
23353
23741
  import { execFileSync as execFileSync2 } from "child_process";
23354
23742
  import { randomBytes as randomBytes2 } from "crypto";
23355
- import { chmodSync as chmodSync3, readFileSync as readFileSync7, renameSync as renameSync4, rmSync as rmSync6, statSync as statSync5, writeFileSync as writeFileSync3 } from "fs";
23356
- import { join as join11 } from "path";
23743
+ import { chmodSync as chmodSync3, readFileSync as readFileSync9, renameSync as renameSync4, rmSync as rmSync6, statSync as statSync5, writeFileSync as writeFileSync3 } from "fs";
23744
+ import { join as join14 } from "path";
23357
23745
 
23358
23746
  // ../../packages/persistence/src/vault/vault.ts
23359
23747
  import { randomBytes as randomBytes3, randomUUID as randomUUID12 } from "crypto";
23360
23748
 
23361
23749
  // ../../packages/persistence/src/warn-era-cap.ts
23362
- import { existsSync as existsSync6, writeFileSync as writeFileSync4 } from "fs";
23363
- import { join as join12 } from "path";
23750
+ import { existsSync as existsSync7, writeFileSync as writeFileSync4 } from "fs";
23751
+ import { join as join15 } from "path";
23364
23752
 
23365
23753
  // ../../packages/plugin-sdk/src/provider-env.ts
23366
23754
  var booleanish = external_exports.string().optional().transform((v) => {
@@ -23381,9 +23769,9 @@ var providerEnvShape = {
23381
23769
  var ProviderEnvSchema = external_exports.object(providerEnvShape);
23382
23770
 
23383
23771
  // ../../packages/plugin-sdk/src/config-inventory.ts
23384
- import { readdirSync as readdirSync2, readFileSync as readFileSync9, realpathSync as realpathSync2, statSync as statSync7 } from "fs";
23772
+ import { readdirSync as readdirSync2, readFileSync as readFileSync11, realpathSync as realpathSync2, statSync as statSync7 } from "fs";
23385
23773
  import { homedir as homedir2 } from "os";
23386
- import { basename as basename3, join as join15 } from "path";
23774
+ import { basename as basename3, join as join18 } from "path";
23387
23775
 
23388
23776
  // ../../packages/detections/src/egress/registry.ts
23389
23777
  var EXTRACTOR_VERSION = "1";
@@ -24141,24 +24529,20 @@ var CPU_CORROBORATION_SHARE = 0.2;
24141
24529
  var CORROBORATION_FLOOR_MS = BUDGET_MS * CPU_CORROBORATION_SHARE;
24142
24530
 
24143
24531
  // ../../packages/plugin-sdk/src/repo.ts
24144
- import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync6 } from "fs";
24145
- import { basename as basename2, dirname as dirname4, isAbsolute, join as join14, sep as sep2 } from "path";
24532
+ import { existsSync as existsSync9, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
24533
+ import { basename as basename2, dirname as dirname4, isAbsolute, join as join17, sep as sep2 } from "path";
24146
24534
 
24147
24535
  // ../../packages/plugin-sdk/src/events.ts
24148
- import { createHash as createHash4, randomUUID as randomUUID13 } from "crypto";
24536
+ import { createHash as createHash5, randomUUID as randomUUID13 } from "crypto";
24149
24537
 
24150
24538
  // ../../packages/plugin-sdk/src/isolated-scan.ts
24151
- import { existsSync as existsSync9 } from "fs";
24539
+ import { existsSync as existsSync10 } from "fs";
24152
24540
  import { fileURLToPath } from "url";
24153
24541
  import { Worker } from "worker_threads";
24154
24542
 
24155
- // ../../packages/plugin-sdk/src/ignore-layers.ts
24156
- var import_ignore = __toESM(require_ignore(), 1);
24157
- import { readFileSync as readFileSync10 } from "fs";
24158
- import { join as join16 } from "path";
24159
-
24160
- // ../../packages/plugin-sdk/src/inventory-resolver.ts
24161
- import { arch, hostname as hostname4, platform, release } from "os";
24543
+ // ../../packages/plugin-sdk/src/host-floor.ts
24544
+ import { readFileSync as readFileSync13 } from "fs";
24545
+ import { join as join20 } from "path";
24162
24546
 
24163
24547
  // ../../packages/plugin-sdk/src/model-governance.ts
24164
24548
  import {
@@ -24166,24 +24550,50 @@ import {
24166
24550
  fstatSync,
24167
24551
  mkdirSync as mkdirSync2,
24168
24552
  openSync as openSync2,
24169
- readFileSync as readFileSync11,
24553
+ readFileSync as readFileSync12,
24170
24554
  readSync,
24171
24555
  writeFileSync as writeFileSync5
24172
24556
  } from "fs";
24173
- import { join as join17 } from "path";
24557
+ import { join as join19 } from "path";
24174
24558
  var TAIL_BYTES = 256 * 1024;
24175
24559
 
24560
+ // ../../packages/plugin-sdk/src/host-floor.ts
24561
+ var HOST_FEATURE = {
24562
+ ModelSwitch: "model-switch",
24563
+ VaultPointerDisplay: "vault-pointer-display"
24564
+ };
24565
+ var HOST_FLOORS = {
24566
+ [HOST_FEATURE.ModelSwitch]: {
24567
+ label: "model-switch protection",
24568
+ hookEvents: ["PreModelSwitch", "PostModelSwitch"],
24569
+ since: "2.1.251"
24570
+ },
24571
+ [HOST_FEATURE.VaultPointerDisplay]: {
24572
+ label: "vault pointer display",
24573
+ hookEvents: ["MessageDisplay"],
24574
+ since: "2.1.152"
24575
+ }
24576
+ };
24577
+
24578
+ // ../../packages/plugin-sdk/src/ignore-layers.ts
24579
+ var import_ignore = __toESM(require_ignore(), 1);
24580
+ import { readFileSync as readFileSync14 } from "fs";
24581
+ import { join as join21 } from "path";
24582
+
24583
+ // ../../packages/plugin-sdk/src/inventory-resolver.ts
24584
+ import { arch, hostname as hostname4, platform, release } from "os";
24585
+
24176
24586
  // ../../packages/plugin-sdk/src/nudge.ts
24177
- import { mkdirSync as mkdirSync3, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "fs";
24178
- import { join as join18 } from "path";
24587
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync15, writeFileSync as writeFileSync6 } from "fs";
24588
+ import { join as join22 } from "path";
24179
24589
 
24180
24590
  // ../../packages/plugin-sdk/src/paths.ts
24181
24591
  import { readdirSync as readdirSync3, realpathSync as realpathSync3 } from "fs";
24182
24592
  import { basename as basename4, dirname as dirname5, sep as sep3 } from "path";
24183
24593
 
24184
24594
  // ../../packages/plugin-sdk/src/project-files.ts
24185
- import { existsSync as existsSync10, readdirSync as readdirSync4 } from "fs";
24186
- import { basename as basename5, join as join19 } from "path";
24595
+ import { existsSync as existsSync11, readdirSync as readdirSync4 } from "fs";
24596
+ import { basename as basename5, join as join23 } from "path";
24187
24597
 
24188
24598
  // ../../packages/plugin-sdk/src/provider-env-antigravity.ts
24189
24599
  var optionalBaseUrl2 = external_exports.preprocess((v) => {
@@ -24219,11 +24629,11 @@ var THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1e3;
24219
24629
 
24220
24630
  // ../../packages/plugin-sdk/src/throttle.ts
24221
24631
  import { mkdirSync as mkdirSync4, statSync as statSync8, writeFileSync as writeFileSync7 } from "fs";
24222
- import { join as join20 } from "path";
24632
+ import { join as join24 } from "path";
24223
24633
 
24224
24634
  // ../../packages/setup-wizard/src/remediation/rotation-checklist.ts
24225
24635
  import { writeFileSync as writeFileSync8 } from "fs";
24226
- import { join as join21 } from "path";
24636
+ import { join as join25 } from "path";
24227
24637
 
24228
24638
  // ../../packages/setup-wizard/src/triage/merge.ts
24229
24639
  var RANK = Object.fromEntries(
@@ -24231,9 +24641,9 @@ var RANK = Object.fromEntries(
24231
24641
  );
24232
24642
 
24233
24643
  // ../../packages/setup-wizard/src/triage/plan-file.ts
24234
- import { mkdtempSync, readFileSync as readFileSync13, rmdirSync, rmSync as rmSync7, writeFileSync as writeFileSync9 } from "fs";
24644
+ import { mkdtempSync, readFileSync as readFileSync16, rmdirSync, rmSync as rmSync7, writeFileSync as writeFileSync9 } from "fs";
24235
24645
  import { tmpdir } from "os";
24236
- import { basename as basename6, dirname as dirname6, join as join22 } from "path";
24646
+ import { basename as basename6, dirname as dirname6, join as join26 } from "path";
24237
24647
  var SuppressionEntrySchema = external_exports.object({
24238
24648
  ruleId: external_exports.string(),
24239
24649
  category: DetectionCategory,
@@ -24376,7 +24786,7 @@ function buildIntroCard(manifest2, verified) {
24376
24786
  var manifestPath = process.argv[2];
24377
24787
  var manifest = {};
24378
24788
  try {
24379
- manifest = JSON.parse(readFileSync14(manifestPath ?? "", "utf8"));
24789
+ manifest = JSON.parse(readFileSync17(manifestPath ?? "", "utf8"));
24380
24790
  } catch {
24381
24791
  }
24382
24792
  process.stdout.write(show(fenced(buildIntroCard(manifest))));