@akasecurity/cli 0.9.14 → 0.9.15

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.
Files changed (207) hide show
  1. package/dist/cli.js +762 -267
  2. package/extension/manifest.json +1 -1
  3. package/native-host/content-retention.js +184 -55
  4. package/native-host/history-sync.js +190 -61
  5. package/native-host/host.js +469 -120
  6. package/native-host/scan-worker.js +241 -34
  7. package/native-host/sync.js +91 -36
  8. package/package.json +9 -9
  9. package/web-ui/package.json +6 -6
  10. package/web-ui/packages/dashboard-ui/package.json +1 -1
  11. package/web-ui/packages/plugin-sdk/package.json +1 -1
  12. package/web-ui/packages/schema/package.json +2 -2
  13. package/web-ui/web-ui/.next/BUILD_ID +1 -1
  14. package/web-ui/web-ui/.next/app-build-manifest.json +254 -254
  15. package/web-ui/web-ui/.next/app-path-routes-manifest.json +7 -7
  16. package/web-ui/web-ui/.next/build-manifest.json +14 -14
  17. package/web-ui/web-ui/.next/prerender-manifest.json +14 -14
  18. package/web-ui/web-ui/.next/required-server-files.json +1 -1
  19. package/web-ui/web-ui/.next/server/app/(app)/activity/page.js +2 -2
  20. package/web-ui/web-ui/.next/server/app/(app)/activity/page.js.nft.json +1 -1
  21. package/web-ui/web-ui/.next/server/app/(app)/activity/page_client-reference-manifest.js +1 -1
  22. package/web-ui/web-ui/.next/server/app/(app)/data-shares/page.js +2 -2
  23. package/web-ui/web-ui/.next/server/app/(app)/data-shares/page.js.nft.json +1 -1
  24. package/web-ui/web-ui/.next/server/app/(app)/data-shares/page_client-reference-manifest.js +1 -1
  25. package/web-ui/web-ui/.next/server/app/(app)/detections/page.js +2 -2
  26. package/web-ui/web-ui/.next/server/app/(app)/detections/page.js.nft.json +1 -1
  27. package/web-ui/web-ui/.next/server/app/(app)/detections/page_client-reference-manifest.js +1 -1
  28. package/web-ui/web-ui/.next/server/app/(app)/exceptions/[id]/page.js +2 -2
  29. package/web-ui/web-ui/.next/server/app/(app)/exceptions/[id]/page.js.nft.json +1 -1
  30. package/web-ui/web-ui/.next/server/app/(app)/exceptions/[id]/page_client-reference-manifest.js +1 -1
  31. package/web-ui/web-ui/.next/server/app/(app)/exceptions/new/page.js +2 -2
  32. package/web-ui/web-ui/.next/server/app/(app)/exceptions/new/page.js.nft.json +1 -1
  33. package/web-ui/web-ui/.next/server/app/(app)/exceptions/new/page_client-reference-manifest.js +1 -1
  34. package/web-ui/web-ui/.next/server/app/(app)/exceptions/page.js +2 -2
  35. package/web-ui/web-ui/.next/server/app/(app)/exceptions/page.js.nft.json +1 -1
  36. package/web-ui/web-ui/.next/server/app/(app)/exceptions/page_client-reference-manifest.js +1 -1
  37. package/web-ui/web-ui/.next/server/app/(app)/findings/page.js +2 -2
  38. package/web-ui/web-ui/.next/server/app/(app)/findings/page.js.nft.json +1 -1
  39. package/web-ui/web-ui/.next/server/app/(app)/findings/page_client-reference-manifest.js +1 -1
  40. package/web-ui/web-ui/.next/server/app/(app)/inventory/page.js +2 -2
  41. package/web-ui/web-ui/.next/server/app/(app)/inventory/page.js.nft.json +1 -1
  42. package/web-ui/web-ui/.next/server/app/(app)/inventory/page_client-reference-manifest.js +1 -1
  43. package/web-ui/web-ui/.next/server/app/(app)/policies/page.js +2 -2
  44. package/web-ui/web-ui/.next/server/app/(app)/policies/page.js.nft.json +1 -1
  45. package/web-ui/web-ui/.next/server/app/(app)/policies/page_client-reference-manifest.js +1 -1
  46. package/web-ui/web-ui/.next/server/app/(app)/scan/page.js +3 -3
  47. package/web-ui/web-ui/.next/server/app/(app)/scan/page.js.nft.json +1 -1
  48. package/web-ui/web-ui/.next/server/app/(app)/scan/page_client-reference-manifest.js +1 -1
  49. package/web-ui/web-ui/.next/server/app/(app)/security/page.js +2 -2
  50. package/web-ui/web-ui/.next/server/app/(app)/security/page.js.nft.json +1 -1
  51. package/web-ui/web-ui/.next/server/app/(app)/security/page_client-reference-manifest.js +1 -1
  52. package/web-ui/web-ui/.next/server/app/(app)/settings/page.js +2 -2
  53. package/web-ui/web-ui/.next/server/app/(app)/settings/page.js.nft.json +1 -1
  54. package/web-ui/web-ui/.next/server/app/(app)/settings/page_client-reference-manifest.js +1 -1
  55. package/web-ui/web-ui/.next/server/app/(app)/updates/page.js +2 -2
  56. package/web-ui/web-ui/.next/server/app/(app)/updates/page.js.nft.json +1 -1
  57. package/web-ui/web-ui/.next/server/app/(app)/updates/page_client-reference-manifest.js +1 -1
  58. package/web-ui/web-ui/.next/server/app/(app)/vault/page.js +2 -2
  59. package/web-ui/web-ui/.next/server/app/(app)/vault/page.js.nft.json +1 -1
  60. package/web-ui/web-ui/.next/server/app/(app)/vault/page_client-reference-manifest.js +1 -1
  61. package/web-ui/web-ui/.next/server/app/_not-found/page.js +2 -2
  62. package/web-ui/web-ui/.next/server/app/_not-found/page.js.nft.json +1 -1
  63. package/web-ui/web-ui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  64. package/web-ui/web-ui/.next/server/app/_not-found.html +1 -1
  65. package/web-ui/web-ui/.next/server/app/_not-found.rsc +10 -10
  66. package/web-ui/web-ui/.next/server/app/icon.svg/route.js +1 -1
  67. package/web-ui/web-ui/.next/server/app/icon.svg/route.js.nft.json +1 -1
  68. package/web-ui/web-ui/.next/server/app/index.html +1 -1
  69. package/web-ui/web-ui/.next/server/app/index.rsc +10 -10
  70. package/web-ui/web-ui/.next/server/app/page.js +2 -2
  71. package/web-ui/web-ui/.next/server/app/page.js.nft.json +1 -1
  72. package/web-ui/web-ui/.next/server/app/page_client-reference-manifest.js +1 -1
  73. package/web-ui/web-ui/.next/server/app-paths-manifest.json +7 -7
  74. package/web-ui/web-ui/.next/server/chunks/184.js +1039 -0
  75. package/web-ui/web-ui/.next/server/chunks/245.js +11 -0
  76. package/web-ui/web-ui/.next/server/chunks/{670.js → 250.js} +1 -1
  77. package/web-ui/web-ui/.next/server/chunks/491.js +1 -0
  78. package/web-ui/web-ui/.next/server/chunks/51.js +1 -0
  79. package/web-ui/web-ui/.next/server/chunks/511.js +66 -0
  80. package/web-ui/web-ui/.next/server/chunks/537.js +1 -0
  81. package/web-ui/web-ui/.next/server/chunks/{74.js → 586.js} +55 -38
  82. package/web-ui/web-ui/.next/server/chunks/643.js +6 -0
  83. package/web-ui/web-ui/.next/server/chunks/660.js +109 -0
  84. package/web-ui/web-ui/.next/server/chunks/662.js +1 -0
  85. package/web-ui/web-ui/.next/server/chunks/749.js +22 -0
  86. package/web-ui/web-ui/.next/server/chunks/756.js +6 -0
  87. package/web-ui/web-ui/.next/server/chunks/774.js +12 -0
  88. package/web-ui/web-ui/.next/server/functions-config-manifest.json +5 -5
  89. package/web-ui/web-ui/.next/server/middleware-build-manifest.js +1 -1
  90. package/web-ui/web-ui/.next/server/middleware-manifest.json +5 -5
  91. package/web-ui/web-ui/.next/server/middleware.js +2 -2
  92. package/web-ui/web-ui/.next/server/pages/404.html +1 -1
  93. package/web-ui/web-ui/.next/server/pages/500.html +1 -1
  94. package/web-ui/web-ui/.next/server/pages/_app.js +1 -1
  95. package/web-ui/web-ui/.next/server/pages/_app.js.nft.json +1 -1
  96. package/web-ui/web-ui/.next/server/pages/_document.js +1 -1
  97. package/web-ui/web-ui/.next/server/pages/_document.js.nft.json +1 -1
  98. package/web-ui/web-ui/.next/server/pages/_error.js +3 -3
  99. package/web-ui/web-ui/.next/server/pages/_error.js.nft.json +1 -1
  100. package/web-ui/web-ui/.next/server/server-reference-manifest.js +1 -1
  101. package/web-ui/web-ui/.next/server/server-reference-manifest.json +1 -1
  102. package/web-ui/web-ui/.next/static/chunks/394-310a18b4e4df5baf.js +1 -0
  103. package/web-ui/web-ui/.next/static/chunks/458-51313fc93031a722.js +1 -0
  104. package/web-ui/web-ui/.next/static/chunks/784-4ea191865f1d4d08.js +1 -0
  105. package/web-ui/web-ui/.next/static/chunks/800-5a959d56ff462fa5.js +1 -0
  106. package/web-ui/web-ui/.next/static/chunks/982-d4c17097640bdc58.js +55 -0
  107. package/web-ui/web-ui/.next/static/chunks/app/(app)/activity/loading-1c2f7a583c03a3ac.js +1 -0
  108. package/web-ui/web-ui/.next/static/chunks/app/(app)/activity/page-6a2b4ce7f62aa2ba.js +1 -0
  109. package/web-ui/web-ui/.next/static/chunks/app/(app)/data-shares/loading-1c2f7a583c03a3ac.js +1 -0
  110. package/web-ui/web-ui/.next/static/chunks/app/(app)/data-shares/page-3032d8c5d83ed0ae.js +1 -0
  111. package/web-ui/web-ui/.next/static/chunks/app/(app)/detections/loading-1c2f7a583c03a3ac.js +1 -0
  112. package/web-ui/web-ui/.next/static/chunks/app/(app)/detections/page-541933106e3fbbd5.js +1 -0
  113. package/web-ui/web-ui/.next/static/chunks/app/(app)/error-8db18c71ebeb633c.js +1 -0
  114. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/[id]/loading-1c2f7a583c03a3ac.js +1 -0
  115. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/[id]/page-b2913fd29067c1aa.js +1 -0
  116. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/loading-1c2f7a583c03a3ac.js +1 -0
  117. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/new/loading-1c2f7a583c03a3ac.js +1 -0
  118. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/new/page-d71ddfb1b6a8508a.js +1 -0
  119. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/page-db4102808bb1d7ba.js +1 -0
  120. package/web-ui/web-ui/.next/static/chunks/app/(app)/findings/loading-1c2f7a583c03a3ac.js +1 -0
  121. package/web-ui/web-ui/.next/static/chunks/app/(app)/findings/page-8fc32e776e5c8f17.js +1 -0
  122. package/web-ui/web-ui/.next/static/chunks/app/(app)/inventory/loading-1c2f7a583c03a3ac.js +1 -0
  123. package/web-ui/web-ui/.next/static/chunks/app/(app)/inventory/page-5136fa903953a1f1.js +1 -0
  124. package/web-ui/web-ui/.next/static/chunks/app/(app)/layout-0a38af585fc577fa.js +1 -0
  125. package/web-ui/web-ui/.next/static/chunks/app/(app)/policies/loading-1c2f7a583c03a3ac.js +1 -0
  126. package/web-ui/web-ui/.next/static/chunks/app/(app)/policies/page-7b0a5b76d199ec55.js +1 -0
  127. package/web-ui/web-ui/.next/static/chunks/app/(app)/scan/loading-1c2f7a583c03a3ac.js +1 -0
  128. package/web-ui/web-ui/.next/static/chunks/app/(app)/scan/page-dd238c793fc58e5b.js +1 -0
  129. package/web-ui/web-ui/.next/static/chunks/app/(app)/security/loading-1c2f7a583c03a3ac.js +1 -0
  130. package/web-ui/web-ui/.next/static/chunks/app/(app)/security/page-27448935d7ce4168.js +1 -0
  131. package/web-ui/web-ui/.next/static/chunks/app/(app)/settings/loading-1c2f7a583c03a3ac.js +1 -0
  132. package/web-ui/web-ui/.next/static/chunks/app/(app)/settings/page-e8f75d1d2a05a860.js +1 -0
  133. package/web-ui/web-ui/.next/static/chunks/app/(app)/updates/loading-1c2f7a583c03a3ac.js +1 -0
  134. package/web-ui/web-ui/.next/static/chunks/app/(app)/updates/page-34525856979b2faf.js +1 -0
  135. package/web-ui/web-ui/.next/static/chunks/app/(app)/vault/loading-1c2f7a583c03a3ac.js +1 -0
  136. package/web-ui/web-ui/.next/static/chunks/app/(app)/vault/page-90ff82a26647fc29.js +1 -0
  137. package/web-ui/web-ui/.next/static/chunks/app/_not-found/page-688942265deca357.js +1 -0
  138. package/web-ui/web-ui/.next/static/chunks/app/layout-66e4db4cb3e3b073.js +1 -0
  139. package/web-ui/web-ui/.next/static/chunks/app/page-64c3ee82a8af8ca6.js +1 -0
  140. package/web-ui/web-ui/.next/static/chunks/fc2b9f2a-dbaa334f7301101d.js +1 -0
  141. package/web-ui/web-ui/.next/static/chunks/{framework-4a8a69f5ce633b25.js → framework-f6112ebf12822e8c.js} +1 -1
  142. package/web-ui/web-ui/.next/static/chunks/main-app-9c9fe8121a92e5d6.js +1 -0
  143. package/web-ui/web-ui/.next/static/chunks/main-b1c87d0ac6039542.js +1 -0
  144. package/web-ui/web-ui/.next/static/chunks/pages/_app-3a76cb93bbdd6993.js +1 -0
  145. package/web-ui/web-ui/.next/static/chunks/pages/_error-690c2fcfe129b529.js +1 -0
  146. package/web-ui/web-ui/.next/static/chunks/{webpack-c0fb35a40828243e.js → webpack-27570aabc530cb21.js} +1 -1
  147. package/web-ui/web-ui/.next/static/css/010b6061327092dd.css +2 -0
  148. package/web-ui/web-ui/.next/static/{5Pl1KmhN7uMqXkPkq0ZmS → zCQxcf2ZbK52vQeWXgBgs}/_buildManifest.js +1 -1
  149. package/web-ui/web-ui/dist/scan-worker.js +241 -34
  150. package/web-ui/web-ui/package.json +3 -3
  151. package/web-ui/web-ui/.next/server/chunks/167.js +0 -11
  152. package/web-ui/web-ui/.next/server/chunks/197.js +0 -12
  153. package/web-ui/web-ui/.next/server/chunks/247.js +0 -66
  154. package/web-ui/web-ui/.next/server/chunks/259.js +0 -22
  155. package/web-ui/web-ui/.next/server/chunks/285.js +0 -1
  156. package/web-ui/web-ui/.next/server/chunks/293.js +0 -1022
  157. package/web-ui/web-ui/.next/server/chunks/498.js +0 -1
  158. package/web-ui/web-ui/.next/server/chunks/524.js +0 -109
  159. package/web-ui/web-ui/.next/server/chunks/618.js +0 -1
  160. package/web-ui/web-ui/.next/server/chunks/807.js +0 -6
  161. package/web-ui/web-ui/.next/server/chunks/811.js +0 -6
  162. package/web-ui/web-ui/.next/server/chunks/97.js +0 -1
  163. package/web-ui/web-ui/.next/static/chunks/333-837ec42ac57bd0f5.js +0 -1
  164. package/web-ui/web-ui/.next/static/chunks/423b6282-fc44d01f7ffd176d.js +0 -1
  165. package/web-ui/web-ui/.next/static/chunks/539-ca04468e745ed73a.js +0 -1
  166. package/web-ui/web-ui/.next/static/chunks/614-2c96a5e95ce63862.js +0 -1
  167. package/web-ui/web-ui/.next/static/chunks/639-6f64a434dce13266.js +0 -1
  168. package/web-ui/web-ui/.next/static/chunks/826-e806952dd7b636f8.js +0 -55
  169. package/web-ui/web-ui/.next/static/chunks/app/(app)/activity/loading-dd5849a39c269cf4.js +0 -1
  170. package/web-ui/web-ui/.next/static/chunks/app/(app)/activity/page-5fc18420d8d5bf62.js +0 -1
  171. package/web-ui/web-ui/.next/static/chunks/app/(app)/data-shares/loading-dd5849a39c269cf4.js +0 -1
  172. package/web-ui/web-ui/.next/static/chunks/app/(app)/data-shares/page-fe72214e54d52a14.js +0 -1
  173. package/web-ui/web-ui/.next/static/chunks/app/(app)/detections/loading-dd5849a39c269cf4.js +0 -1
  174. package/web-ui/web-ui/.next/static/chunks/app/(app)/detections/page-47e4dd015f24c04d.js +0 -1
  175. package/web-ui/web-ui/.next/static/chunks/app/(app)/error-be2032a4770a35bf.js +0 -1
  176. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/[id]/loading-dd5849a39c269cf4.js +0 -1
  177. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/[id]/page-f90fbb03406e4383.js +0 -1
  178. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/loading-dd5849a39c269cf4.js +0 -1
  179. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/new/loading-dd5849a39c269cf4.js +0 -1
  180. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/new/page-0a1d6a3557b99750.js +0 -1
  181. package/web-ui/web-ui/.next/static/chunks/app/(app)/exceptions/page-dbf32c5303140e8c.js +0 -1
  182. package/web-ui/web-ui/.next/static/chunks/app/(app)/findings/loading-dd5849a39c269cf4.js +0 -1
  183. package/web-ui/web-ui/.next/static/chunks/app/(app)/findings/page-cb1934547acde891.js +0 -1
  184. package/web-ui/web-ui/.next/static/chunks/app/(app)/inventory/loading-dd5849a39c269cf4.js +0 -1
  185. package/web-ui/web-ui/.next/static/chunks/app/(app)/inventory/page-6688bc58741c7c7d.js +0 -1
  186. package/web-ui/web-ui/.next/static/chunks/app/(app)/layout-d357a1d54c653d14.js +0 -1
  187. package/web-ui/web-ui/.next/static/chunks/app/(app)/policies/loading-dd5849a39c269cf4.js +0 -1
  188. package/web-ui/web-ui/.next/static/chunks/app/(app)/policies/page-bc95c7097cca0dfc.js +0 -1
  189. package/web-ui/web-ui/.next/static/chunks/app/(app)/scan/loading-dd5849a39c269cf4.js +0 -1
  190. package/web-ui/web-ui/.next/static/chunks/app/(app)/scan/page-5bebd818c1bb3a79.js +0 -1
  191. package/web-ui/web-ui/.next/static/chunks/app/(app)/security/loading-dd5849a39c269cf4.js +0 -1
  192. package/web-ui/web-ui/.next/static/chunks/app/(app)/security/page-42845dce0b734eeb.js +0 -1
  193. package/web-ui/web-ui/.next/static/chunks/app/(app)/settings/loading-dd5849a39c269cf4.js +0 -1
  194. package/web-ui/web-ui/.next/static/chunks/app/(app)/settings/page-d3ce8a503e8ce592.js +0 -1
  195. package/web-ui/web-ui/.next/static/chunks/app/(app)/updates/loading-dd5849a39c269cf4.js +0 -1
  196. package/web-ui/web-ui/.next/static/chunks/app/(app)/updates/page-802942c0a06fbe31.js +0 -1
  197. package/web-ui/web-ui/.next/static/chunks/app/(app)/vault/loading-dd5849a39c269cf4.js +0 -1
  198. package/web-ui/web-ui/.next/static/chunks/app/(app)/vault/page-52c8cd3a2a09a067.js +0 -1
  199. package/web-ui/web-ui/.next/static/chunks/app/_not-found/page-260d84f0d7697773.js +0 -1
  200. package/web-ui/web-ui/.next/static/chunks/app/layout-c64d57251ee073d5.js +0 -1
  201. package/web-ui/web-ui/.next/static/chunks/app/page-b7ea78b4203d219b.js +0 -1
  202. package/web-ui/web-ui/.next/static/chunks/main-89a5d50418a9a7e3.js +0 -1
  203. package/web-ui/web-ui/.next/static/chunks/main-app-4a18e3117ef3af1e.js +0 -1
  204. package/web-ui/web-ui/.next/static/chunks/pages/_app-671d04cd06b05cac.js +0 -1
  205. package/web-ui/web-ui/.next/static/chunks/pages/_error-ae172b6a97f64258.js +0 -1
  206. package/web-ui/web-ui/.next/static/css/616a1cc3e0d40480.css +0 -2
  207. /package/web-ui/web-ui/.next/static/{5Pl1KmhN7uMqXkPkq0ZmS → zCQxcf2ZbK52vQeWXgBgs}/_ssgManifest.js +0 -0
@@ -32,9 +32,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
32
32
  mod
33
33
  ));
34
34
 
35
- // ../../node_modules/.pnpm/ignore@7.0.9/node_modules/ignore/index.js
35
+ // ../../node_modules/.pnpm/ignore@7.0.10/node_modules/ignore/index.js
36
36
  var require_ignore = __commonJS({
37
- "../../node_modules/.pnpm/ignore@7.0.9/node_modules/ignore/index.js"(exports, module) {
37
+ "../../node_modules/.pnpm/ignore@7.0.10/node_modules/ignore/index.js"(exports, module) {
38
38
  "use strict";
39
39
  function makeArray(subject) {
40
40
  return Array.isArray(subject) ? subject : [subject];
@@ -429,6 +429,13 @@ var require_ignore = __commonJS({
429
429
  }
430
430
  };
431
431
  var WILDCARD = "[^\\/]*";
432
+ var separatorAfter = (run, at) => {
433
+ let separator = EMPTY;
434
+ for (let index = at + 1; index < run.length && !run[index].wildcard; index++) {
435
+ separator += run[index].single;
436
+ }
437
+ return separator;
438
+ };
432
439
  var pinWildcards = (source) => {
433
440
  if (source.indexOf(WILDCARD) < 0) {
434
441
  return source;
@@ -498,7 +505,7 @@ var require_ignore = __commonJS({
498
505
  out += token.single;
499
506
  return;
500
507
  }
501
- out += at === lastWildcard ? WILDCARD : `(?:(?!${run[at + 1].single})[^\\/])*`;
508
+ out += at === lastWildcard ? WILDCARD : `(?:(?!${separatorAfter(run, at)})[^\\/])*`;
502
509
  });
503
510
  run = [];
504
511
  };
@@ -675,13 +682,13 @@ var require_ignore = __commonJS({
675
682
  const rules = this._rules;
676
683
  const { length } = rules;
677
684
  const shortcut = this._basenameCount * 2 >= length;
678
- const basename7 = shortcut ? basenameOf(path) : path;
685
+ const basename8 = shortcut ? basenameOf(path) : path;
679
686
  for (let index = 0; index < length; index++) {
680
687
  const rule = rules[index];
681
688
  const { negative } = rule;
682
689
  const skip = unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored;
683
690
  if (!skip && rule[mode].test(
684
- shortcut && rule._basenameOnly ? basename7 : path
691
+ shortcut && rule._basenameOnly ? basename8 : path
685
692
  )) {
686
693
  ignored = !negative;
687
694
  unignored = negative;
@@ -1002,6 +1009,10 @@ var SQLITE_MIGRATIONS = [
1002
1009
  {
1003
1010
  tag: "0035_share_destination_provider_id",
1004
1011
  sql: "ALTER TABLE `share_destination` ADD `provider_id` text;"
1012
+ },
1013
+ {
1014
+ tag: "0036_secret_vault_identity_fingerprint",
1015
+ sql: "ALTER TABLE `secret_vault` ADD `value_identity_fingerprint` text DEFAULT '' NOT NULL;--> statement-breakpoint\nUPDATE `secret_vault` SET `value_identity_fingerprint` = `value_fingerprint`;\n"
1005
1016
  }
1006
1017
  ];
1007
1018
 
@@ -1011,6 +1022,12 @@ var HOUR_MS = 60 * MINUTE_MS;
1011
1022
  var MAX_TEMPORARY_MS = 24 * HOUR_MS;
1012
1023
  var ONCE_BACKSTOP_MS = 30 * MINUTE_MS;
1013
1024
 
1025
+ // ../../packages/schema/src/invisible-padding.ts
1026
+ var INVISIBLE_PADDING = /[\u00AD\u200B\u2060-\u2064\u202A-\u202E\u2066-\u2069\uFEFF\u{E0001}\u{E0020}-\u{E007F}]/gu;
1027
+ function stripInvisiblePadding(text) {
1028
+ return text.replace(INVISIBLE_PADDING, "");
1029
+ }
1030
+
1014
1031
  // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/external.js
1015
1032
  var external_exports = {};
1016
1033
  __export(external_exports, {
@@ -6037,7 +6054,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
6037
6054
  var NONE = 0;
6038
6055
  var ASSUMED = 1;
6039
6056
  var PROVEN = 2;
6040
- function isRecursive(inst, stack, resolve2) {
6057
+ function isRecursive(inst, stack, resolve3) {
6041
6058
  const cached2 = recursive.get(inst);
6042
6059
  if (cached2 !== void 0)
6043
6060
  return cached2 ? PROVEN : NONE;
@@ -6047,7 +6064,7 @@ function isRecursive(inst, stack, resolve2) {
6047
6064
  let result = NONE;
6048
6065
  const check2 = (child) => {
6049
6066
  if (result !== PROVEN && child?._zod) {
6050
- const answer = isRecursive(child, stack, resolve2);
6067
+ const answer = isRecursive(child, stack, resolve3);
6051
6068
  if (answer > result)
6052
6069
  result = answer;
6053
6070
  }
@@ -6058,7 +6075,7 @@ function isRecursive(inst, stack, resolve2) {
6058
6075
  const desc = Object.getOwnPropertyDescriptor(sh, key);
6059
6076
  if (spread && !desc.enumerable)
6060
6077
  continue;
6061
- const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve2) : NONE;
6078
+ const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve3) : NONE;
6062
6079
  if (child > answer)
6063
6080
  answer = child;
6064
6081
  }
@@ -6122,7 +6139,7 @@ function isRecursive(inst, stack, resolve2) {
6122
6139
  break;
6123
6140
  // `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
6124
6141
  case "lazy": {
6125
- const inner = def._cachedInner ?? (resolve2 ? inst._zod.innerType : void 0);
6142
+ const inner = def._cachedInner ?? (resolve3 ? inst._zod.innerType : void 0);
6126
6143
  merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
6127
6144
  break;
6128
6145
  }
@@ -23520,7 +23537,29 @@ var StorePosturePlugin = external_exports.object({
23520
23537
  */
23521
23538
  policyBundleVersion: external_exports.string().max(200).nullable(),
23522
23539
  /** Epoch millis, on the CLIENT clock, of that fetch. */
23523
- policyFetchedAt: external_exports.number().int().min(0).max(MAX_DATE_MS).nullable()
23540
+ policyFetchedAt: external_exports.number().int().min(0).max(MAX_DATE_MS).nullable(),
23541
+ /**
23542
+ * The newest version the host's own install record holds for this plugin —
23543
+ * what is on disk. After an update it leads `version` (the running copy) by
23544
+ * one launch. Null when no usable version can be read: no install record
23545
+ * (a plugin run from a checkout), no entry with a valid version, or every
23546
+ * such entry names an `installPath` that no longer exists; OPTIONAL, not
23547
+ * required, so a build that predates the member keeps getting its 200.
23548
+ * Bounded like `version`.
23549
+ */
23550
+ installedVersion: external_exports.string().max(64).nullable().optional(),
23551
+ /**
23552
+ * The local-store schema version this running build migrates a store to:
23553
+ * the number of store migrations it carries, the count it stamps into
23554
+ * `PRAGMA user_version`. A snapshot whose `schemaVersion` is above it
23555
+ * usually describes a store a newer build migrated. It is a hint, not a
23556
+ * verdict: the stamp is write-only, so a store whose count ran past this
23557
+ * build's while this build knows every migration in its ledger reads above
23558
+ * it too, which is why describeStoreSkew decides skew on ledger tags and
23559
+ * never on the count. OPTIONAL for the same reason as `installedVersion`;
23560
+ * bounded like `schemaVersion`.
23561
+ */
23562
+ buildSchemaVersion: external_exports.number().int().min(0).max(MAX_INT4).optional()
23524
23563
  }).meta({ id: "StorePosturePlugin" });
23525
23564
  var StorePostureSnapshot = external_exports.object({
23526
23565
  deviceId: external_exports.guid(),
@@ -25163,10 +25202,15 @@ var ParsedPointer = external_exports.object({
25163
25202
  });
25164
25203
  var VaultEntry = external_exports.object({
25165
25204
  pointerId: external_exports.string(),
25166
- // The keyed HMAC of the raw value under `exception.key`, and the epoch it was
25167
- // derived under. This is what a reveal-to-model grant matches on, and it rotates
25168
- // independently of the vault encryption key below.
25205
+ // The keyed HMAC of the EXACT raw bytes under `exception.key`, and the epoch it
25206
+ // was derived under. The vault's own dedupe key: a value and its invisibly
25207
+ // padded twin are two rows. It rotates independently of the vault encryption
25208
+ // key below. Never matched against an exception or grant.
25169
25209
  valueFingerprint: external_exports.string().regex(/^[0-9a-f]{64}$/),
25210
+ // The same HMAC over the raw with invisible padding removed: the identity a
25211
+ // reveal-to-model grant and every exception match on. Shared by a value and
25212
+ // its padded twin.
25213
+ valueIdentityFingerprint: external_exports.string().regex(/^[0-9a-f]{64}$/),
25170
25214
  fingerprintKeyVersion: external_exports.number().int().positive(),
25171
25215
  // The vault-key epoch this row's ciphertext was sealed under.
25172
25216
  keyVersion: external_exports.number().int().positive(),
@@ -25751,10 +25795,18 @@ var SeveritySummaryItem = external_exports.object({
25751
25795
  count: external_exports.number().int().nonnegative(),
25752
25796
  // Resolution-aware breakdown (optional, additive). Populated once findings
25753
25797
  // carry lifecycle state: `caught` = handled in-flight (enforced); `openAtRest`
25754
- // = still open with no in-flight enforcement (needs remediation). Absent on the
25755
- // legacy count-only response until the resolution feature lands.
25798
+ // = still open with no in-flight enforcement (needs remediation); `dismissed`
25799
+ // = closed by a human judgement rather than a fix — visible, but not counted as
25800
+ // needing remediation. The three are disjoint. Absent on the legacy count-only
25801
+ // response until the resolution feature lands.
25756
25802
  caught: external_exports.number().int().nonnegative().optional(),
25757
- openAtRest: external_exports.number().int().nonnegative().optional()
25803
+ openAtRest: external_exports.number().int().nonnegative().optional(),
25804
+ dismissed: external_exports.number().int().nonnegative().optional(),
25805
+ // The two halves of `caught`, for a reader that wants them apart: `handled` =
25806
+ // in-flight findings an enforcement action already contained; `resolved` =
25807
+ // at-rest findings closed out by fixing them. `handled + resolved === caught`.
25808
+ handled: external_exports.number().int().nonnegative().optional(),
25809
+ resolved: external_exports.number().int().nonnegative().optional()
25758
25810
  }).meta({ id: "SeveritySummaryItem" });
25759
25811
  var SeveritySummaryResponse = external_exports.object({
25760
25812
  // Sum of bySeverity[].count.
@@ -25762,6 +25814,9 @@ var SeveritySummaryResponse = external_exports.object({
25762
25814
  // Findings still open at rest (sum of bySeverity[].openAtRest). Optional and
25763
25815
  // additive — absent on the legacy response until the resolution feature lands.
25764
25816
  needsRemediation: external_exports.number().int().nonnegative().optional(),
25817
+ // Findings a user dismissed (sum of bySeverity[].dismissed). Excluded from
25818
+ // needsRemediation, and kept visible here so an accepted risk is not erased.
25819
+ dismissed: external_exports.number().int().nonnegative().optional(),
25765
25820
  // All four severity levels are always present (count may be 0).
25766
25821
  bySeverity: external_exports.array(SeveritySummaryItem)
25767
25822
  }).meta({ id: "SeveritySummaryResponse" });
@@ -26395,11 +26450,11 @@ function repairOrRefuseMode(file2) {
26395
26450
  const link = lstatSync2(file2, { throwIfNoEntry: false });
26396
26451
  if (link === void 0) return "absent";
26397
26452
  if (link.isSymbolicLink()) return "untrusted";
26398
- const stat = statSync(file2, { throwIfNoEntry: false });
26399
- if (stat === void 0) return "absent";
26453
+ const stat2 = statSync(file2, { throwIfNoEntry: false });
26454
+ if (stat2 === void 0) return "absent";
26400
26455
  const uid = process.getuid?.();
26401
- if (uid !== void 0 && stat.uid !== uid) return "untrusted";
26402
- if (process.platform !== "win32" && (stat.mode & 511) !== DATA_FILE_MODE) {
26456
+ if (uid !== void 0 && stat2.uid !== uid) return "untrusted";
26457
+ if (process.platform !== "win32" && (stat2.mode & 511) !== DATA_FILE_MODE) {
26403
26458
  try {
26404
26459
  chmodSync2(file2, DATA_FILE_MODE);
26405
26460
  } catch {
@@ -26415,9 +26470,9 @@ function readControlPlaneCredentialState(settingsDir2, connection) {
26415
26470
  function readControlPlaneCredentialFile(settingsDir2, connection) {
26416
26471
  const file2 = controlPlaneCredentialPath(settingsDir2);
26417
26472
  let raw;
26418
- const gate = repairOrRefuseMode(file2);
26419
- if (gate === "absent") return { usable: false, reason: "absent" };
26420
- if (gate === "untrusted") return { usable: false, reason: "untrusted-file" };
26473
+ const gate2 = repairOrRefuseMode(file2);
26474
+ if (gate2 === "absent") return { usable: false, reason: "absent" };
26475
+ if (gate2 === "untrusted") return { usable: false, reason: "untrusted-file" };
26421
26476
  try {
26422
26477
  raw = readFileSync(file2, "utf8");
26423
26478
  } catch (err) {
@@ -32562,7 +32617,10 @@ var SqliteResolutionsRepository = class {
32562
32617
  * Insert many dispositions as ONE transaction — all of them or none.
32563
32618
  *
32564
32619
  * A dashboard dismissal closes every open finding of a rule, which is one
32565
- * write per key; run loose, a fault partway leaves half a rule closed with
32620
+ * write per key. It reaches this through
32621
+ * `LocalDatabase.dismissOpenFindingsForRule`, which calls it inside the
32622
+ * transaction that selected the keys, so there it runs as a SAVEPOINT of
32623
+ * that transaction. Run loose, a fault partway leaves half a rule closed with
32566
32624
  * nothing recording that the other half was meant to be. The caller then has
32567
32625
  * no way to tell a partial run from a complete one, because the card it
32568
32626
  * refreshes into just shows a smaller number either way.
@@ -32782,6 +32840,7 @@ function toSighting(row) {
32782
32840
  var SELECT_COLUMNS = `
32783
32841
  pointer_id AS pointerId,
32784
32842
  value_fingerprint AS valueFingerprint,
32843
+ value_identity_fingerprint AS valueIdentityFingerprint,
32785
32844
  fingerprint_key_version AS fingerprintKeyVersion,
32786
32845
  key_version AS keyVersion,
32787
32846
  format_version AS formatVersion,
@@ -32806,13 +32865,13 @@ var SqliteSecretVaultRepository = class {
32806
32865
  this.db = db;
32807
32866
  this.insertStmt = db.prepare(
32808
32867
  `INSERT INTO secret_vault (
32809
- pointer_id, value_fingerprint, fingerprint_key_version, key_version,
32810
- format_version, category, rule_id, masked_match, provider,
32868
+ pointer_id, value_fingerprint, value_identity_fingerprint,
32869
+ fingerprint_key_version, key_version, format_version, category, rule_id, masked_match, provider,
32811
32870
  ciphertext, nonce, auth_tag,
32812
32871
  user_authorized, occurrence_count, first_seen, last_seen
32813
32872
  ) VALUES (
32814
- :pointerId, :valueFingerprint, :fingerprintKeyVersion, :keyVersion,
32815
- :formatVersion, :category, :ruleId, :maskedMatch, :provider,
32873
+ :pointerId, :valueFingerprint, :valueIdentityFingerprint,
32874
+ :fingerprintKeyVersion, :keyVersion, :formatVersion, :category, :ruleId, :maskedMatch, :provider,
32816
32875
  :ciphertext, :nonce, :authTag,
32817
32876
  :userAuthorized, 1, :now, :now
32818
32877
  )`
@@ -32837,7 +32896,13 @@ var SqliteSecretVaultRepository = class {
32837
32896
  );
32838
32897
  this.refreshFingerprintStmt = db.prepare(
32839
32898
  `UPDATE secret_vault
32840
- SET value_fingerprint = :valueFingerprint, fingerprint_key_version = :fingerprintKeyVersion
32899
+ SET value_fingerprint = :valueFingerprint,
32900
+ value_identity_fingerprint = :valueIdentityFingerprint,
32901
+ fingerprint_key_version = :fingerprintKeyVersion
32902
+ WHERE pointer_id = :pointerId`
32903
+ );
32904
+ this.setIdentityStmt = db.prepare(
32905
+ `UPDATE secret_vault SET value_identity_fingerprint = :valueIdentityFingerprint
32841
32906
  WHERE pointer_id = :pointerId`
32842
32907
  );
32843
32908
  this.deleteByPointerStmt = db.prepare(`DELETE FROM secret_vault WHERE pointer_id = :pointerId`);
@@ -32854,6 +32919,7 @@ var SqliteSecretVaultRepository = class {
32854
32919
  listStmt;
32855
32920
  replaceCiphertextStmt;
32856
32921
  refreshFingerprintStmt;
32922
+ setIdentityStmt;
32857
32923
  deleteByPointerStmt;
32858
32924
  derefStmt;
32859
32925
  /**
@@ -32884,6 +32950,7 @@ var SqliteSecretVaultRepository = class {
32884
32950
  bindParams({
32885
32951
  pointerId: input2.pointerId,
32886
32952
  valueFingerprint: input2.valueFingerprint,
32953
+ valueIdentityFingerprint: input2.valueIdentityFingerprint,
32887
32954
  fingerprintKeyVersion: input2.fingerprintKeyVersion,
32888
32955
  keyVersion: input2.keyVersion,
32889
32956
  formatVersion: input2.formatVersion ?? POINTER_FORMAT_VERSION,
@@ -32945,7 +33012,15 @@ var SqliteSecretVaultRepository = class {
32945
33012
  replaceCiphertext(pointerId, next) {
32946
33013
  this.replaceCiphertextStmt.run({ pointerId, ...next });
32947
33014
  }
32948
- /** Re-derive an entry's fingerprint under a new fingerprint-key epoch. */
33015
+ /**
33016
+ * Correct an entry's identity fingerprint in place, leaving its exact
33017
+ * fingerprint and key epoch alone. For a row whose identity column still holds
33018
+ * the exact value copied in by the migration that added it.
33019
+ */
33020
+ setIdentityFingerprint(pointerId, valueIdentityFingerprint) {
33021
+ this.setIdentityStmt.run({ pointerId, valueIdentityFingerprint });
33022
+ }
33023
+ /** Re-derive an entry's fingerprints under a new fingerprint-key epoch. */
32949
33024
  refreshFingerprint(pointerId, next) {
32950
33025
  this.refreshFingerprintStmt.run({ pointerId, ...next });
32951
33026
  }
@@ -33076,7 +33151,7 @@ var SqliteSecretVaultRepository = class {
33076
33151
  `SELECT ${INVENTORY_COLUMNS},
33077
33152
  (SELECT e.id FROM exceptions e
33078
33153
  WHERE e.rule_id = v.rule_id
33079
- AND e.value_fingerprint = v.value_fingerprint
33154
+ AND e.value_fingerprint = v.value_identity_fingerprint
33080
33155
  AND e.key_version = v.fingerprint_key_version
33081
33156
  AND ${ACTIVE_REVEAL_GRANT_PREDICATE}
33082
33157
  LIMIT 1) AS grant_id
@@ -33119,7 +33194,7 @@ var SqliteSecretVaultRepository = class {
33119
33194
  `SELECT ${INVENTORY_COLUMNS},
33120
33195
  (SELECT e.id FROM exceptions e
33121
33196
  WHERE e.rule_id = v.rule_id
33122
- AND e.value_fingerprint = v.value_fingerprint
33197
+ AND e.value_fingerprint = v.value_identity_fingerprint
33123
33198
  AND e.key_version = v.fingerprint_key_version
33124
33199
  AND ${ACTIVE_REVEAL_GRANT_PREDICATE}
33125
33200
  LIMIT 1) AS grant_id
@@ -33223,6 +33298,18 @@ var OPEN_AT_REST_FINDINGS_SQL = `FROM inspection_findings f
33223
33298
  OR latest.status IS NULL
33224
33299
  OR latest.status NOT IN ('resolved', 'dismissed')
33225
33300
  )`;
33301
+ function selectOpenFindingKeysForRule(db, ruleId) {
33302
+ const rows = allRows(
33303
+ db.prepare(
33304
+ `SELECT DISTINCT f.finding_key AS finding_key
33305
+ ${OPEN_AT_REST_FINDINGS_SQL}
33306
+ AND d.rule_id = :ruleId
33307
+ AND f.finding_key IS NOT NULL`
33308
+ ),
33309
+ { ruleId }
33310
+ );
33311
+ return rows.map((r) => r.finding_key);
33312
+ }
33226
33313
  var SEVERITIES = ["critical", "high", "medium", "low"];
33227
33314
  var ACTION_TO_KIND = {
33228
33315
  block: "blocked",
@@ -33279,16 +33366,16 @@ var SqliteSecurityRepository = class {
33279
33366
  // findings are caught only once their latest disposition is resolved,
33280
33367
  // otherwise they are open-at-rest.
33281
33368
  //
33282
- // NOTE for future manual-resolution writers: only latest status
33283
- // 'resolved' counts as caught above. When acknowledged/dismissed/
33284
- // false-positive manual dispositions land, this must keep filtering by
33285
- // status/method — 'acknowledged' is accepted risk, not a fix, and must NOT
33286
- // be bucketed as caught alongside 'resolved'.
33369
+ // Only latest status 'resolved' counts as caught above. 'dismissed' is its
33370
+ // own bucket: a judgement rather than a fix, so it is neither caught nor
33371
+ // needing remediation, and stays countable. A further manual disposition
33372
+ // (acknowledged, false-positive) must be placed deliberately — 'acknowledged'
33373
+ // is accepted risk, not a fix, and must NOT be bucketed as caught.
33287
33374
  //
33288
33375
  // Legacy at-rest findings from pre-branch scans carry finding_key = NULL —
33289
33376
  // the resolution lifecycle is keyed by finding_key, so it can never attach a
33290
33377
  // disposition to (or clear) one of these on re-scan. They are excluded from
33291
- // both caught and openAtRest (untracked, not "needs remediation forever"),
33378
+ // all three buckets (untracked, not "needs remediation forever"),
33292
33379
  // but still counted in total/count below — this keeps this predicate
33293
33380
  // consistent with SqliteResolutionsRepository.openAtRestKeysForPath, which
33294
33381
  // already filters `finding_key IS NOT NULL`.
@@ -33311,12 +33398,25 @@ var SqliteSecurityRepository = class {
33311
33398
  WHEN latest.status = 'resolved' THEN 1
33312
33399
  ELSE 0
33313
33400
  END) AS caught,
33401
+ SUM(CASE WHEN e.event_type != 'code_change' THEN 1 ELSE 0 END) AS handled,
33402
+ SUM(CASE
33403
+ WHEN e.event_type = 'code_change'
33404
+ AND f.finding_key IS NOT NULL
33405
+ AND latest.status = 'resolved' THEN 1
33406
+ ELSE 0
33407
+ END) AS resolved,
33314
33408
  SUM(CASE
33315
33409
  WHEN e.event_type = 'code_change'
33316
33410
  AND f.finding_key IS NOT NULL
33317
- AND (latest.status IS NULL OR latest.status != 'resolved') THEN 1
33411
+ AND (latest.status IS NULL
33412
+ OR latest.status NOT IN ('resolved', 'dismissed')) THEN 1
33413
+ ELSE 0
33414
+ END) AS open_at_rest,
33415
+ SUM(CASE
33416
+ WHEN e.event_type = 'code_change'
33417
+ AND latest.status = 'dismissed' THEN 1
33318
33418
  ELSE 0
33319
- END) AS open_at_rest
33419
+ END) AS dismissed
33320
33420
  FROM inspection_findings f
33321
33421
  JOIN audit_events e INDEXED BY idx_audit_capture_rollup ON e.id = f.audit_event_id
33322
33422
  JOIN inspection_definitions d ON d.id = f.inspection_definition_id
@@ -33331,11 +33431,15 @@ var SqliteSecurityRepository = class {
33331
33431
  severity,
33332
33432
  count: byRow.get(severity)?.count ?? 0,
33333
33433
  caught: byRow.get(severity)?.caught ?? 0,
33334
- openAtRest: byRow.get(severity)?.open_at_rest ?? 0
33434
+ handled: byRow.get(severity)?.handled ?? 0,
33435
+ resolved: byRow.get(severity)?.resolved ?? 0,
33436
+ openAtRest: byRow.get(severity)?.open_at_rest ?? 0,
33437
+ dismissed: byRow.get(severity)?.dismissed ?? 0
33335
33438
  }));
33336
33439
  const total = bySeverity.reduce((sum, s) => sum + s.count, 0);
33337
33440
  const needsRemediation = bySeverity.reduce((sum, s) => sum + s.openAtRest, 0);
33338
- return Promise.resolve({ total, needsRemediation, bySeverity });
33441
+ const dismissed = bySeverity.reduce((sum, s) => sum + s.dismissed, 0);
33442
+ return Promise.resolve({ total, needsRemediation, dismissed, bySeverity });
33339
33443
  }
33340
33444
  // Range is echoed but does not change the result today — coverage is a constant
33341
33445
  // business fact (see SCAN_COVERAGE), not a measured per-window metric. Order
@@ -33652,10 +33756,10 @@ var SqliteSecurityRepository = class {
33652
33756
  * machine, and the second reported "no recommendations" over live exposure.
33653
33757
  *
33654
33758
  * `open` mirrors `deriveFindingStatus` — at-rest, minus resolved and dismissed —
33655
- * so a row's count is exactly what `?status=open&type=<rule>` returns. Note that
33656
- * is NOT `severitySummary`'s `openAtRest`, which keeps dismissed findings (a
33657
- * dismissal is a judgement, not a remediation) and drops untracked legacy rows.
33658
- * The two answer different questions and only this one has to match a link.
33759
+ * so a row's count is exactly what `?status=open&type=<rule>` returns. It
33760
+ * differs from `severitySummary`'s `openAtRest` only in including untracked
33761
+ * legacy rows, which that bucket leaves out; dismissed is excluded from both.
33762
+ * Only this one has to match a link.
33659
33763
  *
33660
33764
  * Aggregated in SQL: the result is O(distinct rule × category × severity), so a
33661
33765
  * whole-store scope costs a grouped scan rather than a row per finding.
@@ -33683,6 +33787,8 @@ var SqliteSecurityRepository = class {
33683
33787
  /**
33684
33788
  * The distinct `finding_key`s behind ONE rule's {@link recommendationInputs}
33685
33789
  * tally — what a dashboard dismissal of that row writes a disposition for.
33790
+ * The dismissal itself does not call this: it reads the same set through
33791
+ * {@link selectOpenFindingKeysForRule}, inside its own write transaction.
33686
33792
  *
33687
33793
  * It shares {@link OPEN_AT_REST_FINDINGS_SQL} with the count rather than
33688
33794
  * restating the predicate, because a dismissal has to act on exactly the set
@@ -33699,16 +33805,7 @@ var SqliteSecurityRepository = class {
33699
33805
  * this set SMALLER than the tally, never larger.
33700
33806
  */
33701
33807
  openFindingKeysForRule(ruleId) {
33702
- const rows = allRows(
33703
- this.db.prepare(
33704
- `SELECT DISTINCT f.finding_key AS finding_key
33705
- ${OPEN_AT_REST_FINDINGS_SQL}
33706
- AND d.rule_id = :ruleId
33707
- AND f.finding_key IS NOT NULL`
33708
- ),
33709
- { ruleId }
33710
- );
33711
- return Promise.resolve(rows.map((r) => r.finding_key));
33808
+ return Promise.resolve(selectOpenFindingKeysForRule(this.db, ruleId));
33712
33809
  }
33713
33810
  // Findings whose parent event occurred in [fromMs, toMs), with the parent's
33714
33811
  // epoch-millis timestamp. started_at is an INTEGER column, so the bounds stay
@@ -34754,6 +34851,31 @@ function openLocalDatabase(dir, options = {}) {
34754
34851
  );
34755
34852
  });
34756
34853
  }
34854
+ function dismissOpenFindingsForRule(ruleId, disposition) {
34855
+ let dismissed = 0;
34856
+ withTransaction(
34857
+ db,
34858
+ () => {
34859
+ const keys = selectOpenFindingKeysForRule(db, ruleId);
34860
+ resolutions.insertResolutions(
34861
+ keys.map((findingKey) => ({
34862
+ findingKey,
34863
+ status: "dismissed",
34864
+ method: disposition.method,
34865
+ resolvedAt: disposition.resolvedAt,
34866
+ evidence: disposition.evidence
34867
+ }))
34868
+ );
34869
+ dismissed = keys.length;
34870
+ },
34871
+ // IMMEDIATE takes the write lock at BEGIN, before the select, which is
34872
+ // what keeps a concurrent resolve out of the gap. It also makes waiting
34873
+ // on a busy writer an ordinary busy_timeout wait rather than a
34874
+ // read-to-write upgrade SQLite refuses to retry.
34875
+ "IMMEDIATE"
34876
+ );
34877
+ return dismissed;
34878
+ }
34757
34879
  function recordCapture(event, detected) {
34758
34880
  failOpenTransaction(db, () => {
34759
34881
  const sessionId = event.metadata?.sessionId;
@@ -34937,6 +35059,7 @@ function openLocalDatabase(dir, options = {}) {
34937
35059
  inspectionDefinitions,
34938
35060
  inspectionFindings,
34939
35061
  recordCapture,
35062
+ dismissOpenFindingsForRule,
34940
35063
  markCaptureDelivered,
34941
35064
  markCaptureOwed,
34942
35065
  markAuditEventsDelivered,
@@ -35153,6 +35276,9 @@ function loadOrCreateFingerprintKey(dataDir2) {
35153
35276
  });
35154
35277
  }
35155
35278
  function fingerprintValue(key, raw) {
35279
+ return exactFingerprintValue(key, stripInvisiblePadding(raw));
35280
+ }
35281
+ function exactFingerprintValue(key, raw) {
35156
35282
  return createHmac("sha256", key.material).update(raw, "utf8").digest("hex");
35157
35283
  }
35158
35284
 
@@ -35323,7 +35449,7 @@ async function send(options) {
35323
35449
  }
35324
35450
  }
35325
35451
  };
35326
- return new Promise((resolve2, reject) => {
35452
+ return new Promise((resolve3, reject) => {
35327
35453
  let settled = false;
35328
35454
  const fail = (reason, status) => {
35329
35455
  if (settled) return;
@@ -35349,7 +35475,7 @@ async function send(options) {
35349
35475
  res.on("end", () => {
35350
35476
  if (settled) return;
35351
35477
  settled = true;
35352
- resolve2({
35478
+ resolve3({
35353
35479
  status: res.statusCode ?? 0,
35354
35480
  headers: res.headers,
35355
35481
  body: Buffer.concat(chunks).toString("utf8")
@@ -36328,6 +36454,82 @@ function escapeRegExp2(value) {
36328
36454
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
36329
36455
  }
36330
36456
 
36457
+ // ../../packages/detections/src/format-chars.ts
36458
+ var HAS_FORMAT_CHAR = new RegExp("\\p{Cf}", "u");
36459
+ var FORMAT_CHAR_GLOBAL = new RegExp("\\p{Cf}", "gu");
36460
+ function normalizeFormatChars(text) {
36461
+ if (!HAS_FORMAT_CHAR.test(text)) return void 0;
36462
+ const normalizedParts = [];
36463
+ const segments = [];
36464
+ let cursor = 0;
36465
+ let normLength = 0;
36466
+ for (const match of text.matchAll(FORMAT_CHAR_GLOBAL)) {
36467
+ const matchStart = match.index;
36468
+ if (matchStart > cursor) {
36469
+ const length = matchStart - cursor;
36470
+ normalizedParts.push(text.slice(cursor, matchStart));
36471
+ segments.push({ normStart: normLength, origStart: cursor, length });
36472
+ normLength += length;
36473
+ }
36474
+ cursor = matchStart + match[0].length;
36475
+ }
36476
+ if (cursor < text.length) {
36477
+ const length = text.length - cursor;
36478
+ normalizedParts.push(text.slice(cursor));
36479
+ segments.push({ normStart: normLength, origStart: cursor, length });
36480
+ }
36481
+ return { normalized: normalizedParts.join(""), segments };
36482
+ }
36483
+ function segmentAt(segments, normPos) {
36484
+ let lo = 0;
36485
+ let hi = segments.length - 1;
36486
+ while (lo < hi) {
36487
+ const mid = lo + hi >> 1;
36488
+ const segment = segments[mid];
36489
+ if (segment !== void 0 && normPos >= segment.normStart + segment.length) {
36490
+ lo = mid + 1;
36491
+ } else {
36492
+ hi = mid;
36493
+ }
36494
+ }
36495
+ const found = segments[lo];
36496
+ if (found === void 0) {
36497
+ throw new Error(`normPos ${String(normPos)} has no covering segment`);
36498
+ }
36499
+ return found;
36500
+ }
36501
+ function mapSpanToOriginal(span, normalization) {
36502
+ const { segments } = normalization;
36503
+ const startSegment = segmentAt(segments, span.start);
36504
+ const start = startSegment.origStart + (span.start - startSegment.normStart);
36505
+ const endSegment = segmentAt(segments, span.end - 1);
36506
+ const end = endSegment.origStart + (span.end - 1 - endSegment.normStart) + 1;
36507
+ return { start, end };
36508
+ }
36509
+ function normalizedOffset(origPos, segments) {
36510
+ let lo = 0;
36511
+ let hi = segments.length;
36512
+ while (lo < hi) {
36513
+ const mid = lo + hi >> 1;
36514
+ const segment = segments[mid];
36515
+ if (segment !== void 0 && segment.origStart + segment.length <= origPos) {
36516
+ lo = mid + 1;
36517
+ } else {
36518
+ hi = mid;
36519
+ }
36520
+ }
36521
+ const found = segments[Math.min(lo, segments.length - 1)];
36522
+ if (found === void 0) return 0;
36523
+ return found.normStart + Math.min(Math.max(0, origPos - found.origStart), found.length);
36524
+ }
36525
+ function mapSpanToNormalized(span, normalization) {
36526
+ const { segments } = normalization;
36527
+ return {
36528
+ start: normalizedOffset(span.start, segments),
36529
+ end: normalizedOffset(span.end, segments)
36530
+ };
36531
+ }
36532
+
36331
36533
  // ../../packages/detections/src/regex-cache.ts
36332
36534
  var singles = /* @__PURE__ */ new WeakMap();
36333
36535
  var keywordLists = /* @__PURE__ */ new WeakMap();
@@ -36489,29 +36691,35 @@ function registerPack(pack) {
36489
36691
  function getLoadedRules() {
36490
36692
  return [...packs.values()].flatMap((p) => p.rules);
36491
36693
  }
36492
- function isCorroborated(candidate, candidates, text) {
36694
+ function spansOverlap(a, b) {
36695
+ return a.start < b.end && a.end > b.start;
36696
+ }
36697
+ function isCorroborated(candidate, candidates, text, normalization) {
36493
36698
  const req = candidate.rule.requiresNearby;
36494
36699
  if (!req) return true;
36495
36700
  const halfWindow = req.windowChars;
36496
- const { start, end } = candidate.match.span;
36497
- const winStart = start - halfWindow;
36498
- const winEnd = end + halfWindow;
36701
+ const ns = candidate.normSpan;
36702
+ const winStart = ns.start - halfWindow;
36703
+ const winEnd = ns.end + halfWindow;
36499
36704
  const categories = req.categories;
36500
36705
  const ruleIds = req.ruleIds;
36501
36706
  if (categories?.length || ruleIds?.length) {
36502
36707
  for (const other of candidates) {
36503
36708
  if (other === candidate) continue;
36504
- const os = other.match.span;
36505
- if (os.end < winStart || os.start > winEnd) continue;
36506
- if (other.match.ruleId !== candidate.match.ruleId && categories?.includes(other.match.category)) {
36507
- return true;
36709
+ if (other.normSpan.end < winStart || other.normSpan.start > winEnd) continue;
36710
+ const relevant = other.match.ruleId !== candidate.match.ruleId && categories?.includes(other.match.category) === true || ruleIds?.includes(other.match.ruleId) === true;
36711
+ if (!relevant) continue;
36712
+ if (other.match.ruleId === candidate.match.ruleId && spansOverlap(other.match.span, candidate.match.span)) {
36713
+ continue;
36508
36714
  }
36509
- if (ruleIds?.includes(other.match.ruleId)) return true;
36715
+ return true;
36510
36716
  }
36511
36717
  }
36512
36718
  const labels = req.labels;
36513
36719
  if (labels && labels.length > 0) {
36514
- const haystack = text.slice(Math.max(0, winStart), winEnd);
36720
+ const { start, end } = candidate.match.span;
36721
+ const haystack = text.slice(Math.max(0, start - halfWindow), end + halfWindow);
36722
+ const normalizedHaystack = normalization === void 0 ? void 0 : normalization.normalized.slice(Math.max(0, winStart), winEnd);
36515
36723
  for (const re of memoizedRegExpList(
36516
36724
  "label",
36517
36725
  req,
@@ -36520,29 +36728,20 @@ function isCorroborated(candidate, candidates, text) {
36520
36728
  return trimmed2.length === 0 ? void 0 : new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed2)}(?![A-Za-z0-9])`, "i");
36521
36729
  })
36522
36730
  )) {
36523
- if (re?.test(haystack)) return true;
36731
+ if (!re) continue;
36732
+ if (re.test(haystack)) return true;
36733
+ if (normalizedHaystack !== void 0 && re.test(normalizedHaystack)) return true;
36524
36734
  }
36525
36735
  }
36526
36736
  return false;
36527
36737
  }
36528
- function extensionOf(filePath) {
36529
- const base = filePath.slice(Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\")) + 1);
36530
- const dot = base.lastIndexOf(".");
36531
- return dot > 0 ? base.slice(dot).toLowerCase() : void 0;
36532
- }
36533
- function ruleApplies(rule, extension) {
36534
- if (!rule.appliesTo || extension === void 0) return true;
36535
- return rule.appliesTo.extensions.some((e) => e.toLowerCase() === extension);
36536
- }
36537
- function scan(text, rules, context) {
36538
- const ruleset = rules ?? getLoadedRules();
36539
- const extension = context?.filePath ? extensionOf(context.filePath) : void 0;
36738
+ function buildCandidates(matchText, ruleset, extension) {
36540
36739
  const candidates = [];
36541
36740
  for (const rule of ruleset) {
36542
36741
  if (!ruleApplies(rule, extension)) continue;
36543
- const spans = MATCHERS[rule.matcher.type](text, rule);
36742
+ const spans = MATCHERS[rule.matcher.type](matchText, rule);
36544
36743
  for (const span of spans) {
36545
- const rawMatch = text.slice(span.start, span.end);
36744
+ const rawMatch = matchText.slice(span.start, span.end);
36546
36745
  if (!passesPostValidators(rule, rawMatch)) continue;
36547
36746
  candidates.push({
36548
36747
  rule,
@@ -36553,10 +36752,31 @@ function scan(text, rules, context) {
36553
36752
  span,
36554
36753
  rawMatch,
36555
36754
  confidence: 0.9
36556
- }
36755
+ },
36756
+ // In `matchText`'s own coordinates, which is the normalized text for
36757
+ // a normalized-pass candidate and so already right; an original-pass
36758
+ // candidate on the slow path is re-derived by withNormalizedSpan.
36759
+ normSpan: span
36557
36760
  });
36558
36761
  }
36559
36762
  }
36763
+ return candidates;
36764
+ }
36765
+ function mapCandidateToOriginal(candidate, normalization, text) {
36766
+ const span = mapSpanToOriginal(candidate.match.span, normalization);
36767
+ return {
36768
+ rule: candidate.rule,
36769
+ match: { ...candidate.match, span, rawMatch: text.slice(span.start, span.end) },
36770
+ // Deliberately NOT remapped: `normSpan` is the span the primitive match
36771
+ // was found at in the normalized text, which is exactly the coordinate
36772
+ // space windows are measured in. See the `Candidate` comment.
36773
+ normSpan: candidate.normSpan
36774
+ };
36775
+ }
36776
+ function withNormalizedSpan(candidate, normalization) {
36777
+ return { ...candidate, normSpan: mapSpanToNormalized(candidate.match.span, normalization) };
36778
+ }
36779
+ function gate(candidates, text, normalization) {
36560
36780
  const findings = [];
36561
36781
  for (const candidate of candidates) {
36562
36782
  const req = candidate.rule.requiresNearby;
@@ -36564,7 +36784,7 @@ function scan(text, rules, context) {
36564
36784
  findings.push(candidate.match);
36565
36785
  continue;
36566
36786
  }
36567
- if (!isCorroborated(candidate, candidates, text)) continue;
36787
+ if (!isCorroborated(candidate, candidates, text, normalization)) continue;
36568
36788
  const boost = req.confidenceBoost;
36569
36789
  findings.push(
36570
36790
  boost ? { ...candidate.match, confidence: Math.min(0.99, candidate.match.confidence + boost) } : candidate.match
@@ -36572,6 +36792,81 @@ function scan(text, rules, context) {
36572
36792
  }
36573
36793
  return findings;
36574
36794
  }
36795
+ function closeRegion(open3, text) {
36796
+ const span = { start: open3.start, end: open3.end };
36797
+ return {
36798
+ ruleId: open3.ruleId,
36799
+ category: open3.category,
36800
+ severity: open3.severity,
36801
+ span,
36802
+ rawMatch: text.slice(span.start, span.end),
36803
+ confidence: open3.confidence
36804
+ };
36805
+ }
36806
+ function mergeOverlappingSameRule(findings, text) {
36807
+ if (findings.length === 0) return findings;
36808
+ const groups = /* @__PURE__ */ new Map();
36809
+ const ruleOrder = [];
36810
+ for (const finding2 of findings) {
36811
+ const group = groups.get(finding2.ruleId);
36812
+ if (group) {
36813
+ group.push(finding2);
36814
+ } else {
36815
+ groups.set(finding2.ruleId, [finding2]);
36816
+ ruleOrder.push(finding2.ruleId);
36817
+ }
36818
+ }
36819
+ const merged = [];
36820
+ for (const ruleId of ruleOrder) {
36821
+ const group = groups.get(ruleId) ?? [];
36822
+ const sorted = [...group].sort(
36823
+ (a, b) => a.span.start - b.span.start || a.span.end - b.span.end
36824
+ );
36825
+ let open3;
36826
+ for (const finding2 of sorted) {
36827
+ if (open3 && finding2.span.start < open3.end) {
36828
+ open3.end = Math.max(open3.end, finding2.span.end);
36829
+ open3.confidence = Math.max(open3.confidence, finding2.confidence);
36830
+ continue;
36831
+ }
36832
+ if (open3) merged.push(closeRegion(open3, text));
36833
+ open3 = {
36834
+ start: finding2.span.start,
36835
+ end: finding2.span.end,
36836
+ confidence: finding2.confidence,
36837
+ ruleId: finding2.ruleId,
36838
+ category: finding2.category,
36839
+ severity: finding2.severity
36840
+ };
36841
+ }
36842
+ if (open3) merged.push(closeRegion(open3, text));
36843
+ }
36844
+ return merged;
36845
+ }
36846
+ function extensionOf(filePath) {
36847
+ const base = filePath.slice(Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\")) + 1);
36848
+ const dot = base.lastIndexOf(".");
36849
+ return dot > 0 ? base.slice(dot).toLowerCase() : void 0;
36850
+ }
36851
+ function ruleApplies(rule, extension) {
36852
+ if (!rule.appliesTo || extension === void 0) return true;
36853
+ return rule.appliesTo.extensions.some((e) => e.toLowerCase() === extension);
36854
+ }
36855
+ function scan(text, rules, context) {
36856
+ const ruleset = rules ?? getLoadedRules();
36857
+ const extension = context?.filePath ? extensionOf(context.filePath) : void 0;
36858
+ const normalization = normalizeFormatChars(text);
36859
+ const originalCandidates = buildCandidates(text, ruleset, extension);
36860
+ if (!normalization) return gate(originalCandidates, text, void 0);
36861
+ const pooledOriginal = originalCandidates.map(
36862
+ (candidate) => withNormalizedSpan(candidate, normalization)
36863
+ );
36864
+ const normalizedCandidates = buildCandidates(normalization.normalized, ruleset, extension).map(
36865
+ (candidate) => mapCandidateToOriginal(candidate, normalization, text)
36866
+ );
36867
+ const findings = gate([...pooledOriginal, ...normalizedCandidates], text, normalization);
36868
+ return mergeOverlappingSameRule(findings, text);
36869
+ }
36575
36870
  var SEVERITY_RANK2 = {
36576
36871
  critical: 3,
36577
36872
  high: 2,
@@ -39414,8 +39709,8 @@ function collectConfigFiles(scan2, claudeDir, cwd) {
39414
39709
  }
39415
39710
  function configFileEntry(path, scope, kind) {
39416
39711
  try {
39417
- const stat = statSync7(path);
39418
- return { name: basename4(path), path, scope, kind, updatedAt: stat.mtime.toISOString() };
39712
+ const stat2 = statSync7(path);
39713
+ return { name: basename4(path), path, scope, kind, updatedAt: stat2.mtime.toISOString() };
39419
39714
  } catch {
39420
39715
  return void 0;
39421
39716
  }
@@ -39918,8 +40213,8 @@ function createIsolatedScanner(data, opts = {}) {
39918
40213
  }
39919
40214
  function enqueue(spec) {
39920
40215
  const next = chain.then(
39921
- () => new Promise((resolve2) => {
39922
- spec(resolve2);
40216
+ () => new Promise((resolve3) => {
40217
+ spec(resolve3);
39923
40218
  })
39924
40219
  );
39925
40220
  chain = next.then(
@@ -39930,7 +40225,7 @@ function createIsolatedScanner(data, opts = {}) {
39930
40225
  }
39931
40226
  return {
39932
40227
  scan(text, context, scanOpts) {
39933
- return enqueue((resolve2) => {
40228
+ return enqueue((resolve3) => {
39934
40229
  runOne(
39935
40230
  {
39936
40231
  budgetMs,
@@ -39943,23 +40238,23 @@ function createIsolatedScanner(data, opts = {}) {
39943
40238
  }),
39944
40239
  reply: (message2) => {
39945
40240
  if (message2.kind !== "result") return false;
39946
- resolve2({ status: "ok", findings: message2.findings });
40241
+ resolve3({ status: "ok", findings: message2.findings });
39947
40242
  return true;
39948
40243
  }
39949
40244
  },
39950
- resolve2
40245
+ resolve3
39951
40246
  );
39952
40247
  });
39953
40248
  },
39954
40249
  probe(rule) {
39955
- return enqueue((resolve2) => {
40250
+ return enqueue((resolve3) => {
39956
40251
  runOne(
39957
40252
  {
39958
40253
  budgetMs: probeBudgetMs,
39959
40254
  build: (id) => ({ kind: "probe", id, rule }),
39960
40255
  reply: (message2) => {
39961
40256
  if (message2.kind !== "probed") return false;
39962
- resolve2({
40257
+ resolve3({
39963
40258
  status: "ok",
39964
40259
  verdict: message2.verdict,
39965
40260
  worstMs: message2.worstMs,
@@ -39968,7 +40263,7 @@ function createIsolatedScanner(data, opts = {}) {
39968
40263
  return true;
39969
40264
  }
39970
40265
  },
39971
- resolve2
40266
+ resolve3
39972
40267
  );
39973
40268
  });
39974
40269
  },
@@ -41653,10 +41948,55 @@ function spawnDetached(scriptPath) {
41653
41948
  child.unref();
41654
41949
  }
41655
41950
 
41951
+ // ../../packages/plugin-runtime/src/attached/install-record.ts
41952
+ import { readFile as readFile2, stat } from "fs/promises";
41953
+ import { basename as basename7, dirname as dirname6, join as join28, resolve as resolve2 } from "path";
41954
+ async function readInstalledVersion(installRoot) {
41955
+ try {
41956
+ const versionDir = resolve2(installRoot);
41957
+ const pluginDir = dirname6(versionDir);
41958
+ const marketplaceDir = dirname6(pluginDir);
41959
+ const cacheDir = dirname6(marketplaceDir);
41960
+ if (basename7(cacheDir) !== "cache") return null;
41961
+ const key = `${basename7(pluginDir)}@${basename7(marketplaceDir)}`;
41962
+ const record2 = JSON.parse(
41963
+ await readFile2(join28(dirname6(cacheDir), "installed_plugins.json"), "utf8")
41964
+ );
41965
+ const plugins = record2?.plugins;
41966
+ if (typeof plugins !== "object" || plugins === null || !Object.hasOwn(plugins, key)) {
41967
+ return null;
41968
+ }
41969
+ const entries = plugins[key];
41970
+ if (!Array.isArray(entries)) return null;
41971
+ let newest = null;
41972
+ for (const entry of entries) {
41973
+ const { version: version3, installPath } = entry ?? {};
41974
+ if (typeof version3 !== "string" || !isParseableBinaryVersion(version3)) continue;
41975
+ if (!StorePosturePlugin.shape.installedVersion.safeParse(version3).success) continue;
41976
+ if (newest !== null && compareBinaryVersions(version3, newest) <= 0) continue;
41977
+ if (typeof installPath === "string" && !await exists(installPath)) continue;
41978
+ newest = version3;
41979
+ }
41980
+ return newest;
41981
+ } catch {
41982
+ return null;
41983
+ }
41984
+ }
41985
+ async function exists(path) {
41986
+ try {
41987
+ await stat(path);
41988
+ return true;
41989
+ } catch {
41990
+ return false;
41991
+ }
41992
+ }
41993
+
41656
41994
  // ../../packages/plugin-runtime/src/attached/plugin-block.ts
41657
41995
  import { readFileSync as readFileSync18 } from "fs";
41996
+ var INSTALL_RECORD_READ_TIMEOUT_MS = REQUEST_TIMEOUT_MS / 2;
41658
41997
  function createPluginBlock(build, policyStore) {
41659
41998
  return async () => {
41999
+ const installed = build.installRoot === void 0 ? void 0 : readInstalledVersionBounded(build.installRoot);
41660
42000
  const cached2 = await policyStore.read();
41661
42001
  const fetchedAtMs = cached2?.fetchedAtMs;
41662
42002
  const block = {
@@ -41664,16 +42004,25 @@ function createPluginBlock(build, policyStore) {
41664
42004
  version: build.version,
41665
42005
  ossVersion: build.ossVersion ?? null,
41666
42006
  policyBundleVersion: cached2 !== null && StorePosturePlugin.shape.policyBundleVersion.safeParse(cached2.bundle.version).success ? cached2.bundle.version : null,
41667
- policyFetchedAt: fetchedAtMs !== void 0 && fetchedAtMs > 0 && StorePosturePlugin.shape.policyFetchedAt.safeParse(fetchedAtMs).success ? fetchedAtMs : null
42007
+ policyFetchedAt: fetchedAtMs !== void 0 && fetchedAtMs > 0 && StorePosturePlugin.shape.policyFetchedAt.safeParse(fetchedAtMs).success ? fetchedAtMs : null,
42008
+ ...installed === void 0 ? {} : { installedVersion: await installed },
42009
+ buildSchemaVersion: SQLITE_MIGRATIONS.length
41668
42010
  };
41669
42011
  return StorePosturePlugin.safeParse(block).success ? block : void 0;
41670
42012
  };
41671
42013
  }
42014
+ async function readInstalledVersionBounded(installRoot) {
42015
+ try {
42016
+ return await withTimeout(readInstalledVersion(installRoot), INSTALL_RECORD_READ_TIMEOUT_MS);
42017
+ } catch {
42018
+ return null;
42019
+ }
42020
+ }
41672
42021
 
41673
42022
  // ../../packages/plugin-runtime/src/attached/policy-store.ts
41674
42023
  import { randomUUID as randomUUID16 } from "crypto";
41675
- import { readFile as readFile2, rm, writeFile as writeFile2 } from "fs/promises";
41676
- import { join as join28 } from "path";
42024
+ import { readFile as readFile3, rm, writeFile as writeFile2 } from "fs/promises";
42025
+ import { join as join29 } from "path";
41677
42026
 
41678
42027
  // ../../packages/plugin-runtime/src/attached/atomic-publish.ts
41679
42028
  import { rename as rename2 } from "fs/promises";
@@ -41681,11 +42030,11 @@ var RETRYABLE = /* @__PURE__ */ new Set(["EPERM", "EACCES", "EBUSY"]);
41681
42030
  var IMMEDIATE_RETRIES = 8;
41682
42031
  var TIMED_RETRIES = 4;
41683
42032
  var ATTEMPTS = 1 + IMMEDIATE_RETRIES + TIMED_RETRIES;
41684
- var delay = (ms) => new Promise((resolve2) => {
41685
- setTimeout(resolve2, ms);
42033
+ var delay = (ms) => new Promise((resolve3) => {
42034
+ setTimeout(resolve3, ms);
41686
42035
  });
41687
- var yieldToLoop = () => new Promise((resolve2) => {
41688
- setImmediate(resolve2);
42036
+ var yieldToLoop = () => new Promise((resolve3) => {
42037
+ setImmediate(resolve3);
41689
42038
  });
41690
42039
  async function publishByRename(tmp, file2, move = rename2) {
41691
42040
  for (let attempt = 1; ; attempt += 1) {
@@ -41702,10 +42051,10 @@ async function publishByRename(tmp, file2, move = rename2) {
41702
42051
 
41703
42052
  // ../../packages/plugin-runtime/src/attached/policy-store.ts
41704
42053
  function createPolicyStore(dir = dataDir()) {
41705
- const file2 = join28(dir, "policy-cache.json");
42054
+ const file2 = join29(dir, "policy-cache.json");
41706
42055
  async function read() {
41707
42056
  try {
41708
- const raw = await readFile2(file2, "utf8");
42057
+ const raw = await readFile3(file2, "utf8");
41709
42058
  const parsed2 = JSON.parse(raw);
41710
42059
  if (typeof parsed2 !== "object" || parsed2 === null) return null;
41711
42060
  const record2 = parsed2;
@@ -41727,7 +42076,7 @@ function createPolicyStore(dir = dataDir()) {
41727
42076
  }
41728
42077
  async function priorRecord() {
41729
42078
  try {
41730
- const parsed2 = JSON.parse(await readFile2(file2, "utf8"));
42079
+ const parsed2 = JSON.parse(await readFile3(file2, "utf8"));
41731
42080
  return typeof parsed2 === "object" && parsed2 !== null ? parsed2 : null;
41732
42081
  } catch {
41733
42082
  return null;
@@ -41773,7 +42122,7 @@ function createPolicyStore(dir = dataDir()) {
41773
42122
 
41774
42123
  // ../../packages/plugin-runtime/src/attached/posture-report-state.ts
41775
42124
  import { readFileSync as readFileSync19 } from "fs";
41776
- import { join as join29 } from "path";
42125
+ import { join as join30 } from "path";
41777
42126
  var POSTURE_REPORT_STATE_FILENAME = ATTACHED_POSTURE_REPORT_FILENAME;
41778
42127
  var OUTCOME_KEYS = {
41779
42128
  ok: true,
@@ -41787,7 +42136,7 @@ var OUTCOME_KEYS = {
41787
42136
  };
41788
42137
  var OUTCOMES = new Set(Object.keys(OUTCOME_KEYS));
41789
42138
  function postureReportStatePath(dataDir2) {
41790
- return join29(dataDir2, POSTURE_REPORT_STATE_FILENAME);
42139
+ return join30(dataDir2, POSTURE_REPORT_STATE_FILENAME);
41791
42140
  }
41792
42141
  function writePostureReportState(dataDir2, state) {
41793
42142
  try {
@@ -41966,12 +42315,12 @@ function readStorePosture(dbPath2) {
41966
42315
 
41967
42316
  // ../../packages/plugin-runtime/src/attached/posture-store.ts
41968
42317
  import { randomUUID as randomUUID17 } from "crypto";
41969
- import { readFile as readFile3, rm as rm2, writeFile as writeFile3 } from "fs/promises";
41970
- import { join as join30 } from "path";
42318
+ import { readFile as readFile4, rm as rm2, writeFile as writeFile3 } from "fs/promises";
42319
+ import { join as join31 } from "path";
41971
42320
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
41972
42321
  function createPostureStore(dir = settingsDir(), legacyDir) {
41973
- const file2 = join30(dir, "posture-state.json");
41974
- const legacyFile = legacyDir === void 0 ? null : join30(legacyDir, "posture-state.json");
42322
+ const file2 = join31(dir, "posture-state.json");
42323
+ const legacyFile = legacyDir === void 0 ? null : join31(legacyDir, "posture-state.json");
41975
42324
  async function persist(state) {
41976
42325
  await ensureDataDir(dir);
41977
42326
  const tmp = `${file2}.${randomUUID17()}.tmp`;
@@ -41986,7 +42335,7 @@ function createPostureStore(dir = settingsDir(), legacyDir) {
41986
42335
  async function readFrom(path) {
41987
42336
  let raw;
41988
42337
  try {
41989
- raw = await readFile3(path, "utf8");
42338
+ raw = await readFile4(path, "utf8");
41990
42339
  } catch (err) {
41991
42340
  const code = err.code;
41992
42341
  if (code === "ENOENT" || code === "ENOTDIR") return null;
@@ -42040,7 +42389,7 @@ function createPostureStore(dir = settingsDir(), legacyDir) {
42040
42389
 
42041
42390
  // ../../packages/plugin-runtime/src/attached/sync-state.ts
42042
42391
  import { readFileSync as readFileSync20 } from "fs";
42043
- import { join as join31 } from "path";
42392
+ import { join as join32 } from "path";
42044
42393
 
42045
42394
  // ../../packages/plugin-runtime/src/attached/status.ts
42046
42395
  var REFUSAL_LINES = {
@@ -42161,12 +42510,12 @@ var StandaloneDataGateway = class {
42161
42510
  // reconciler drops the whole pass and recovers it idempotently on the next read.
42162
42511
  recordLlmCalls(inputs) {
42163
42512
  if (inputs.length === 0) return Promise.resolve();
42164
- return new Promise((resolve2, reject) => {
42513
+ return new Promise((resolve3, reject) => {
42165
42514
  try {
42166
42515
  this.db.auditEvents.runInTransaction(() => {
42167
42516
  for (const input2 of inputs) this.db.auditEvents.insertLlmCall(input2);
42168
42517
  });
42169
- resolve2();
42518
+ resolve3();
42170
42519
  } catch (err) {
42171
42520
  reject(err instanceof Error ? err : new Error(String(err)));
42172
42521
  }
@@ -42178,12 +42527,12 @@ var StandaloneDataGateway = class {
42178
42527
  // drops the whole pass and recovers it idempotently next time.
42179
42528
  recordToolCalls(inputs) {
42180
42529
  if (inputs.length === 0) return Promise.resolve();
42181
- return new Promise((resolve2, reject) => {
42530
+ return new Promise((resolve3, reject) => {
42182
42531
  try {
42183
42532
  this.db.auditEvents.runInTransaction(() => {
42184
42533
  for (const input2 of inputs) this.writeToolCall(input2);
42185
42534
  });
42186
- resolve2();
42535
+ resolve3();
42187
42536
  } catch (err) {
42188
42537
  reject(err instanceof Error ? err : new Error(String(err)));
42189
42538
  }
@@ -42734,7 +43083,7 @@ function buildSessionRoot(sessionId, input2, ctx, resolved, provider, branch) {
42734
43083
 
42735
43084
  // package.json
42736
43085
  var name = "@akasecurity/plugin-browser-extension";
42737
- var version2 = "0.9.14";
43086
+ var version2 = "0.9.15";
42738
43087
 
42739
43088
  // src/native-host/exchange.ts
42740
43089
  var MAX_TARGET_LEN = 500;
@@ -42908,10 +43257,10 @@ function writeMessage(stdout, message2) {
42908
43257
  const body = Buffer.from(JSON.stringify(message2), "utf8");
42909
43258
  const header = Buffer.alloc(4);
42910
43259
  header.writeUInt32LE(body.length, 0);
42911
- return new Promise((resolve2, reject) => {
43260
+ return new Promise((resolve3, reject) => {
42912
43261
  stdout.write(Buffer.concat([header, body]), (err) => {
42913
43262
  if (err) reject(err);
42914
- else resolve2();
43263
+ else resolve3();
42915
43264
  });
42916
43265
  });
42917
43266
  }