@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
package/dist/cli.js CHANGED
@@ -33,9 +33,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
33
  mod
34
34
  ));
35
35
 
36
- // ../node_modules/.pnpm/ignore@7.0.9/node_modules/ignore/index.js
36
+ // ../node_modules/.pnpm/ignore@7.0.10/node_modules/ignore/index.js
37
37
  var require_ignore = __commonJS({
38
- "../node_modules/.pnpm/ignore@7.0.9/node_modules/ignore/index.js"(exports, module) {
38
+ "../node_modules/.pnpm/ignore@7.0.10/node_modules/ignore/index.js"(exports, module) {
39
39
  "use strict";
40
40
  function makeArray(subject) {
41
41
  return Array.isArray(subject) ? subject : [subject];
@@ -430,6 +430,13 @@ var require_ignore = __commonJS({
430
430
  }
431
431
  };
432
432
  var WILDCARD = "[^\\/]*";
433
+ var separatorAfter = (run2, at) => {
434
+ let separator = EMPTY;
435
+ for (let index = at + 1; index < run2.length && !run2[index].wildcard; index++) {
436
+ separator += run2[index].single;
437
+ }
438
+ return separator;
439
+ };
433
440
  var pinWildcards = (source) => {
434
441
  if (source.indexOf(WILDCARD) < 0) {
435
442
  return source;
@@ -499,7 +506,7 @@ var require_ignore = __commonJS({
499
506
  out += token.single;
500
507
  return;
501
508
  }
502
- out += at === lastWildcard ? WILDCARD : `(?:(?!${run2[at + 1].single})[^\\/])*`;
509
+ out += at === lastWildcard ? WILDCARD : `(?:(?!${separatorAfter(run2, at)})[^\\/])*`;
503
510
  });
504
511
  run2 = [];
505
512
  };
@@ -676,13 +683,13 @@ var require_ignore = __commonJS({
676
683
  const rules = this._rules;
677
684
  const { length } = rules;
678
685
  const shortcut = this._basenameCount * 2 >= length;
679
- const basename9 = shortcut ? basenameOf(path) : path;
686
+ const basename10 = shortcut ? basenameOf(path) : path;
680
687
  for (let index = 0; index < length; index++) {
681
688
  const rule = rules[index];
682
689
  const { negative } = rule;
683
690
  const skip = unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored;
684
691
  if (!skip && rule[mode].test(
685
- shortcut && rule._basenameOnly ? basename9 : path
692
+ shortcut && rule._basenameOnly ? basename10 : path
686
693
  )) {
687
694
  ignored = !negative;
688
695
  unignored = negative;
@@ -990,6 +997,10 @@ var SQLITE_MIGRATIONS = [
990
997
  {
991
998
  tag: "0035_share_destination_provider_id",
992
999
  sql: "ALTER TABLE `share_destination` ADD `provider_id` text;"
1000
+ },
1001
+ {
1002
+ tag: "0036_secret_vault_identity_fingerprint",
1003
+ 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"
993
1004
  }
994
1005
  ];
995
1006
 
@@ -1056,6 +1067,12 @@ function scopeFromAnswer(answer, now = Date.now()) {
1056
1067
  var PRODUCT_NAME = "AKA Security";
1057
1068
  var PRODUCT_TAGLINE = "We secure agent harnesses at the source.";
1058
1069
 
1070
+ // ../packages/schema/src/invisible-padding.ts
1071
+ var INVISIBLE_PADDING = /[\u00AD\u200B\u2060-\u2064\u202A-\u202E\u2066-\u2069\uFEFF\u{E0001}\u{E0020}-\u{E007F}]/gu;
1072
+ function stripInvisiblePadding(text) {
1073
+ return text.replace(INVISIBLE_PADDING, "");
1074
+ }
1075
+
1059
1076
  // ../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/external.js
1060
1077
  var external_exports = {};
1061
1078
  __export(external_exports, {
@@ -6082,7 +6099,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
6082
6099
  var NONE = 0;
6083
6100
  var ASSUMED = 1;
6084
6101
  var PROVEN = 2;
6085
- function isRecursive(inst, stack, resolve8) {
6102
+ function isRecursive(inst, stack, resolve9) {
6086
6103
  const cached2 = recursive.get(inst);
6087
6104
  if (cached2 !== void 0)
6088
6105
  return cached2 ? PROVEN : NONE;
@@ -6092,7 +6109,7 @@ function isRecursive(inst, stack, resolve8) {
6092
6109
  let result = NONE;
6093
6110
  const check2 = (child) => {
6094
6111
  if (result !== PROVEN && child?._zod) {
6095
- const answer = isRecursive(child, stack, resolve8);
6112
+ const answer = isRecursive(child, stack, resolve9);
6096
6113
  if (answer > result)
6097
6114
  result = answer;
6098
6115
  }
@@ -6103,7 +6120,7 @@ function isRecursive(inst, stack, resolve8) {
6103
6120
  const desc = Object.getOwnPropertyDescriptor(sh, key);
6104
6121
  if (spread && !desc.enumerable)
6105
6122
  continue;
6106
- const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve8) : NONE;
6123
+ const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve9) : NONE;
6107
6124
  if (child > answer)
6108
6125
  answer = child;
6109
6126
  }
@@ -6167,7 +6184,7 @@ function isRecursive(inst, stack, resolve8) {
6167
6184
  break;
6168
6185
  // `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
6169
6186
  case "lazy": {
6170
- const inner = def._cachedInner ?? (resolve8 ? inst._zod.innerType : void 0);
6187
+ const inner = def._cachedInner ?? (resolve9 ? inst._zod.innerType : void 0);
6171
6188
  merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
6172
6189
  break;
6173
6190
  }
@@ -23608,7 +23625,29 @@ var StorePosturePlugin = external_exports.object({
23608
23625
  */
23609
23626
  policyBundleVersion: external_exports.string().max(200).nullable(),
23610
23627
  /** Epoch millis, on the CLIENT clock, of that fetch. */
23611
- policyFetchedAt: external_exports.number().int().min(0).max(MAX_DATE_MS).nullable()
23628
+ policyFetchedAt: external_exports.number().int().min(0).max(MAX_DATE_MS).nullable(),
23629
+ /**
23630
+ * The newest version the host's own install record holds for this plugin —
23631
+ * what is on disk. After an update it leads `version` (the running copy) by
23632
+ * one launch. Null when no usable version can be read: no install record
23633
+ * (a plugin run from a checkout), no entry with a valid version, or every
23634
+ * such entry names an `installPath` that no longer exists; OPTIONAL, not
23635
+ * required, so a build that predates the member keeps getting its 200.
23636
+ * Bounded like `version`.
23637
+ */
23638
+ installedVersion: external_exports.string().max(64).nullable().optional(),
23639
+ /**
23640
+ * The local-store schema version this running build migrates a store to:
23641
+ * the number of store migrations it carries, the count it stamps into
23642
+ * `PRAGMA user_version`. A snapshot whose `schemaVersion` is above it
23643
+ * usually describes a store a newer build migrated. It is a hint, not a
23644
+ * verdict: the stamp is write-only, so a store whose count ran past this
23645
+ * build's while this build knows every migration in its ledger reads above
23646
+ * it too, which is why describeStoreSkew decides skew on ledger tags and
23647
+ * never on the count. OPTIONAL for the same reason as `installedVersion`;
23648
+ * bounded like `schemaVersion`.
23649
+ */
23650
+ buildSchemaVersion: external_exports.number().int().min(0).max(MAX_INT4).optional()
23612
23651
  }).meta({ id: "StorePosturePlugin" });
23613
23652
  var StorePostureSnapshot = external_exports.object({
23614
23653
  deviceId: external_exports.guid(),
@@ -25184,10 +25223,15 @@ var ParsedPointer = external_exports.object({
25184
25223
  });
25185
25224
  var VaultEntry = external_exports.object({
25186
25225
  pointerId: external_exports.string(),
25187
- // The keyed HMAC of the raw value under `exception.key`, and the epoch it was
25188
- // derived under. This is what a reveal-to-model grant matches on, and it rotates
25189
- // independently of the vault encryption key below.
25226
+ // The keyed HMAC of the EXACT raw bytes under `exception.key`, and the epoch it
25227
+ // was derived under. The vault's own dedupe key: a value and its invisibly
25228
+ // padded twin are two rows. It rotates independently of the vault encryption
25229
+ // key below. Never matched against an exception or grant.
25190
25230
  valueFingerprint: external_exports.string().regex(/^[0-9a-f]{64}$/),
25231
+ // The same HMAC over the raw with invisible padding removed: the identity a
25232
+ // reveal-to-model grant and every exception match on. Shared by a value and
25233
+ // its padded twin.
25234
+ valueIdentityFingerprint: external_exports.string().regex(/^[0-9a-f]{64}$/),
25191
25235
  fingerprintKeyVersion: external_exports.number().int().positive(),
25192
25236
  // The vault-key epoch this row's ciphertext was sealed under.
25193
25237
  keyVersion: external_exports.number().int().positive(),
@@ -25816,10 +25860,18 @@ var SeveritySummaryItem = external_exports.object({
25816
25860
  count: external_exports.number().int().nonnegative(),
25817
25861
  // Resolution-aware breakdown (optional, additive). Populated once findings
25818
25862
  // carry lifecycle state: `caught` = handled in-flight (enforced); `openAtRest`
25819
- // = still open with no in-flight enforcement (needs remediation). Absent on the
25820
- // legacy count-only response until the resolution feature lands.
25863
+ // = still open with no in-flight enforcement (needs remediation); `dismissed`
25864
+ // = closed by a human judgement rather than a fix — visible, but not counted as
25865
+ // needing remediation. The three are disjoint. Absent on the legacy count-only
25866
+ // response until the resolution feature lands.
25821
25867
  caught: external_exports.number().int().nonnegative().optional(),
25822
- openAtRest: external_exports.number().int().nonnegative().optional()
25868
+ openAtRest: external_exports.number().int().nonnegative().optional(),
25869
+ dismissed: external_exports.number().int().nonnegative().optional(),
25870
+ // The two halves of `caught`, for a reader that wants them apart: `handled` =
25871
+ // in-flight findings an enforcement action already contained; `resolved` =
25872
+ // at-rest findings closed out by fixing them. `handled + resolved === caught`.
25873
+ handled: external_exports.number().int().nonnegative().optional(),
25874
+ resolved: external_exports.number().int().nonnegative().optional()
25823
25875
  }).meta({ id: "SeveritySummaryItem" });
25824
25876
  var SeveritySummaryResponse = external_exports.object({
25825
25877
  // Sum of bySeverity[].count.
@@ -25827,6 +25879,9 @@ var SeveritySummaryResponse = external_exports.object({
25827
25879
  // Findings still open at rest (sum of bySeverity[].openAtRest). Optional and
25828
25880
  // additive — absent on the legacy response until the resolution feature lands.
25829
25881
  needsRemediation: external_exports.number().int().nonnegative().optional(),
25882
+ // Findings a user dismissed (sum of bySeverity[].dismissed). Excluded from
25883
+ // needsRemediation, and kept visible here so an accepted risk is not erased.
25884
+ dismissed: external_exports.number().int().nonnegative().optional(),
25830
25885
  // All four severity levels are always present (count may be 0).
25831
25886
  bySeverity: external_exports.array(SeveritySummaryItem)
25832
25887
  }).meta({ id: "SeveritySummaryResponse" });
@@ -26203,6 +26258,15 @@ var RELEASE_TAG_SOURCE = {
26203
26258
  /** The lookup produced no tag map at all; the version is null. */
26204
26259
  Unknown: "unknown"
26205
26260
  };
26261
+ function managedPluginNoteParts(s) {
26262
+ const managed = s.managedInstall;
26263
+ if (managed === void 0) return { ref: "", lead: "" };
26264
+ return {
26265
+ ref: managed.ref !== void 0 ? ` (marketplace ref ${managed.ref})` : "",
26266
+ lead: managed.pending && s.latest !== null ? `v${s.latest} is on its way. ` : ""
26267
+ };
26268
+ }
26269
+ var MANAGED_PLUGIN_ADVICE = "Your organization's managed settings install it and pin its version. Updates arrive through Claude Code's own plugin autoupdate when a new session starts, or /plugin \u2192 update inside a session.";
26206
26270
 
26207
26271
  // ../packages/schema/src/zod/web-capture.ts
26208
26272
  var WebUsageSource = external_exports.enum(["site", "estimated", "none"]);
@@ -26462,9 +26526,9 @@ var HOST_VERBS = {
26462
26526
  // Stated rather than defaulted, and stated whenever the ledger names one —
26463
26527
  // including `user`. An implicit agreement between the two halves is exactly
26464
26528
  // what broke, so the reading the comparison used is the one spelled here.
26465
- // Whether a given scope may be updated at all is the host's call: `managed`
26466
- // is an administrator's install, and a refusal from `claude` naming that is
26467
- // a true answer, unlike the one this replaces.
26529
+ // A `managed` install never reaches this verb: it is an organization's
26530
+ // install, pinned by its marketplace declaration, and `applyPluginUpdate`
26531
+ // refuses it before anything runs. Every other scope is spelled here.
26468
26532
  update: (ref, scope) => [["plugin", "update", ref, ...scope ? ["--scope", scope] : []]],
26469
26533
  register: (source) => [["plugin", "marketplace", "add", source]],
26470
26534
  refresh: (marketplace) => [["plugin", "marketplace", "update", marketplace]]
@@ -26574,11 +26638,24 @@ function readJson(path) {
26574
26638
  }
26575
26639
  }
26576
26640
  function marketplaceRoot(claudeHome, marketplace) {
26641
+ const entry = knownMarketplace(claudeHome, marketplace);
26642
+ if (entry === null) return null;
26643
+ return typeof entry.installLocation === "string" ? entry.installLocation : null;
26644
+ }
26645
+ function knownMarketplace(claudeHome, marketplace) {
26577
26646
  const known = readJson(knownMarketplacesPath(claudeHome));
26578
26647
  if (!isRecord(known)) return null;
26579
26648
  const entry = known[marketplace];
26580
- if (!isRecord(entry)) return null;
26581
- return typeof entry.installLocation === "string" ? entry.installLocation : null;
26649
+ return isRecord(entry) ? entry : null;
26650
+ }
26651
+ var MAX_REF_LENGTH = 200;
26652
+ var printableRef = printable(MAX_REF_LENGTH);
26653
+ function marketplaceSourceRef(claudeHome, marketplace) {
26654
+ const entry = knownMarketplace(claudeHome, marketplace);
26655
+ if (entry === null || !isRecord(entry.source)) return void 0;
26656
+ const ref = entry.source.ref;
26657
+ if (typeof ref !== "string" || ref.trim() === "") return void 0;
26658
+ return printableRef.safeParse(ref).success ? ref : void 0;
26582
26659
  }
26583
26660
  var NO_PIN = { version: null };
26584
26661
  function marketplacePinnedVersion(agent, claudeHome = join(homedir2(), ".claude")) {
@@ -26715,6 +26792,19 @@ function installedPluginsPath(claudeHome) {
26715
26792
  return join2(claudeHome, "plugins", "installed_plugins.json");
26716
26793
  }
26717
26794
  function installedPlugins(claudeHome = join2(homedir3(), ".claude")) {
26795
+ const out = /* @__PURE__ */ new Map();
26796
+ for (const [ref, records] of ledgerRecords(claudeHome)) {
26797
+ const record2 = records.find((r) => isRecord2(r) && r.scope === "user") ?? records.find((r) => isRecord2(r));
26798
+ if (record2 && typeof record2.version === "string") {
26799
+ out.set(ref, {
26800
+ version: record2.version,
26801
+ ...typeof record2.scope === "string" ? { scope: record2.scope } : {}
26802
+ });
26803
+ }
26804
+ }
26805
+ return out;
26806
+ }
26807
+ function ledgerRecords(claudeHome) {
26718
26808
  const out = /* @__PURE__ */ new Map();
26719
26809
  const path = installedPluginsPath(claudeHome);
26720
26810
  if (!existsSync2(path)) return out;
@@ -26726,20 +26816,24 @@ function installedPlugins(claudeHome = join2(homedir3(), ".claude")) {
26726
26816
  }
26727
26817
  if (!isRecord2(raw) || !isRecord2(raw.plugins)) return out;
26728
26818
  for (const [ref, records] of Object.entries(raw.plugins)) {
26729
- if (!Array.isArray(records) || records.length === 0) continue;
26730
- const record2 = records.find((r) => isRecord2(r) && r.scope === "user") ?? records.find((r) => isRecord2(r));
26731
- if (record2 && typeof record2.version === "string") {
26732
- out.set(ref, {
26733
- version: record2.version,
26734
- ...typeof record2.scope === "string" ? { scope: record2.scope } : {}
26735
- });
26736
- }
26819
+ if (Array.isArray(records) && records.length > 0) out.set(ref, records);
26737
26820
  }
26738
26821
  return out;
26739
26822
  }
26740
26823
  function installedPluginScope(ref, claudeHome) {
26741
26824
  return installedPlugins(claudeHome).get(ref)?.scope;
26742
26825
  }
26826
+ var MANAGED_SCOPE = "managed";
26827
+ function managedPluginInstall(agent, claudeHome = join2(homedir3(), ".claude")) {
26828
+ if (agent.cliBin !== "claude") return null;
26829
+ const ref = pluginRef(agent);
26830
+ if (ref === void 0) return null;
26831
+ const record2 = ledgerRecords(claudeHome).get(ref)?.find((r) => isRecord2(r) && r.scope === MANAGED_SCOPE);
26832
+ if (record2 === void 0) return null;
26833
+ const version2 = typeof record2.version === "string" && record2.version.trim() !== "" ? record2.version : null;
26834
+ const sourceRef = agent.marketplace === void 0 ? void 0 : marketplaceSourceRef(claudeHome, agent.marketplace);
26835
+ return { version: version2, ...sourceRef !== void 0 ? { ref: sourceRef } : {} };
26836
+ }
26743
26837
  function installedPluginVersions(claudeHome) {
26744
26838
  return new Map([...installedPlugins(claudeHome)].map(([ref, { version: version2 }]) => [ref, version2]));
26745
26839
  }
@@ -26830,7 +26924,8 @@ function gatherReport(deps) {
26830
26924
  for (const agent of AGENT_PLUGINS) {
26831
26925
  const ref = pluginRef(agent);
26832
26926
  if (!ref || !agent.npmPackage) continue;
26833
- const installed = deps.installed.get(ref) ?? null;
26927
+ const managed = deps.managedInstall(agent);
26928
+ const installed = managed !== null ? managed.version : deps.installed.get(ref) ?? null;
26834
26929
  const channel = channelOfVersion(installed);
26835
26930
  const npm = resolveChannel(deps.viewDistTags(agent.npmPackage), channel);
26836
26931
  const npmLatest = npm.version;
@@ -26845,6 +26940,23 @@ function gatherReport(deps) {
26845
26940
  ...pin.range !== void 0 ? { range: pin.range } : {}
26846
26941
  }
26847
26942
  } : {};
26943
+ if (managed !== null) {
26944
+ statuses.push({
26945
+ id: agent.id,
26946
+ name: agent.name,
26947
+ kind: "plugin",
26948
+ installed,
26949
+ latest: pin.version,
26950
+ updateAvailable: false,
26951
+ channel,
26952
+ ...pinned,
26953
+ managedInstall: {
26954
+ ...managed.ref !== void 0 ? { ref: managed.ref } : {},
26955
+ pending: pin.version !== null && installed !== null && isNewer(pin.version, installed)
26956
+ }
26957
+ });
26958
+ continue;
26959
+ }
26848
26960
  if (installed === null) {
26849
26961
  availablePlugins.push({ id: agent.id, name: agent.name, latest });
26850
26962
  continue;
@@ -26879,7 +26991,8 @@ function gatherReportLive(cliChannel) {
26879
26991
  // the HOST check, because a guard written at the call site admits Codex —
26880
26992
  // its registry entry carries a marketplace and a plugin name like any
26881
26993
  // other — into a reader that only understands Claude Code's layout.
26882
- marketplacePin: (agent) => marketplacePinnedVersion(agent)
26994
+ marketplacePin: (agent) => marketplacePinnedVersion(agent),
26995
+ managedInstall: (agent) => managedPluginInstall(agent)
26883
26996
  });
26884
26997
  }
26885
26998
 
@@ -27184,6 +27297,118 @@ function describeChannel(channel) {
27184
27297
  }
27185
27298
  }
27186
27299
 
27300
+ // ../packages/local-ops/src/update-render.ts
27301
+ function pinNotes(report) {
27302
+ const notes = [];
27303
+ for (const s of report.statuses) {
27304
+ const pin = s.marketplacePin;
27305
+ if (!pin || s.managedInstall) continue;
27306
+ if (pin.range !== void 0) {
27307
+ const npmPart = pin.npmLatest !== null ? ` npm has v${pin.npmLatest}.` : "";
27308
+ notes.push(
27309
+ ` ${s.name}: the ${pin.marketplace} marketplace pins ${pin.range}, which the host resolves within \u2014 not a single version this report can compare.${npmPart}`
27310
+ );
27311
+ continue;
27312
+ }
27313
+ if (!pin.npmAhead || s.latest === null || pin.npmLatest === null) continue;
27314
+ notes.push(
27315
+ ` ${s.name}: the ${pin.marketplace} marketplace pins v${s.latest}. npm has v${pin.npmLatest}, which this machine cannot install until that marketplace moves.`
27316
+ );
27317
+ }
27318
+ return notes;
27319
+ }
27320
+ function managedNotes(report) {
27321
+ const notes = [];
27322
+ for (const s of report.statuses) {
27323
+ if (!s.managedInstall) continue;
27324
+ const { ref, lead } = managedPluginNoteParts(s);
27325
+ notes.push(
27326
+ ` ${s.name}${ref}: ${lead}${MANAGED_PLUGIN_ADVICE} \`aka update\` leaves it alone.`
27327
+ );
27328
+ }
27329
+ return notes;
27330
+ }
27331
+ function managedState(s) {
27332
+ if (!s.managedInstall) return void 0;
27333
+ if (s.installed === null || s.latest === null) return "unknown";
27334
+ if (!isSemver(s.installed) || !isSemver(s.latest)) return "unknown";
27335
+ return s.managedInstall.pending ? "pending" : "current";
27336
+ }
27337
+ var MANAGED_STATUS = {
27338
+ unknown: "managed",
27339
+ pending: "managed \u2014 update pending",
27340
+ current: "managed \u2014 up to date"
27341
+ };
27342
+ function statusLabel(s) {
27343
+ const managed = managedState(s);
27344
+ if (managed !== void 0) return MANAGED_STATUS[managed];
27345
+ if (s.installed === null || s.latest === null) return "unknown";
27346
+ return s.updateAvailable ? "update available" : "up to date";
27347
+ }
27348
+ function channelCell(s) {
27349
+ return s.channel === void 0 || s.channel === RELEASE_CHANNEL.Stable ? "" : s.channel;
27350
+ }
27351
+ function renderReport(report) {
27352
+ const rows = report.statuses.map((s) => ({
27353
+ name: s.name,
27354
+ installed: s.installed ?? "\u2014",
27355
+ latest: s.latest ?? "unknown",
27356
+ channel: channelCell(s),
27357
+ status: statusLabel(s)
27358
+ }));
27359
+ const nameW = Math.max(9, ...rows.map((r) => r.name.length));
27360
+ const instW = Math.max(9, ...rows.map((r) => r.installed.length));
27361
+ const latW = Math.max(6, ...rows.map((r) => r.latest.length));
27362
+ const chanW = rows.some((r) => r.channel !== "") ? Math.max(7, ...rows.map((r) => r.channel.length)) : 0;
27363
+ const chanCol = (value) => chanW === 0 ? "" : `${value.padEnd(chanW)} `;
27364
+ const lines = [];
27365
+ lines.push(
27366
+ ` ${"Component".padEnd(nameW)} ${"Installed".padEnd(instW)} ${"Latest".padEnd(latW)} ${chanCol("Channel")}Status`
27367
+ );
27368
+ for (const r of rows) {
27369
+ lines.push(
27370
+ ` ${r.name.padEnd(nameW)} ${r.installed.padEnd(instW)} ${r.latest.padEnd(latW)} ${chanCol(r.channel)}${r.status}`
27371
+ );
27372
+ }
27373
+ const notes = pinNotes(report);
27374
+ if (notes.length > 0) {
27375
+ lines.push("");
27376
+ lines.push(" Pinned by a marketplace:");
27377
+ lines.push(...notes);
27378
+ }
27379
+ const managed = managedNotes(report);
27380
+ if (managed.length > 0) {
27381
+ lines.push("");
27382
+ lines.push(" Managed by your organization:");
27383
+ lines.push(...managed);
27384
+ }
27385
+ if (report.availablePlugins.length > 0) {
27386
+ lines.push("");
27387
+ lines.push(" Available plugins (not installed):");
27388
+ for (const p of report.availablePlugins) {
27389
+ const version2 = p.latest ? ` v${p.latest}` : "";
27390
+ lines.push(` ${p.name} (${p.id})${version2} \u2014 install: aka plugins install ${p.id}`);
27391
+ }
27392
+ }
27393
+ return lines.join("\n");
27394
+ }
27395
+ function outdated(report) {
27396
+ return report.statuses.filter((s) => s.updateAvailable);
27397
+ }
27398
+ function nothingToApplyLine(report) {
27399
+ const unsettled = report.statuses.some((s) => {
27400
+ const managed = managedState(s);
27401
+ return managed !== void 0 && managed !== "current";
27402
+ });
27403
+ return unsettled ? "Nothing for `aka update` to apply \u2014 updates to the plugin your organization manages arrive through Claude Code itself." : "Everything is up to date.";
27404
+ }
27405
+ function managedUpdateRefusal(name) {
27406
+ return `${name} is managed by your organization, so nothing was run. ${MANAGED_PLUGIN_ADVICE}`;
27407
+ }
27408
+ function managedInstallRefusal(name) {
27409
+ return `${name} is managed by your organization and is already installed, so nothing was run. ` + MANAGED_PLUGIN_ADVICE;
27410
+ }
27411
+
27187
27412
  // ../packages/local-ops/src/apply.ts
27188
27413
  var APPLY_TIMEOUT_MS = 10 * 6e4;
27189
27414
  var PREP_TIMEOUT_MS = 6e4;
@@ -27255,6 +27480,10 @@ function prepare(resolved, mode) {
27255
27480
  }
27256
27481
  }
27257
27482
  function applyPluginUpdate(agentId, mode = "capture") {
27483
+ const agent = findAgent(agentId);
27484
+ if (agent !== void 0 && managedPluginInstall(agent) !== null) {
27485
+ return { ok: false, output: managedUpdateRefusal(agent.name) };
27486
+ }
27258
27487
  const resolved = resolveRef2(agentId);
27259
27488
  if ("ok" in resolved) return resolved;
27260
27489
  prepare(resolved, mode);
@@ -27262,6 +27491,10 @@ function applyPluginUpdate(agentId, mode = "capture") {
27262
27491
  return runSteps(resolved.cliBin, manager3.updateSteps(resolved.ref), mode);
27263
27492
  }
27264
27493
  function installAgentPlugin(agentId, mode = "capture") {
27494
+ const agent = findAgent(agentId);
27495
+ if (agent !== void 0 && managedPluginInstall(agent) !== null) {
27496
+ return { ok: false, output: managedInstallRefusal(agent.name) };
27497
+ }
27265
27498
  const resolved = resolveRef2(agentId);
27266
27499
  if ("ok" in resolved) return resolved;
27267
27500
  prepare(resolved, mode);
@@ -28484,11 +28717,11 @@ var EXACT_KIND_BY_BASENAME = {
28484
28717
  "composer.json": "composer.json",
28485
28718
  "packages.config": "packages.config"
28486
28719
  };
28487
- function manifestKindOf(basename9) {
28488
- if (LOCKFILE_BASENAMES.has(basename9)) return null;
28489
- const exact = Object.hasOwn(EXACT_KIND_BY_BASENAME, basename9) ? EXACT_KIND_BY_BASENAME[basename9] : void 0;
28720
+ function manifestKindOf(basename10) {
28721
+ if (LOCKFILE_BASENAMES.has(basename10)) return null;
28722
+ const exact = Object.hasOwn(EXACT_KIND_BY_BASENAME, basename10) ? EXACT_KIND_BY_BASENAME[basename10] : void 0;
28490
28723
  if (exact !== void 0) return exact;
28491
- if (basename9.endsWith(".csproj")) return "csproj";
28724
+ if (basename10.endsWith(".csproj")) return "csproj";
28492
28725
  return null;
28493
28726
  }
28494
28727
  function extractManifestSdks(text, kind) {
@@ -28966,6 +29199,82 @@ function escapeRegExp2(value) {
28966
29199
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
28967
29200
  }
28968
29201
 
29202
+ // ../packages/detections/src/format-chars.ts
29203
+ var HAS_FORMAT_CHAR = new RegExp("\\p{Cf}", "u");
29204
+ var FORMAT_CHAR_GLOBAL = new RegExp("\\p{Cf}", "gu");
29205
+ function normalizeFormatChars(text) {
29206
+ if (!HAS_FORMAT_CHAR.test(text)) return void 0;
29207
+ const normalizedParts = [];
29208
+ const segments2 = [];
29209
+ let cursor = 0;
29210
+ let normLength = 0;
29211
+ for (const match of text.matchAll(FORMAT_CHAR_GLOBAL)) {
29212
+ const matchStart = match.index;
29213
+ if (matchStart > cursor) {
29214
+ const length = matchStart - cursor;
29215
+ normalizedParts.push(text.slice(cursor, matchStart));
29216
+ segments2.push({ normStart: normLength, origStart: cursor, length });
29217
+ normLength += length;
29218
+ }
29219
+ cursor = matchStart + match[0].length;
29220
+ }
29221
+ if (cursor < text.length) {
29222
+ const length = text.length - cursor;
29223
+ normalizedParts.push(text.slice(cursor));
29224
+ segments2.push({ normStart: normLength, origStart: cursor, length });
29225
+ }
29226
+ return { normalized: normalizedParts.join(""), segments: segments2 };
29227
+ }
29228
+ function segmentAt(segments2, normPos) {
29229
+ let lo = 0;
29230
+ let hi = segments2.length - 1;
29231
+ while (lo < hi) {
29232
+ const mid = lo + hi >> 1;
29233
+ const segment = segments2[mid];
29234
+ if (segment !== void 0 && normPos >= segment.normStart + segment.length) {
29235
+ lo = mid + 1;
29236
+ } else {
29237
+ hi = mid;
29238
+ }
29239
+ }
29240
+ const found = segments2[lo];
29241
+ if (found === void 0) {
29242
+ throw new Error(`normPos ${String(normPos)} has no covering segment`);
29243
+ }
29244
+ return found;
29245
+ }
29246
+ function mapSpanToOriginal(span, normalization) {
29247
+ const { segments: segments2 } = normalization;
29248
+ const startSegment = segmentAt(segments2, span.start);
29249
+ const start = startSegment.origStart + (span.start - startSegment.normStart);
29250
+ const endSegment = segmentAt(segments2, span.end - 1);
29251
+ const end = endSegment.origStart + (span.end - 1 - endSegment.normStart) + 1;
29252
+ return { start, end };
29253
+ }
29254
+ function normalizedOffset(origPos, segments2) {
29255
+ let lo = 0;
29256
+ let hi = segments2.length;
29257
+ while (lo < hi) {
29258
+ const mid = lo + hi >> 1;
29259
+ const segment = segments2[mid];
29260
+ if (segment !== void 0 && segment.origStart + segment.length <= origPos) {
29261
+ lo = mid + 1;
29262
+ } else {
29263
+ hi = mid;
29264
+ }
29265
+ }
29266
+ const found = segments2[Math.min(lo, segments2.length - 1)];
29267
+ if (found === void 0) return 0;
29268
+ return found.normStart + Math.min(Math.max(0, origPos - found.origStart), found.length);
29269
+ }
29270
+ function mapSpanToNormalized(span, normalization) {
29271
+ const { segments: segments2 } = normalization;
29272
+ return {
29273
+ start: normalizedOffset(span.start, segments2),
29274
+ end: normalizedOffset(span.end, segments2)
29275
+ };
29276
+ }
29277
+
28969
29278
  // ../packages/detections/src/regex-cache.ts
28970
29279
  var singles = /* @__PURE__ */ new WeakMap();
28971
29280
  var keywordLists = /* @__PURE__ */ new WeakMap();
@@ -29127,29 +29436,35 @@ function registerPack(pack) {
29127
29436
  function getLoadedRules() {
29128
29437
  return [...packs.values()].flatMap((p) => p.rules);
29129
29438
  }
29130
- function isCorroborated(candidate, candidates, text) {
29439
+ function spansOverlap(a, b) {
29440
+ return a.start < b.end && a.end > b.start;
29441
+ }
29442
+ function isCorroborated(candidate, candidates, text, normalization) {
29131
29443
  const req = candidate.rule.requiresNearby;
29132
29444
  if (!req) return true;
29133
29445
  const halfWindow = req.windowChars;
29134
- const { start, end } = candidate.match.span;
29135
- const winStart = start - halfWindow;
29136
- const winEnd = end + halfWindow;
29446
+ const ns = candidate.normSpan;
29447
+ const winStart = ns.start - halfWindow;
29448
+ const winEnd = ns.end + halfWindow;
29137
29449
  const categories = req.categories;
29138
29450
  const ruleIds = req.ruleIds;
29139
29451
  if (categories?.length || ruleIds?.length) {
29140
29452
  for (const other of candidates) {
29141
29453
  if (other === candidate) continue;
29142
- const os = other.match.span;
29143
- if (os.end < winStart || os.start > winEnd) continue;
29144
- if (other.match.ruleId !== candidate.match.ruleId && categories?.includes(other.match.category)) {
29145
- return true;
29454
+ if (other.normSpan.end < winStart || other.normSpan.start > winEnd) continue;
29455
+ const relevant = other.match.ruleId !== candidate.match.ruleId && categories?.includes(other.match.category) === true || ruleIds?.includes(other.match.ruleId) === true;
29456
+ if (!relevant) continue;
29457
+ if (other.match.ruleId === candidate.match.ruleId && spansOverlap(other.match.span, candidate.match.span)) {
29458
+ continue;
29146
29459
  }
29147
- if (ruleIds?.includes(other.match.ruleId)) return true;
29460
+ return true;
29148
29461
  }
29149
29462
  }
29150
29463
  const labels = req.labels;
29151
29464
  if (labels && labels.length > 0) {
29152
- const haystack = text.slice(Math.max(0, winStart), winEnd);
29465
+ const { start, end } = candidate.match.span;
29466
+ const haystack = text.slice(Math.max(0, start - halfWindow), end + halfWindow);
29467
+ const normalizedHaystack = normalization === void 0 ? void 0 : normalization.normalized.slice(Math.max(0, winStart), winEnd);
29153
29468
  for (const re of memoizedRegExpList(
29154
29469
  "label",
29155
29470
  req,
@@ -29158,29 +29473,20 @@ function isCorroborated(candidate, candidates, text) {
29158
29473
  return trimmed.length === 0 ? void 0 : new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed)}(?![A-Za-z0-9])`, "i");
29159
29474
  })
29160
29475
  )) {
29161
- if (re?.test(haystack)) return true;
29476
+ if (!re) continue;
29477
+ if (re.test(haystack)) return true;
29478
+ if (normalizedHaystack !== void 0 && re.test(normalizedHaystack)) return true;
29162
29479
  }
29163
29480
  }
29164
29481
  return false;
29165
29482
  }
29166
- function extensionOf(filePath) {
29167
- const base = filePath.slice(Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\")) + 1);
29168
- const dot = base.lastIndexOf(".");
29169
- return dot > 0 ? base.slice(dot).toLowerCase() : void 0;
29170
- }
29171
- function ruleApplies(rule, extension) {
29172
- if (!rule.appliesTo || extension === void 0) return true;
29173
- return rule.appliesTo.extensions.some((e) => e.toLowerCase() === extension);
29174
- }
29175
- function scan(text, rules, context) {
29176
- const ruleset = rules ?? getLoadedRules();
29177
- const extension = context?.filePath ? extensionOf(context.filePath) : void 0;
29483
+ function buildCandidates(matchText, ruleset, extension) {
29178
29484
  const candidates = [];
29179
29485
  for (const rule of ruleset) {
29180
29486
  if (!ruleApplies(rule, extension)) continue;
29181
- const spans = MATCHERS[rule.matcher.type](text, rule);
29487
+ const spans = MATCHERS[rule.matcher.type](matchText, rule);
29182
29488
  for (const span of spans) {
29183
- const rawMatch = text.slice(span.start, span.end);
29489
+ const rawMatch = matchText.slice(span.start, span.end);
29184
29490
  if (!passesPostValidators(rule, rawMatch)) continue;
29185
29491
  candidates.push({
29186
29492
  rule,
@@ -29191,10 +29497,31 @@ function scan(text, rules, context) {
29191
29497
  span,
29192
29498
  rawMatch,
29193
29499
  confidence: 0.9
29194
- }
29500
+ },
29501
+ // In `matchText`'s own coordinates, which is the normalized text for
29502
+ // a normalized-pass candidate and so already right; an original-pass
29503
+ // candidate on the slow path is re-derived by withNormalizedSpan.
29504
+ normSpan: span
29195
29505
  });
29196
29506
  }
29197
29507
  }
29508
+ return candidates;
29509
+ }
29510
+ function mapCandidateToOriginal(candidate, normalization, text) {
29511
+ const span = mapSpanToOriginal(candidate.match.span, normalization);
29512
+ return {
29513
+ rule: candidate.rule,
29514
+ match: { ...candidate.match, span, rawMatch: text.slice(span.start, span.end) },
29515
+ // Deliberately NOT remapped: `normSpan` is the span the primitive match
29516
+ // was found at in the normalized text, which is exactly the coordinate
29517
+ // space windows are measured in. See the `Candidate` comment.
29518
+ normSpan: candidate.normSpan
29519
+ };
29520
+ }
29521
+ function withNormalizedSpan(candidate, normalization) {
29522
+ return { ...candidate, normSpan: mapSpanToNormalized(candidate.match.span, normalization) };
29523
+ }
29524
+ function gate(candidates, text, normalization) {
29198
29525
  const findings = [];
29199
29526
  for (const candidate of candidates) {
29200
29527
  const req = candidate.rule.requiresNearby;
@@ -29202,7 +29529,7 @@ function scan(text, rules, context) {
29202
29529
  findings.push(candidate.match);
29203
29530
  continue;
29204
29531
  }
29205
- if (!isCorroborated(candidate, candidates, text)) continue;
29532
+ if (!isCorroborated(candidate, candidates, text, normalization)) continue;
29206
29533
  const boost = req.confidenceBoost;
29207
29534
  findings.push(
29208
29535
  boost ? { ...candidate.match, confidence: Math.min(0.99, candidate.match.confidence + boost) } : candidate.match
@@ -29210,6 +29537,81 @@ function scan(text, rules, context) {
29210
29537
  }
29211
29538
  return findings;
29212
29539
  }
29540
+ function closeRegion(open3, text) {
29541
+ const span = { start: open3.start, end: open3.end };
29542
+ return {
29543
+ ruleId: open3.ruleId,
29544
+ category: open3.category,
29545
+ severity: open3.severity,
29546
+ span,
29547
+ rawMatch: text.slice(span.start, span.end),
29548
+ confidence: open3.confidence
29549
+ };
29550
+ }
29551
+ function mergeOverlappingSameRule(findings, text) {
29552
+ if (findings.length === 0) return findings;
29553
+ const groups = /* @__PURE__ */ new Map();
29554
+ const ruleOrder = [];
29555
+ for (const finding of findings) {
29556
+ const group = groups.get(finding.ruleId);
29557
+ if (group) {
29558
+ group.push(finding);
29559
+ } else {
29560
+ groups.set(finding.ruleId, [finding]);
29561
+ ruleOrder.push(finding.ruleId);
29562
+ }
29563
+ }
29564
+ const merged = [];
29565
+ for (const ruleId of ruleOrder) {
29566
+ const group = groups.get(ruleId) ?? [];
29567
+ const sorted = [...group].sort(
29568
+ (a, b) => a.span.start - b.span.start || a.span.end - b.span.end
29569
+ );
29570
+ let open3;
29571
+ for (const finding of sorted) {
29572
+ if (open3 && finding.span.start < open3.end) {
29573
+ open3.end = Math.max(open3.end, finding.span.end);
29574
+ open3.confidence = Math.max(open3.confidence, finding.confidence);
29575
+ continue;
29576
+ }
29577
+ if (open3) merged.push(closeRegion(open3, text));
29578
+ open3 = {
29579
+ start: finding.span.start,
29580
+ end: finding.span.end,
29581
+ confidence: finding.confidence,
29582
+ ruleId: finding.ruleId,
29583
+ category: finding.category,
29584
+ severity: finding.severity
29585
+ };
29586
+ }
29587
+ if (open3) merged.push(closeRegion(open3, text));
29588
+ }
29589
+ return merged;
29590
+ }
29591
+ function extensionOf(filePath) {
29592
+ const base = filePath.slice(Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\")) + 1);
29593
+ const dot = base.lastIndexOf(".");
29594
+ return dot > 0 ? base.slice(dot).toLowerCase() : void 0;
29595
+ }
29596
+ function ruleApplies(rule, extension) {
29597
+ if (!rule.appliesTo || extension === void 0) return true;
29598
+ return rule.appliesTo.extensions.some((e) => e.toLowerCase() === extension);
29599
+ }
29600
+ function scan(text, rules, context) {
29601
+ const ruleset = rules ?? getLoadedRules();
29602
+ const extension = context?.filePath ? extensionOf(context.filePath) : void 0;
29603
+ const normalization = normalizeFormatChars(text);
29604
+ const originalCandidates = buildCandidates(text, ruleset, extension);
29605
+ if (!normalization) return gate(originalCandidates, text, void 0);
29606
+ const pooledOriginal = originalCandidates.map(
29607
+ (candidate) => withNormalizedSpan(candidate, normalization)
29608
+ );
29609
+ const normalizedCandidates = buildCandidates(normalization.normalized, ruleset, extension).map(
29610
+ (candidate) => mapCandidateToOriginal(candidate, normalization, text)
29611
+ );
29612
+ const findings = gate([...pooledOriginal, ...normalizedCandidates], text, normalization);
29613
+ return mergeOverlappingSameRule(findings, text);
29614
+ }
29213
29615
  var SEVERITY_RANK2 = {
29214
29616
  critical: 3,
29215
29617
  high: 2,
@@ -29632,11 +30034,11 @@ function repairOrRefuseMode(file2) {
29632
30034
  const link = lstatSync2(file2, { throwIfNoEntry: false });
29633
30035
  if (link === void 0) return "absent";
29634
30036
  if (link.isSymbolicLink()) return "untrusted";
29635
- const stat = statSync(file2, { throwIfNoEntry: false });
29636
- if (stat === void 0) return "absent";
30037
+ const stat2 = statSync(file2, { throwIfNoEntry: false });
30038
+ if (stat2 === void 0) return "absent";
29637
30039
  const uid = process.getuid?.();
29638
- if (uid !== void 0 && stat.uid !== uid) return "untrusted";
29639
- if (process.platform !== "win32" && (stat.mode & 511) !== DATA_FILE_MODE) {
30040
+ if (uid !== void 0 && stat2.uid !== uid) return "untrusted";
30041
+ if (process.platform !== "win32" && (stat2.mode & 511) !== DATA_FILE_MODE) {
29640
30042
  try {
29641
30043
  chmodSync2(file2, DATA_FILE_MODE);
29642
30044
  } catch {
@@ -29652,9 +30054,9 @@ function readControlPlaneCredentialState(settingsDir2, connection) {
29652
30054
  function readControlPlaneCredentialFile(settingsDir2, connection) {
29653
30055
  const file2 = controlPlaneCredentialPath(settingsDir2);
29654
30056
  let raw;
29655
- const gate = repairOrRefuseMode(file2);
29656
- if (gate === "absent") return { usable: false, reason: "absent" };
29657
- if (gate === "untrusted") return { usable: false, reason: "untrusted-file" };
30057
+ const gate2 = repairOrRefuseMode(file2);
30058
+ if (gate2 === "absent") return { usable: false, reason: "absent" };
30059
+ if (gate2 === "untrusted") return { usable: false, reason: "untrusted-file" };
29658
30060
  try {
29659
30061
  raw = readFileSync5(file2, "utf8");
29660
30062
  } catch (err) {
@@ -36134,7 +36536,10 @@ var SqliteResolutionsRepository = class {
36134
36536
  * Insert many dispositions as ONE transaction — all of them or none.
36135
36537
  *
36136
36538
  * A dashboard dismissal closes every open finding of a rule, which is one
36137
- * write per key; run loose, a fault partway leaves half a rule closed with
36539
+ * write per key. It reaches this through
36540
+ * `LocalDatabase.dismissOpenFindingsForRule`, which calls it inside the
36541
+ * transaction that selected the keys, so there it runs as a SAVEPOINT of
36542
+ * that transaction. Run loose, a fault partway leaves half a rule closed with
36138
36543
  * nothing recording that the other half was meant to be. The caller then has
36139
36544
  * no way to tell a partial run from a complete one, because the card it
36140
36545
  * refreshes into just shows a smaller number either way.
@@ -36354,6 +36759,7 @@ function toSighting(row) {
36354
36759
  var SELECT_COLUMNS = `
36355
36760
  pointer_id AS pointerId,
36356
36761
  value_fingerprint AS valueFingerprint,
36762
+ value_identity_fingerprint AS valueIdentityFingerprint,
36357
36763
  fingerprint_key_version AS fingerprintKeyVersion,
36358
36764
  key_version AS keyVersion,
36359
36765
  format_version AS formatVersion,
@@ -36378,13 +36784,13 @@ var SqliteSecretVaultRepository = class {
36378
36784
  this.db = db;
36379
36785
  this.insertStmt = db.prepare(
36380
36786
  `INSERT INTO secret_vault (
36381
- pointer_id, value_fingerprint, fingerprint_key_version, key_version,
36382
- format_version, category, rule_id, masked_match, provider,
36787
+ pointer_id, value_fingerprint, value_identity_fingerprint,
36788
+ fingerprint_key_version, key_version, format_version, category, rule_id, masked_match, provider,
36383
36789
  ciphertext, nonce, auth_tag,
36384
36790
  user_authorized, occurrence_count, first_seen, last_seen
36385
36791
  ) VALUES (
36386
- :pointerId, :valueFingerprint, :fingerprintKeyVersion, :keyVersion,
36387
- :formatVersion, :category, :ruleId, :maskedMatch, :provider,
36792
+ :pointerId, :valueFingerprint, :valueIdentityFingerprint,
36793
+ :fingerprintKeyVersion, :keyVersion, :formatVersion, :category, :ruleId, :maskedMatch, :provider,
36388
36794
  :ciphertext, :nonce, :authTag,
36389
36795
  :userAuthorized, 1, :now, :now
36390
36796
  )`
@@ -36409,7 +36815,13 @@ var SqliteSecretVaultRepository = class {
36409
36815
  );
36410
36816
  this.refreshFingerprintStmt = db.prepare(
36411
36817
  `UPDATE secret_vault
36412
- SET value_fingerprint = :valueFingerprint, fingerprint_key_version = :fingerprintKeyVersion
36818
+ SET value_fingerprint = :valueFingerprint,
36819
+ value_identity_fingerprint = :valueIdentityFingerprint,
36820
+ fingerprint_key_version = :fingerprintKeyVersion
36821
+ WHERE pointer_id = :pointerId`
36822
+ );
36823
+ this.setIdentityStmt = db.prepare(
36824
+ `UPDATE secret_vault SET value_identity_fingerprint = :valueIdentityFingerprint
36413
36825
  WHERE pointer_id = :pointerId`
36414
36826
  );
36415
36827
  this.deleteByPointerStmt = db.prepare(`DELETE FROM secret_vault WHERE pointer_id = :pointerId`);
@@ -36426,6 +36838,7 @@ var SqliteSecretVaultRepository = class {
36426
36838
  listStmt;
36427
36839
  replaceCiphertextStmt;
36428
36840
  refreshFingerprintStmt;
36841
+ setIdentityStmt;
36429
36842
  deleteByPointerStmt;
36430
36843
  derefStmt;
36431
36844
  /**
@@ -36456,6 +36869,7 @@ var SqliteSecretVaultRepository = class {
36456
36869
  bindParams({
36457
36870
  pointerId: input2.pointerId,
36458
36871
  valueFingerprint: input2.valueFingerprint,
36872
+ valueIdentityFingerprint: input2.valueIdentityFingerprint,
36459
36873
  fingerprintKeyVersion: input2.fingerprintKeyVersion,
36460
36874
  keyVersion: input2.keyVersion,
36461
36875
  formatVersion: input2.formatVersion ?? POINTER_FORMAT_VERSION,
@@ -36517,7 +36931,15 @@ var SqliteSecretVaultRepository = class {
36517
36931
  replaceCiphertext(pointerId, next) {
36518
36932
  this.replaceCiphertextStmt.run({ pointerId, ...next });
36519
36933
  }
36520
- /** Re-derive an entry's fingerprint under a new fingerprint-key epoch. */
36934
+ /**
36935
+ * Correct an entry's identity fingerprint in place, leaving its exact
36936
+ * fingerprint and key epoch alone. For a row whose identity column still holds
36937
+ * the exact value copied in by the migration that added it.
36938
+ */
36939
+ setIdentityFingerprint(pointerId, valueIdentityFingerprint) {
36940
+ this.setIdentityStmt.run({ pointerId, valueIdentityFingerprint });
36941
+ }
36942
+ /** Re-derive an entry's fingerprints under a new fingerprint-key epoch. */
36521
36943
  refreshFingerprint(pointerId, next) {
36522
36944
  this.refreshFingerprintStmt.run({ pointerId, ...next });
36523
36945
  }
@@ -36648,7 +37070,7 @@ var SqliteSecretVaultRepository = class {
36648
37070
  `SELECT ${INVENTORY_COLUMNS},
36649
37071
  (SELECT e.id FROM exceptions e
36650
37072
  WHERE e.rule_id = v.rule_id
36651
- AND e.value_fingerprint = v.value_fingerprint
37073
+ AND e.value_fingerprint = v.value_identity_fingerprint
36652
37074
  AND e.key_version = v.fingerprint_key_version
36653
37075
  AND ${ACTIVE_REVEAL_GRANT_PREDICATE}
36654
37076
  LIMIT 1) AS grant_id
@@ -36691,7 +37113,7 @@ var SqliteSecretVaultRepository = class {
36691
37113
  `SELECT ${INVENTORY_COLUMNS},
36692
37114
  (SELECT e.id FROM exceptions e
36693
37115
  WHERE e.rule_id = v.rule_id
36694
- AND e.value_fingerprint = v.value_fingerprint
37116
+ AND e.value_fingerprint = v.value_identity_fingerprint
36695
37117
  AND e.key_version = v.fingerprint_key_version
36696
37118
  AND ${ACTIVE_REVEAL_GRANT_PREDICATE}
36697
37119
  LIMIT 1) AS grant_id
@@ -36795,6 +37217,18 @@ var OPEN_AT_REST_FINDINGS_SQL = `FROM inspection_findings f
36795
37217
  OR latest.status IS NULL
36796
37218
  OR latest.status NOT IN ('resolved', 'dismissed')
36797
37219
  )`;
37220
+ function selectOpenFindingKeysForRule(db, ruleId) {
37221
+ const rows = allRows(
37222
+ db.prepare(
37223
+ `SELECT DISTINCT f.finding_key AS finding_key
37224
+ ${OPEN_AT_REST_FINDINGS_SQL}
37225
+ AND d.rule_id = :ruleId
37226
+ AND f.finding_key IS NOT NULL`
37227
+ ),
37228
+ { ruleId }
37229
+ );
37230
+ return rows.map((r) => r.finding_key);
37231
+ }
36798
37232
  var SEVERITIES = ["critical", "high", "medium", "low"];
36799
37233
  var ACTION_TO_KIND = {
36800
37234
  block: "blocked",
@@ -36851,16 +37285,16 @@ var SqliteSecurityRepository = class {
36851
37285
  // findings are caught only once their latest disposition is resolved,
36852
37286
  // otherwise they are open-at-rest.
36853
37287
  //
36854
- // NOTE for future manual-resolution writers: only latest status
36855
- // 'resolved' counts as caught above. When acknowledged/dismissed/
36856
- // false-positive manual dispositions land, this must keep filtering by
36857
- // status/method — 'acknowledged' is accepted risk, not a fix, and must NOT
36858
- // be bucketed as caught alongside 'resolved'.
37288
+ // Only latest status 'resolved' counts as caught above. 'dismissed' is its
37289
+ // own bucket: a judgement rather than a fix, so it is neither caught nor
37290
+ // needing remediation, and stays countable. A further manual disposition
37291
+ // (acknowledged, false-positive) must be placed deliberately — 'acknowledged'
37292
+ // is accepted risk, not a fix, and must NOT be bucketed as caught.
36859
37293
  //
36860
37294
  // Legacy at-rest findings from pre-branch scans carry finding_key = NULL —
36861
37295
  // the resolution lifecycle is keyed by finding_key, so it can never attach a
36862
37296
  // disposition to (or clear) one of these on re-scan. They are excluded from
36863
- // both caught and openAtRest (untracked, not "needs remediation forever"),
37297
+ // all three buckets (untracked, not "needs remediation forever"),
36864
37298
  // but still counted in total/count below — this keeps this predicate
36865
37299
  // consistent with SqliteResolutionsRepository.openAtRestKeysForPath, which
36866
37300
  // already filters `finding_key IS NOT NULL`.
@@ -36883,12 +37317,25 @@ var SqliteSecurityRepository = class {
36883
37317
  WHEN latest.status = 'resolved' THEN 1
36884
37318
  ELSE 0
36885
37319
  END) AS caught,
37320
+ SUM(CASE WHEN e.event_type != 'code_change' THEN 1 ELSE 0 END) AS handled,
37321
+ SUM(CASE
37322
+ WHEN e.event_type = 'code_change'
37323
+ AND f.finding_key IS NOT NULL
37324
+ AND latest.status = 'resolved' THEN 1
37325
+ ELSE 0
37326
+ END) AS resolved,
36886
37327
  SUM(CASE
36887
37328
  WHEN e.event_type = 'code_change'
36888
37329
  AND f.finding_key IS NOT NULL
36889
- AND (latest.status IS NULL OR latest.status != 'resolved') THEN 1
37330
+ AND (latest.status IS NULL
37331
+ OR latest.status NOT IN ('resolved', 'dismissed')) THEN 1
37332
+ ELSE 0
37333
+ END) AS open_at_rest,
37334
+ SUM(CASE
37335
+ WHEN e.event_type = 'code_change'
37336
+ AND latest.status = 'dismissed' THEN 1
36890
37337
  ELSE 0
36891
- END) AS open_at_rest
37338
+ END) AS dismissed
36892
37339
  FROM inspection_findings f
36893
37340
  JOIN audit_events e INDEXED BY idx_audit_capture_rollup ON e.id = f.audit_event_id
36894
37341
  JOIN inspection_definitions d ON d.id = f.inspection_definition_id
@@ -36903,11 +37350,15 @@ var SqliteSecurityRepository = class {
36903
37350
  severity,
36904
37351
  count: byRow.get(severity)?.count ?? 0,
36905
37352
  caught: byRow.get(severity)?.caught ?? 0,
36906
- openAtRest: byRow.get(severity)?.open_at_rest ?? 0
37353
+ handled: byRow.get(severity)?.handled ?? 0,
37354
+ resolved: byRow.get(severity)?.resolved ?? 0,
37355
+ openAtRest: byRow.get(severity)?.open_at_rest ?? 0,
37356
+ dismissed: byRow.get(severity)?.dismissed ?? 0
36907
37357
  }));
36908
37358
  const total = bySeverity.reduce((sum, s) => sum + s.count, 0);
36909
37359
  const needsRemediation = bySeverity.reduce((sum, s) => sum + s.openAtRest, 0);
36910
- return Promise.resolve({ total, needsRemediation, bySeverity });
37360
+ const dismissed = bySeverity.reduce((sum, s) => sum + s.dismissed, 0);
37361
+ return Promise.resolve({ total, needsRemediation, dismissed, bySeverity });
36911
37362
  }
36912
37363
  // Range is echoed but does not change the result today — coverage is a constant
36913
37364
  // business fact (see SCAN_COVERAGE), not a measured per-window metric. Order
@@ -37224,10 +37675,10 @@ var SqliteSecurityRepository = class {
37224
37675
  * machine, and the second reported "no recommendations" over live exposure.
37225
37676
  *
37226
37677
  * `open` mirrors `deriveFindingStatus` — at-rest, minus resolved and dismissed —
37227
- * so a row's count is exactly what `?status=open&type=<rule>` returns. Note that
37228
- * is NOT `severitySummary`'s `openAtRest`, which keeps dismissed findings (a
37229
- * dismissal is a judgement, not a remediation) and drops untracked legacy rows.
37230
- * The two answer different questions and only this one has to match a link.
37678
+ * so a row's count is exactly what `?status=open&type=<rule>` returns. It
37679
+ * differs from `severitySummary`'s `openAtRest` only in including untracked
37680
+ * legacy rows, which that bucket leaves out; dismissed is excluded from both.
37681
+ * Only this one has to match a link.
37231
37682
  *
37232
37683
  * Aggregated in SQL: the result is O(distinct rule × category × severity), so a
37233
37684
  * whole-store scope costs a grouped scan rather than a row per finding.
@@ -37255,6 +37706,8 @@ var SqliteSecurityRepository = class {
37255
37706
  /**
37256
37707
  * The distinct `finding_key`s behind ONE rule's {@link recommendationInputs}
37257
37708
  * tally — what a dashboard dismissal of that row writes a disposition for.
37709
+ * The dismissal itself does not call this: it reads the same set through
37710
+ * {@link selectOpenFindingKeysForRule}, inside its own write transaction.
37258
37711
  *
37259
37712
  * It shares {@link OPEN_AT_REST_FINDINGS_SQL} with the count rather than
37260
37713
  * restating the predicate, because a dismissal has to act on exactly the set
@@ -37271,16 +37724,7 @@ var SqliteSecurityRepository = class {
37271
37724
  * this set SMALLER than the tally, never larger.
37272
37725
  */
37273
37726
  openFindingKeysForRule(ruleId) {
37274
- const rows = allRows(
37275
- this.db.prepare(
37276
- `SELECT DISTINCT f.finding_key AS finding_key
37277
- ${OPEN_AT_REST_FINDINGS_SQL}
37278
- AND d.rule_id = :ruleId
37279
- AND f.finding_key IS NOT NULL`
37280
- ),
37281
- { ruleId }
37282
- );
37283
- return Promise.resolve(rows.map((r) => r.finding_key));
37727
+ return Promise.resolve(selectOpenFindingKeysForRule(this.db, ruleId));
37284
37728
  }
37285
37729
  // Findings whose parent event occurred in [fromMs, toMs), with the parent's
37286
37730
  // epoch-millis timestamp. started_at is an INTEGER column, so the bounds stay
@@ -38326,6 +38770,31 @@ function openLocalDatabase(dir, options = {}) {
38326
38770
  );
38327
38771
  });
38328
38772
  }
38773
+ function dismissOpenFindingsForRule(ruleId, disposition) {
38774
+ let dismissed = 0;
38775
+ withTransaction(
38776
+ db,
38777
+ () => {
38778
+ const keys = selectOpenFindingKeysForRule(db, ruleId);
38779
+ resolutions.insertResolutions(
38780
+ keys.map((findingKey) => ({
38781
+ findingKey,
38782
+ status: "dismissed",
38783
+ method: disposition.method,
38784
+ resolvedAt: disposition.resolvedAt,
38785
+ evidence: disposition.evidence
38786
+ }))
38787
+ );
38788
+ dismissed = keys.length;
38789
+ },
38790
+ // IMMEDIATE takes the write lock at BEGIN, before the select, which is
38791
+ // what keeps a concurrent resolve out of the gap. It also makes waiting
38792
+ // on a busy writer an ordinary busy_timeout wait rather than a
38793
+ // read-to-write upgrade SQLite refuses to retry.
38794
+ "IMMEDIATE"
38795
+ );
38796
+ return dismissed;
38797
+ }
38329
38798
  function recordCapture(event, detected) {
38330
38799
  failOpenTransaction(db, () => {
38331
38800
  const sessionId = event.metadata?.sessionId;
@@ -38509,6 +38978,7 @@ function openLocalDatabase(dir, options = {}) {
38509
38978
  inspectionDefinitions,
38510
38979
  inspectionFindings,
38511
38980
  recordCapture,
38981
+ dismissOpenFindingsForRule,
38512
38982
  markCaptureDelivered,
38513
38983
  markCaptureOwed,
38514
38984
  markAuditEventsDelivered,
@@ -38738,6 +39208,9 @@ function rotateFingerprintKey(dataDir2) {
38738
39208
  });
38739
39209
  }
38740
39210
  function fingerprintValue(key, raw) {
39211
+ return exactFingerprintValue(key, stripInvisiblePadding(raw));
39212
+ }
39213
+ function exactFingerprintValue(key, raw) {
38741
39214
  return createHmac("sha256", key.material).update(raw, "utf8").digest("hex");
38742
39215
  }
38743
39216
  function isCurrentKeyVersion(key, keyVersion) {
@@ -39581,10 +40054,14 @@ var SecretVault = class {
39581
40054
  async tokenize(raw, meta4, fingerprintKey) {
39582
40055
  if (!this.#isConsented()) return CONSENT_ABSENT;
39583
40056
  const fpKey = fingerprintKey();
39584
- const valueFingerprint = fingerprintValue(fpKey, raw);
40057
+ const valueFingerprint = exactFingerprintValue(fpKey, raw);
40058
+ const valueIdentityFingerprint = fingerprintValue(fpKey, raw);
39585
40059
  const existing = this.#repo.byValueFingerprint(valueFingerprint);
39586
40060
  const now = this.#now();
39587
40061
  if (existing) {
40062
+ if (existing.valueIdentityFingerprint !== valueIdentityFingerprint) {
40063
+ this.#repo.setIdentityFingerprint(existing.pointerId, valueIdentityFingerprint);
40064
+ }
39588
40065
  this.#repo.upsert(
39589
40066
  {
39590
40067
  ...existing,
@@ -39604,6 +40081,7 @@ var SecretVault = class {
39604
40081
  {
39605
40082
  pointerId: base32Encode(pointerId),
39606
40083
  valueFingerprint,
40084
+ valueIdentityFingerprint,
39607
40085
  fingerprintKeyVersion: fpKey.version,
39608
40086
  keyVersion: version2,
39609
40087
  // Recorded so the row stays OPENABLE if the wire-format constant ever
@@ -39658,7 +40136,7 @@ var SecretVault = class {
39658
40136
  try {
39659
40137
  covered = await verify(grantId, {
39660
40138
  ruleId: row.ruleId,
39661
- valueFingerprint: row.valueFingerprint,
40139
+ valueFingerprint: row.valueIdentityFingerprint,
39662
40140
  fingerprintKeyVersion: row.fingerprintKeyVersion
39663
40141
  });
39664
40142
  } catch {
@@ -39736,16 +40214,36 @@ var SecretVault = class {
39736
40214
  * The raw-free row identity a reveal grant matches on. Deliberately not fed to
39737
40215
  * view surfaces: the keyed fingerprint is a correlation key and must not reach
39738
40216
  * a presentation layer.
40217
+ *
40218
+ * Its `valueFingerprint` is the row's IDENTITY fingerprint (invisible padding
40219
+ * removed) — the space every exception, grant and ledger entry lives in — not
40220
+ * the exact-bytes key the vault dedupes on. A padded value and its clean twin
40221
+ * are two rows with one identity, so one grant covers both.
40222
+ *
40223
+ * Residual: a row written before the identity column existed holds its exact
40224
+ * fingerprint there until the value is next detected or the fingerprint key
40225
+ * rotates. That is the same value for every secret without an invisible
40226
+ * padding character; for a padded one a grant minted from that stale identity
40227
+ * does not match until the row is corrected.
39739
40228
  */
39740
40229
  async resolvePointerIdentity(token) {
39741
40230
  const row = await this.#rowFor(token);
39742
40231
  if (!row) return null;
39743
40232
  return {
39744
40233
  ruleId: row.ruleId,
39745
- valueFingerprint: row.valueFingerprint,
40234
+ valueFingerprint: row.valueIdentityFingerprint,
39746
40235
  fingerprintKeyVersion: row.fingerprintKeyVersion
39747
40236
  };
39748
40237
  }
40238
+ /**
40239
+ * The id of the vault row a pointer verifies against, or null when the vault
40240
+ * cannot identify it. Audit-free like `resolvePointerIdentity`. For callers
40241
+ * that must tell two rows apart even when they share an identity fingerprint.
40242
+ */
40243
+ async resolvePointerRowId(token) {
40244
+ const row = await this.#rowFor(token);
40245
+ return row ? row.pointerId : null;
40246
+ }
39749
40247
  /**
39750
40248
  * Mint the next vault key epoch and re-encrypt every entry under it. Pointers
39751
40249
  * already emitted keep verifying: their tag is checked against the historical
@@ -39809,6 +40307,9 @@ var SecretVault = class {
39809
40307
  * because the raw values are gone — the vault still holds the values, so
39810
40308
  * determinism, dedup, and every outstanding pointer survive the rotation.
39811
40309
  *
40310
+ * Re-derives BOTH fingerprints (the exact dedupe key and the identity), which
40311
+ * also corrects an identity column still holding a pre-migration exact value.
40312
+ *
39812
40313
  * Every fingerprint-key rotation must run this: a row left at the old epoch
39813
40314
  * still resolves, but the same value detected again fingerprints under the
39814
40315
  * NEW key, misses the dedup lookup, and mints a second row and a second
@@ -39826,7 +40327,8 @@ var SecretVault = class {
39826
40327
  const raw = await this.#openRow(row);
39827
40328
  if (raw === null) continue;
39828
40329
  this.#repo.refreshFingerprint(row.pointerId, {
39829
- valueFingerprint: fingerprintValue(next, raw),
40330
+ valueFingerprint: exactFingerprintValue(next, raw),
40331
+ valueIdentityFingerprint: fingerprintValue(next, raw),
39830
40332
  fingerprintKeyVersion: next.version
39831
40333
  });
39832
40334
  refreshed += 1;
@@ -42901,75 +43403,6 @@ ${lines.join("\n")}
42901
43403
  if (!cache || isStale(cache)) triggerBackgroundRefresh(home);
42902
43404
  }
42903
43405
 
42904
- // ../packages/local-ops/src/update-render.ts
42905
- function pinNotes(report) {
42906
- const notes = [];
42907
- for (const s of report.statuses) {
42908
- const pin = s.marketplacePin;
42909
- if (!pin) continue;
42910
- if (pin.range !== void 0) {
42911
- const npmPart = pin.npmLatest !== null ? ` npm has v${pin.npmLatest}.` : "";
42912
- notes.push(
42913
- ` ${s.name}: the ${pin.marketplace} marketplace pins ${pin.range}, which the host resolves within \u2014 not a single version this report can compare.${npmPart}`
42914
- );
42915
- continue;
42916
- }
42917
- if (!pin.npmAhead || s.latest === null || pin.npmLatest === null) continue;
42918
- notes.push(
42919
- ` ${s.name}: the ${pin.marketplace} marketplace pins v${s.latest}. npm has v${pin.npmLatest}, which this machine cannot install until that marketplace moves.`
42920
- );
42921
- }
42922
- return notes;
42923
- }
42924
- function statusLabel(s) {
42925
- if (s.installed === null || s.latest === null) return "unknown";
42926
- return s.updateAvailable ? "update available" : "up to date";
42927
- }
42928
- function channelCell(s) {
42929
- return s.channel === void 0 || s.channel === RELEASE_CHANNEL.Stable ? "" : s.channel;
42930
- }
42931
- function renderReport(report) {
42932
- const rows = report.statuses.map((s) => ({
42933
- name: s.name,
42934
- installed: s.installed ?? "\u2014",
42935
- latest: s.latest ?? "unknown",
42936
- channel: channelCell(s),
42937
- status: statusLabel(s)
42938
- }));
42939
- const nameW = Math.max(9, ...rows.map((r) => r.name.length));
42940
- const instW = Math.max(9, ...rows.map((r) => r.installed.length));
42941
- const latW = Math.max(6, ...rows.map((r) => r.latest.length));
42942
- const chanW = rows.some((r) => r.channel !== "") ? Math.max(7, ...rows.map((r) => r.channel.length)) : 0;
42943
- const chanCol = (value) => chanW === 0 ? "" : `${value.padEnd(chanW)} `;
42944
- const lines = [];
42945
- lines.push(
42946
- ` ${"Component".padEnd(nameW)} ${"Installed".padEnd(instW)} ${"Latest".padEnd(latW)} ${chanCol("Channel")}Status`
42947
- );
42948
- for (const r of rows) {
42949
- lines.push(
42950
- ` ${r.name.padEnd(nameW)} ${r.installed.padEnd(instW)} ${r.latest.padEnd(latW)} ${chanCol(r.channel)}${r.status}`
42951
- );
42952
- }
42953
- const notes = pinNotes(report);
42954
- if (notes.length > 0) {
42955
- lines.push("");
42956
- lines.push(" Pinned by a marketplace:");
42957
- lines.push(...notes);
42958
- }
42959
- if (report.availablePlugins.length > 0) {
42960
- lines.push("");
42961
- lines.push(" Available plugins (not installed):");
42962
- for (const p of report.availablePlugins) {
42963
- const version2 = p.latest ? ` v${p.latest}` : "";
42964
- lines.push(` ${p.name} (${p.id})${version2} \u2014 install: aka plugins install ${p.id}`);
42965
- }
42966
- }
42967
- return lines.join("\n");
42968
- }
42969
- function outdated(report) {
42970
- return report.statuses.filter((s) => s.updateAvailable);
42971
- }
42972
-
42973
43406
  // src/command-manifest.ts
42974
43407
  var COMMAND_SPECS = [
42975
43408
  { name: "init", summary: "Scaffold ~/.aka (settings + local database)" },
@@ -43166,7 +43599,7 @@ async function send(options) {
43166
43599
  }
43167
43600
  }
43168
43601
  };
43169
- return new Promise((resolve8, reject) => {
43602
+ return new Promise((resolve9, reject) => {
43170
43603
  let settled = false;
43171
43604
  const fail = (reason, status) => {
43172
43605
  if (settled) return;
@@ -43192,7 +43625,7 @@ async function send(options) {
43192
43625
  res.on("end", () => {
43193
43626
  if (settled) return;
43194
43627
  settled = true;
43195
- resolve8({
43628
+ resolve9({
43196
43629
  status: res.statusCode ?? 0,
43197
43630
  headers: res.headers,
43198
43631
  body: Buffer.concat(chunks).toString("utf8")
@@ -43462,6 +43895,9 @@ function createSharesSender(timeoutMs = SHARES_FORWARD_TIMEOUT_MS) {
43462
43895
  };
43463
43896
  }
43464
43897
 
43898
+ // ../packages/plugin-runtime/src/attached/with-timeout.ts
43899
+ var REQUEST_TIMEOUT_MS = 2e3;
43900
+
43465
43901
  // ../packages/plugin-runtime/src/attached/forward-drops.ts
43466
43902
  import { readFileSync as readFileSync23 } from "fs";
43467
43903
  import { join as join31 } from "path";
@@ -44162,13 +44598,18 @@ import { spawn as spawn3 } from "child_process";
44162
44598
  import { fileURLToPath as fileURLToPath3 } from "url";
44163
44599
  var HISTORY_SYNC_THROTTLE_MS = 5 * 60 * 1e3;
44164
44600
 
44601
+ // ../packages/plugin-runtime/src/attached/install-record.ts
44602
+ import { readFile as readFile2, stat } from "fs/promises";
44603
+ import { basename as basename7, dirname as dirname9, join as join33, resolve as resolve5 } from "path";
44604
+
44165
44605
  // ../packages/plugin-runtime/src/attached/plugin-block.ts
44166
44606
  import { readFileSync as readFileSync24 } from "fs";
44607
+ var INSTALL_RECORD_READ_TIMEOUT_MS = REQUEST_TIMEOUT_MS / 2;
44167
44608
 
44168
44609
  // ../packages/plugin-runtime/src/attached/policy-store.ts
44169
44610
  import { randomUUID as randomUUID17 } from "crypto";
44170
- import { readFile as readFile2, rm, writeFile as writeFile2 } from "fs/promises";
44171
- import { join as join33 } from "path";
44611
+ import { readFile as readFile3, rm, writeFile as writeFile2 } from "fs/promises";
44612
+ import { join as join34 } from "path";
44172
44613
 
44173
44614
  // ../packages/plugin-runtime/src/attached/atomic-publish.ts
44174
44615
  import { rename as rename2 } from "fs/promises";
@@ -44176,11 +44617,11 @@ var RETRYABLE = /* @__PURE__ */ new Set(["EPERM", "EACCES", "EBUSY"]);
44176
44617
  var IMMEDIATE_RETRIES = 8;
44177
44618
  var TIMED_RETRIES = 4;
44178
44619
  var ATTEMPTS = 1 + IMMEDIATE_RETRIES + TIMED_RETRIES;
44179
- var delay = (ms) => new Promise((resolve8) => {
44180
- setTimeout(resolve8, ms);
44620
+ var delay = (ms) => new Promise((resolve9) => {
44621
+ setTimeout(resolve9, ms);
44181
44622
  });
44182
- var yieldToLoop = () => new Promise((resolve8) => {
44183
- setImmediate(resolve8);
44623
+ var yieldToLoop = () => new Promise((resolve9) => {
44624
+ setImmediate(resolve9);
44184
44625
  });
44185
44626
  async function publishByRename(tmp, file2, move = rename2) {
44186
44627
  for (let attempt = 1; ; attempt += 1) {
@@ -44197,10 +44638,10 @@ async function publishByRename(tmp, file2, move = rename2) {
44197
44638
 
44198
44639
  // ../packages/plugin-runtime/src/attached/policy-store.ts
44199
44640
  function createPolicyStore(dir = dataDir()) {
44200
- const file2 = join33(dir, "policy-cache.json");
44641
+ const file2 = join34(dir, "policy-cache.json");
44201
44642
  async function read() {
44202
44643
  try {
44203
- const raw = await readFile2(file2, "utf8");
44644
+ const raw = await readFile3(file2, "utf8");
44204
44645
  const parsed2 = JSON.parse(raw);
44205
44646
  if (typeof parsed2 !== "object" || parsed2 === null) return null;
44206
44647
  const record2 = parsed2;
@@ -44222,7 +44663,7 @@ function createPolicyStore(dir = dataDir()) {
44222
44663
  }
44223
44664
  async function priorRecord() {
44224
44665
  try {
44225
- const parsed2 = JSON.parse(await readFile2(file2, "utf8"));
44666
+ const parsed2 = JSON.parse(await readFile3(file2, "utf8"));
44226
44667
  return typeof parsed2 === "object" && parsed2 !== null ? parsed2 : null;
44227
44668
  } catch {
44228
44669
  return null;
@@ -44268,7 +44709,7 @@ function createPolicyStore(dir = dataDir()) {
44268
44709
 
44269
44710
  // ../packages/plugin-runtime/src/attached/posture-report-state.ts
44270
44711
  import { readFileSync as readFileSync25 } from "fs";
44271
- import { join as join34 } from "path";
44712
+ import { join as join35 } from "path";
44272
44713
  var POSTURE_REPORT_STATE_FILENAME = ATTACHED_POSTURE_REPORT_FILENAME;
44273
44714
  var OUTCOME_KEYS = {
44274
44715
  ok: true,
@@ -44282,7 +44723,7 @@ var OUTCOME_KEYS = {
44282
44723
  };
44283
44724
  var OUTCOMES2 = new Set(Object.keys(OUTCOME_KEYS));
44284
44725
  function postureReportStatePath(dataDir2) {
44285
- return join34(dataDir2, POSTURE_REPORT_STATE_FILENAME);
44726
+ return join35(dataDir2, POSTURE_REPORT_STATE_FILENAME);
44286
44727
  }
44287
44728
  function readPostureReportState(dataDir2) {
44288
44729
  try {
@@ -44306,12 +44747,12 @@ import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
44306
44747
 
44307
44748
  // ../packages/plugin-runtime/src/attached/posture-store.ts
44308
44749
  import { randomUUID as randomUUID18 } from "crypto";
44309
- import { readFile as readFile3, rm as rm2, writeFile as writeFile3 } from "fs/promises";
44310
- import { join as join35 } from "path";
44750
+ import { readFile as readFile4, rm as rm2, writeFile as writeFile3 } from "fs/promises";
44751
+ import { join as join36 } from "path";
44311
44752
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
44312
44753
  function createPostureStore(dir = settingsDir(), legacyDir) {
44313
- const file2 = join35(dir, "posture-state.json");
44314
- const legacyFile = legacyDir === void 0 ? null : join35(legacyDir, "posture-state.json");
44754
+ const file2 = join36(dir, "posture-state.json");
44755
+ const legacyFile = legacyDir === void 0 ? null : join36(legacyDir, "posture-state.json");
44315
44756
  async function persist(state) {
44316
44757
  await ensureDataDir(dir);
44317
44758
  const tmp = `${file2}.${randomUUID18()}.tmp`;
@@ -44326,7 +44767,7 @@ function createPostureStore(dir = settingsDir(), legacyDir) {
44326
44767
  async function readFrom(path) {
44327
44768
  let raw;
44328
44769
  try {
44329
- raw = await readFile3(path, "utf8");
44770
+ raw = await readFile4(path, "utf8");
44330
44771
  } catch (err) {
44331
44772
  const code = err.code;
44332
44773
  if (code === "ENOENT" || code === "ENOTDIR") return null;
@@ -44384,7 +44825,7 @@ async function readDeviceIdentity(dir) {
44384
44825
 
44385
44826
  // ../packages/plugin-runtime/src/attached/sync-state.ts
44386
44827
  import { readFileSync as readFileSync26 } from "fs";
44387
- import { join as join36 } from "path";
44828
+ import { join as join37 } from "path";
44388
44829
  var SYNC_STATE_FILENAME = ATTACHED_SYNC_STATE_FILENAME;
44389
44830
  var OUTCOMES3 = /* @__PURE__ */ new Set([
44390
44831
  "ok",
@@ -44395,7 +44836,7 @@ var OUTCOMES3 = /* @__PURE__ */ new Set([
44395
44836
  "invalid-bundle"
44396
44837
  ]);
44397
44838
  function syncStatePath(dataDir2) {
44398
- return join36(dataDir2, SYNC_STATE_FILENAME);
44839
+ return join37(dataDir2, SYNC_STATE_FILENAME);
44399
44840
  }
44400
44841
  function readSyncState(dataDir2) {
44401
44842
  try {
@@ -44630,10 +45071,10 @@ import { randomUUID as randomUUID20 } from "crypto";
44630
45071
  var EXCEPTION_RETENTION_MS = 90 * 24 * 60 * 60 * 1e3;
44631
45072
 
44632
45073
  // src/lib/args.ts
44633
- import { resolve as resolve5 } from "path";
45074
+ import { resolve as resolve6 } from "path";
44634
45075
  var HOME_OPTION = { home: { type: "string" } };
44635
45076
  function homeBase(home) {
44636
- return home === void 0 ? defaultDataDir() : resolve5(home);
45077
+ return home === void 0 ? defaultDataDir() : resolve6(home);
44637
45078
  }
44638
45079
 
44639
45080
  // src/lib/open-url.ts
@@ -44701,11 +45142,11 @@ function terminalPrompter(io = processIo()) {
44701
45142
  },
44702
45143
  isInteractive: io.input.isTTY && io.output.isTTY,
44703
45144
  ask(question) {
44704
- return new Promise((resolve8) => {
45145
+ return new Promise((resolve9) => {
44705
45146
  const rl = createInterface({ input: io.input, output: io.output });
44706
45147
  rl.question(question, (answer) => {
44707
45148
  rl.close();
44708
- resolve8(answer);
45149
+ resolve9(answer);
44709
45150
  });
44710
45151
  });
44711
45152
  },
@@ -44716,7 +45157,7 @@ function terminalPrompter(io = processIo()) {
44716
45157
  // fatal signals: a security tool must never brick the terminal it was
44717
45158
  // invoked from.
44718
45159
  askHidden(question) {
44719
- return new Promise((resolve8, reject) => {
45160
+ return new Promise((resolve9, reject) => {
44720
45161
  const stdin = io.input;
44721
45162
  io.output.write(question);
44722
45163
  stdin.setRawMode(true);
@@ -44739,7 +45180,7 @@ function terminalPrompter(io = processIo()) {
44739
45180
  restore();
44740
45181
  io.output.write("\n");
44741
45182
  if (err) reject(err);
44742
- else resolve8(state.value);
45183
+ else resolve9(state.value);
44743
45184
  };
44744
45185
  const onError = (err) => {
44745
45186
  finish(err);
@@ -45350,7 +45791,8 @@ function runCheckUpdates(argv) {
45350
45791
  'Could not reach the npm registry, so "Latest" is unknown. Check your\nnetwork connection and try again.\n'
45351
45792
  );
45352
45793
  } else if (ups.length === 0 && report.availablePlugins.length === 0) {
45353
- out.write("Everything is up to date.\n");
45794
+ out.write(`${nothingToApplyLine(report)}
45795
+ `);
45354
45796
  } else if (ups.length > 0) {
45355
45797
  out.write(`${String(ups.length)} update(s) available \u2014 run \`aka update\` to apply.
45356
45798
  `);
@@ -45529,24 +45971,24 @@ import { spawn as spawn7 } from "child_process";
45529
45971
  import { existsSync as existsSync17 } from "fs";
45530
45972
  import { createRequire as createRequire2 } from "module";
45531
45973
  import { createServer } from "net";
45532
- import { dirname as dirname9, join as join37 } from "path";
45974
+ import { dirname as dirname10, join as join38 } from "path";
45533
45975
  import { fileURLToPath as fileURLToPath6, pathToFileURL } from "url";
45534
45976
  import { parseArgs as parseArgs2 } from "util";
45535
45977
  var require3 = createRequire2(import.meta.url);
45536
- var here = dirname9(fileURLToPath6(import.meta.url));
45978
+ var here = dirname10(fileURLToPath6(import.meta.url));
45537
45979
  var BIND_HOST = "127.0.0.1";
45538
45980
  function pkgBase() {
45539
- return isSea() ? dirname9(process.execPath) : join37(here, "..");
45981
+ return isSea() ? dirname10(process.execPath) : join38(here, "..");
45540
45982
  }
45541
45983
  function isPortFree(port) {
45542
- return new Promise((resolve8) => {
45984
+ return new Promise((resolve9) => {
45543
45985
  const probe = createServer();
45544
45986
  probe.once("error", () => {
45545
- resolve8(false);
45987
+ resolve9(false);
45546
45988
  });
45547
45989
  probe.once("listening", () => {
45548
45990
  probe.close(() => {
45549
- resolve8(true);
45991
+ resolve9(true);
45550
45992
  });
45551
45993
  });
45552
45994
  probe.listen(port, BIND_HOST);
@@ -45590,14 +46032,14 @@ async function runDashboard(argv) {
45590
46032
  refreshUpdateMirror(dataDir());
45591
46033
  const base = pkgBase();
45592
46034
  const bundledServer = [
45593
- join37(base, "web-ui", "server.js"),
45594
- join37(base, "web-ui", "web-ui", "server.js")
46035
+ join38(base, "web-ui", "server.js"),
46036
+ join38(base, "web-ui", "web-ui", "server.js")
45595
46037
  ].find((p) => existsSync17(p));
45596
46038
  if (bundledServer) {
45597
46039
  launchStandalone(bundledServer, port, shouldOpen, url2);
45598
46040
  return;
45599
46041
  }
45600
- const webUiDir = dirname9(require3.resolve("@akasecurity/web-ui/package.json"));
46042
+ const webUiDir = dirname10(require3.resolve("@akasecurity/web-ui/package.json"));
45601
46043
  const nextBin = require3.resolve("next/dist/bin/next", { paths: [webUiDir] });
45602
46044
  const startNext = () => {
45603
46045
  const child = spawn7(
@@ -45611,7 +46053,7 @@ async function runDashboard(argv) {
45611
46053
  onReadyOpen(child, shouldOpen, url2, `Starting the AKA dashboard at ${url2}
45612
46054
  `);
45613
46055
  };
45614
- if (existsSync17(join37(webUiDir, ".next", "BUILD_ID"))) {
46056
+ if (existsSync17(join38(webUiDir, ".next", "BUILD_ID"))) {
45615
46057
  startNext();
45616
46058
  return;
45617
46059
  }
@@ -45634,7 +46076,7 @@ function launchStandalone(serverJs, port, shouldOpen, url2) {
45634
46076
  return;
45635
46077
  }
45636
46078
  const child = spawn7(reinvoke.command, reinvoke.args, {
45637
- cwd: dirname9(serverJs),
46079
+ cwd: dirname10(serverJs),
45638
46080
  stdio: ["inherit", "pipe", "inherit"],
45639
46081
  // Inherit the parent env so the child server sees PATH etc.; PORT/HOSTNAME tell
45640
46082
  // Next's standalone server where to bind (its only port input).
@@ -46321,7 +46763,9 @@ async function fingerprintForRule(ruleId, useStdin, dir, io) {
46321
46763
  );
46322
46764
  }
46323
46765
  if (first !== raw) {
46324
- io.out("Note: the grant binds to the exact detected span, not the whole input.\n");
46766
+ io.out(
46767
+ "Note: the grant binds to the detected span (invisible padding ignored), not the whole input.\n"
46768
+ );
46325
46769
  }
46326
46770
  const key = loadOrCreateFingerprintKey(dir);
46327
46771
  const result = {
@@ -46659,7 +47103,7 @@ import { execFileSync as execFileSync3 } from "child_process";
46659
47103
  import { existsSync as existsSync18, mkdirSync as mkdirSync6, readFileSync as readFileSync27, renameSync as renameSync5, writeFileSync as writeFileSync9 } from "fs";
46660
47104
  import { createRequire as createRequire3 } from "module";
46661
47105
  import { homedir as homedir8 } from "os";
46662
- import { dirname as dirname11, isAbsolute as isAbsolute2, join as join39, resolve as resolve6 } from "path";
47106
+ import { dirname as dirname12, isAbsolute as isAbsolute2, join as join40, resolve as resolve7 } from "path";
46663
47107
  import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL2 } from "url";
46664
47108
  import { parseArgs as parseArgs5 } from "util";
46665
47109
 
@@ -46740,7 +47184,7 @@ function parseLauncher(script) {
46740
47184
 
46741
47185
  // src/lib/stable-path.ts
46742
47186
  import { realpathSync as realpathSync6 } from "fs";
46743
- import { basename as basename7, dirname as dirname10, join as join38, relative as relative2 } from "path";
47187
+ import { basename as basename8, dirname as dirname11, join as join39, relative as relative2 } from "path";
46744
47188
  var realpathOrNull = (path) => {
46745
47189
  try {
46746
47190
  return realpathSync6(path);
@@ -46753,23 +47197,23 @@ var INSTALLER_BINROOT = /^aka-(?:darwin|linux|win32)-(?:arm64|x64)$/;
46753
47197
  var INSTALLER_VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
46754
47198
  function layoutLinks(realPath) {
46755
47199
  const links = [];
46756
- let versionDir = dirname10(realPath);
47200
+ let versionDir = dirname11(realPath);
46757
47201
  for (let reach = 1; ; reach++) {
46758
- const parent = dirname10(versionDir);
47202
+ const parent = dirname11(versionDir);
46759
47203
  if (parent === versionDir) break;
46760
- const grandparent = dirname10(parent);
47204
+ const grandparent = dirname11(parent);
46761
47205
  const rest = relative2(versionDir, realPath);
46762
47206
  const add = (link) => {
46763
- links.push({ link, path: join38(link, rest) });
47207
+ links.push({ link, path: join39(link, rest) });
46764
47208
  };
46765
47209
  if (reach <= CURRENT_LINK_REACH) {
46766
- if (INSTALLER_BINROOT.test(basename7(versionDir)) && INSTALLER_VERSION.test(basename7(parent)) && grandparent !== parent) {
46767
- add(join38(grandparent, "current"));
47210
+ if (INSTALLER_BINROOT.test(basename8(versionDir)) && INSTALLER_VERSION.test(basename8(parent)) && grandparent !== parent) {
47211
+ add(join39(grandparent, "current"));
46768
47212
  }
46769
- if (basename7(grandparent) === "apps") add(join38(parent, "current"));
47213
+ if (basename8(grandparent) === "apps") add(join39(parent, "current"));
46770
47214
  }
46771
- if (basename7(grandparent) === "Cellar") {
46772
- add(join38(dirname10(grandparent), "opt", basename7(parent)));
47215
+ if (basename8(grandparent) === "Cellar") {
47216
+ add(join39(dirname11(grandparent), "opt", basename8(parent)));
46773
47217
  }
46774
47218
  versionDir = parent;
46775
47219
  }
@@ -46800,9 +47244,9 @@ function versionPin(path, realpath = realpathOrNull) {
46800
47244
 
46801
47245
  // src/commands/extension.ts
46802
47246
  var require4 = createRequire3(import.meta.url);
46803
- var here2 = dirname11(fileURLToPath7(import.meta.url));
47247
+ var here2 = dirname12(fileURLToPath7(import.meta.url));
46804
47248
  function cliRoot() {
46805
- return isSea() ? dirname11(process.execPath) : join39(here2, "..");
47249
+ return isSea() ? dirname12(process.execPath) : join40(here2, "..");
46806
47250
  }
46807
47251
  var EXTENSION_IDS = [
46808
47252
  // Derived from the "key" in plugins/browser-extension/manifest.json.
@@ -46819,22 +47263,22 @@ function nativeHostManifest(hostPath) {
46819
47263
  };
46820
47264
  }
46821
47265
  function resolveHostScript(root = cliRoot()) {
46822
- const bundled = join39(root, "native-host", "host.js");
47266
+ const bundled = join40(root, "native-host", "host.js");
46823
47267
  if (existsSync18(bundled)) return bundled;
46824
47268
  try {
46825
47269
  const pkgJson = require4.resolve("@akasecurity/plugin-browser-extension/package.json");
46826
- const devBuilt = join39(dirname11(pkgJson), "native-host", "host.js");
47270
+ const devBuilt = join40(dirname12(pkgJson), "native-host", "host.js");
46827
47271
  if (existsSync18(devBuilt)) return devBuilt;
46828
47272
  } catch {
46829
47273
  }
46830
47274
  return null;
46831
47275
  }
46832
47276
  function resolveExtensionDist(root = cliRoot()) {
46833
- const bundled = join39(root, "extension");
47277
+ const bundled = join40(root, "extension");
46834
47278
  if (existsSync18(bundled)) return bundled;
46835
47279
  try {
46836
47280
  const pkgJson = require4.resolve("@akasecurity/plugin-browser-extension/package.json");
46837
- const devDist = join39(dirname11(pkgJson), "dist");
47281
+ const devDist = join40(dirname12(pkgJson), "dist");
46838
47282
  if (existsSync18(devDist)) return devDist;
46839
47283
  } catch {
46840
47284
  }
@@ -46842,7 +47286,7 @@ function resolveExtensionDist(root = cliRoot()) {
46842
47286
  }
46843
47287
  function chromeManifestDir(platform3 = process.platform) {
46844
47288
  if (platform3 === "darwin") {
46845
- return join39(
47289
+ return join40(
46846
47290
  homedir8(),
46847
47291
  "Library",
46848
47292
  "Application Support",
@@ -46852,9 +47296,9 @@ function chromeManifestDir(platform3 = process.platform) {
46852
47296
  );
46853
47297
  }
46854
47298
  if (platform3 === "win32") {
46855
- return join39(homedir8(), ".aka", "native-messaging");
47299
+ return join40(homedir8(), ".aka", "native-messaging");
46856
47300
  }
46857
- return join39(homedir8(), ".config", "google-chrome", "NativeMessagingHosts");
47301
+ return join40(homedir8(), ".config", "google-chrome", "NativeMessagingHosts");
46858
47302
  }
46859
47303
  var NATIVE_HOST_COMMAND = "__native-host";
46860
47304
  function currentRuntime() {
@@ -46866,7 +47310,7 @@ function launcherCommand(hostScript, runtime = currentRuntime()) {
46866
47310
  return [executable, stablePath(hostScript, runtime.realpath)];
46867
47311
  }
46868
47312
  function launcherPath(manifestDir, platform3) {
46869
- return join39(
47313
+ return join40(
46870
47314
  manifestDir,
46871
47315
  platform3 === "win32" ? `${NATIVE_HOST_NAME}.cmd` : `${NATIVE_HOST_NAME}.sh`
46872
47316
  );
@@ -46894,7 +47338,7 @@ async function runNativeHost(hostScript = resolveHostScript()) {
46894
47338
  }
46895
47339
  function hostChildScript(command, sea = isSea(), root = cliRoot()) {
46896
47340
  if (!sea || !isAbsolute2(command) || !command.endsWith(".js")) return null;
46897
- if (resolve6(dirname11(command)) !== resolve6(root, "native-host")) return null;
47341
+ if (resolve7(dirname12(command)) !== resolve7(root, "native-host")) return null;
46898
47342
  return existsSync18(command) ? command : null;
46899
47343
  }
46900
47344
  function windowsRegistryKey() {
@@ -46945,7 +47389,7 @@ function runInstall(manifestDir, hostScript = resolveHostScript(), extensionDist
46945
47389
  const argv = command ?? launcherCommand(hostScript);
46946
47390
  mkdirSync6(manifestDir, { recursive: true });
46947
47391
  const launcher = writeLauncher(manifestDir, argv, process.platform);
46948
- const manifestPath = join39(manifestDir, `${NATIVE_HOST_NAME}.json`);
47392
+ const manifestPath = join40(manifestDir, `${NATIVE_HOST_NAME}.json`);
46949
47393
  const tmp = `${manifestPath}.tmp`;
46950
47394
  writeFileSync9(tmp, `${JSON.stringify(nativeHostManifest(launcher), null, 2)}
46951
47395
  `, {
@@ -47076,7 +47520,7 @@ function registrationFaults(manifestPath) {
47076
47520
  return lines;
47077
47521
  }
47078
47522
  function runStatus2(manifestDir, home) {
47079
- const manifestPath = join39(manifestDir, `${NATIVE_HOST_NAME}.json`);
47523
+ const manifestPath = join40(manifestDir, `${NATIVE_HOST_NAME}.json`);
47080
47524
  if (!existsSync18(manifestPath)) {
47081
47525
  process.stdout.write(
47082
47526
  `native-messaging host: not installed
@@ -47101,7 +47545,7 @@ function runStatus2(manifestDir, home) {
47101
47545
 
47102
47546
  // src/commands/init.ts
47103
47547
  import { existsSync as existsSync20, lstatSync as lstatSync4, readdirSync as readdirSync7, statSync as statSync13 } from "fs";
47104
- import { join as join40 } from "path";
47548
+ import { join as join41 } from "path";
47105
47549
  import * as readline from "readline/promises";
47106
47550
  import { parseArgs as parseArgs7 } from "util";
47107
47551
 
@@ -47132,10 +47576,13 @@ async function listPlugins(argv) {
47132
47576
  const installed = installedAgentPluginVersions();
47133
47577
  const out = process.stdout;
47134
47578
  out.write("Agent plugins (the CLI is an optional hub \u2014 plugins also self-install):\n\n");
47579
+ let anyManaged = false;
47135
47580
  for (const a of AGENT_PLUGINS) {
47136
47581
  const ref = pluginRef(a);
47582
+ const managed = managedPluginInstall(a);
47583
+ if (managed !== null) anyManaged = true;
47137
47584
  const version2 = ref ? installed.get(ref) : void 0;
47138
- const state = version2 ? `installed v${version2}` : active.has(a.sourceTool) ? "active" : "available";
47585
+ const state = managed !== null ? managedState2(managed.version) : version2 ? `installed v${version2}` : active.has(a.sourceTool) ? "active" : "available";
47139
47586
  out.write(` ${a.id.padEnd(16)} ${state.padEnd(16)} ${a.name}
47140
47587
  `);
47141
47588
  out.write(` ${" ".padEnd(16)} ${" ".padEnd(16)} ${a.description}
@@ -47143,6 +47590,15 @@ async function listPlugins(argv) {
47143
47590
  }
47144
47591
  out.write("\nInstall: aka plugins install <agent>\n");
47145
47592
  out.write("Update: aka update (or: aka check-updates)\n");
47593
+ if (anyManaged) {
47594
+ out.write(
47595
+ `Managed: \`aka plugins install\` and \`aka update\` leave a managed plugin alone. ${MANAGED_PLUGIN_ADVICE}
47596
+ `
47597
+ );
47598
+ }
47599
+ }
47600
+ function managedState2(version2) {
47601
+ return version2 !== null ? `managed v${version2}` : "managed";
47146
47602
  }
47147
47603
  async function installPlugin(argv, deps) {
47148
47604
  const { positionals } = parseArgs6({ args: argv, options: HOME_OPTION, allowPositionals: true });
@@ -47159,6 +47615,7 @@ async function installPlugin(argv, deps) {
47159
47615
  process.exitCode = 1;
47160
47616
  return;
47161
47617
  }
47618
+ if (refuseManaged(agent, deps)) return;
47162
47619
  const ref = pluginRef(agent);
47163
47620
  const cliBin = agent.cliBin;
47164
47621
  if (!ref || !cliBin) {
@@ -47205,13 +47662,14 @@ Those protections will be inactive until you update Claude Code to ${required2}
47205
47662
  }
47206
47663
  }
47207
47664
  }
47665
+ if (refuseManaged(agent, deps)) return;
47208
47666
  const plan = manager3.installSpawnPlan(ref, agent.marketplaceSource, agent.marketplace);
47209
47667
  process.stdout.write(
47210
47668
  `Installing ${agent.name} via ${cliBin}, running:
47211
47669
  ` + plan.map((command) => ` ${command}
47212
47670
  `).join("")
47213
47671
  );
47214
- const { ok } = installAgentPlugin(agent.id, "inherit");
47672
+ const { ok, output: output2 } = installAgentPlugin(agent.id, "inherit");
47215
47673
  if (ok) {
47216
47674
  process.stdout.write(
47217
47675
  `
@@ -47220,14 +47678,29 @@ Those protections will be inactive until you update Claude Code to ${required2}
47220
47678
  Run \`aka init\` to scaffold your local store (if you haven't already).
47221
47679
  `
47222
47680
  );
47223
- } else {
47224
- process.stderr.write(
47225
- `
47226
- \u2717 Install failed \u2014 see the output above, or add it in ${agent.name} with \`${recipe.join(" && ")}\`.
47227
- `
47228
- );
47681
+ return;
47682
+ }
47683
+ if (refuseManaged(agent, deps)) return;
47684
+ if (output2 !== "") {
47685
+ process.stderr.write(`
47686
+ \u2717 ${output2}
47687
+ `);
47229
47688
  process.exitCode = 1;
47689
+ return;
47230
47690
  }
47691
+ process.stderr.write(
47692
+ `
47693
+ \u2717 Install failed \u2014 see the output above, or add it in ${agent.name} with \`${recipe.join(" && ")}\`.
47694
+ `
47695
+ );
47696
+ process.exitCode = 1;
47697
+ }
47698
+ function refuseManaged(agent, deps) {
47699
+ if (managedPluginInstall(agent) === null) return false;
47700
+ process.stderr.write(`aka plugins install: ${managedInstallRefusal(agent.name)}
47701
+ `);
47702
+ if (deps.declineIsFailure !== false) process.exitCode = 1;
47703
+ return true;
47231
47704
  }
47232
47705
 
47233
47706
  // src/commands/init.ts
@@ -47238,7 +47711,7 @@ function storeModeTargets(home) {
47238
47711
  try {
47239
47712
  for (const entry of readdirSync7(dir, { withFileTypes: true })) {
47240
47713
  if (entry.name.endsWith(".partial") && !entry.isDirectory()) continue;
47241
- targets.add(join40(dir, entry.name));
47714
+ targets.add(join41(dir, entry.name));
47242
47715
  }
47243
47716
  } catch {
47244
47717
  }
@@ -47320,7 +47793,7 @@ async function runInit(argv) {
47320
47793
  ensureLayoutDirSync(home);
47321
47794
  const settings = settingsDir(home);
47322
47795
  ensureLayoutDirSync(settings);
47323
- const settingsFile = join40(settings, "settings.json");
47796
+ const settingsFile = join41(settings, "settings.json");
47324
47797
  let settingsCreated = false;
47325
47798
  if (!existsSync20(settingsFile)) {
47326
47799
  try {
@@ -47368,6 +47841,7 @@ async function offerPluginInstall(autoYes) {
47368
47841
  const ref = agent ? pluginRef(agent) : void 0;
47369
47842
  if (!agent || !ref) return;
47370
47843
  if (installedPluginVersions().has(ref)) return;
47844
+ if (managedPluginInstall(agent) !== null) return;
47371
47845
  const out = process.stdout;
47372
47846
  if (!autoYes) {
47373
47847
  if (!process.stdin.isTTY) {
@@ -47749,10 +48223,12 @@ Latest findings:
47749
48223
  function renderFindingsSummary(severity) {
47750
48224
  const caught = severity.bySeverity.reduce((sum, s) => sum + (s.caught ?? 0), 0);
47751
48225
  const needsRemediation = severity.needsRemediation ?? 0;
48226
+ const dismissed = severity.dismissed ?? 0;
47752
48227
  const labelWidth = Math.max(
47753
48228
  9,
47754
48229
  ...severity.bySeverity.map((s) => s.severity.length),
47755
- "Needs remediation".length
48230
+ "Needs remediation".length,
48231
+ "Dismissed".length
47756
48232
  );
47757
48233
  const lines = [`Findings: ${String(severity.total)} total`];
47758
48234
  for (const s of severity.bySeverity) {
@@ -47760,6 +48236,7 @@ function renderFindingsSummary(severity) {
47760
48236
  }
47761
48237
  lines.push(` ${"Caught".padEnd(labelWidth)} ${String(caught)}`);
47762
48238
  lines.push(` ${"Needs remediation".padEnd(labelWidth)} ${String(needsRemediation)}`);
48239
+ lines.push(` ${"Dismissed".padEnd(labelWidth)} ${String(dismissed)}`);
47763
48240
  return lines.join("\n");
47764
48241
  }
47765
48242
  var TOP_MODELS = 6;
@@ -48494,11 +48971,11 @@ import * as readline2 from "readline/promises";
48494
48971
  import { parseArgs as parseArgs13 } from "util";
48495
48972
 
48496
48973
  // src/lib/install-origin.ts
48497
- import { dirname as dirname12 } from "path";
48974
+ import { dirname as dirname13 } from "path";
48498
48975
  import { fileURLToPath as fileURLToPath8 } from "url";
48499
48976
  function cliInstallOrigin() {
48500
48977
  try {
48501
- return { moduleDir: dirname12(fileURLToPath8(import.meta.url)) };
48978
+ return { moduleDir: dirname13(fileURLToPath8(import.meta.url)) };
48502
48979
  } catch {
48503
48980
  return { moduleDir: void 0 };
48504
48981
  }
@@ -48565,6 +49042,13 @@ async function runUpdate(argv) {
48565
49042
  process.exitCode = 1;
48566
49043
  return;
48567
49044
  }
49045
+ const targetRow = target && target !== "all" ? report.statuses.find((s) => s.id === target) : void 0;
49046
+ if (targetRow?.managedInstall) {
49047
+ process.stderr.write(`aka update: ${managedUpdateRefusal(targetRow.name)}
49048
+ `);
49049
+ process.exitCode = 1;
49050
+ return;
49051
+ }
48568
49052
  let candidates = outdated(report);
48569
49053
  if (target && target !== "all") candidates = candidates.filter((s) => s.id === target);
48570
49054
  if (candidates.length === 0) {
@@ -48580,7 +49064,8 @@ async function runUpdate(argv) {
48580
49064
  } else {
48581
49065
  out.write(
48582
49066
  target && target !== "all" ? `${target} is already up to date.
48583
- ` : "Everything is up to date.\n"
49067
+ ` : `${nothingToApplyLine(report)}
49068
+ `
48584
49069
  );
48585
49070
  }
48586
49071
  return;
@@ -48632,6 +49117,10 @@ function pluginChannelRefusal(target, channel) {
48632
49117
  `;
48633
49118
  if (!agent || !ref || !agent.cliBin) {
48634
49119
  return `${head} Update ${target} through its host, then re-run \`aka check-updates\`.
49120
+ `;
49121
+ }
49122
+ if (managedPluginInstall(agent) !== null) {
49123
+ return `${head} ${agent.name} is managed by your organization. ${MANAGED_PLUGIN_ADVICE}
48635
49124
  `;
48636
49125
  }
48637
49126
  const recipe = createCliPluginManager(agent.cliBin).updateRecipe(ref, agent.marketplaceSource);
@@ -48673,6 +49162,11 @@ function applyPluginUpdate2(status) {
48673
49162
  const cliBin = agent?.cliBin;
48674
49163
  if (!agent || !ref || !cliBin) {
48675
49164
  process.stderr.write(`\u2717 ${status.name}: no update coordinates in the registry.
49165
+ `);
49166
+ return false;
49167
+ }
49168
+ if (managedPluginInstall(agent) !== null) {
49169
+ process.stderr.write(`\u2717 ${managedUpdateRefusal(status.name)}
48676
49170
  `);
48677
49171
  return false;
48678
49172
  }
@@ -48691,9 +49185,11 @@ function applyPluginUpdate2(status) {
48691
49185
  ` + plan.map((command) => ` ${command}
48692
49186
  `).join("")
48693
49187
  );
48694
- const { ok } = applyPluginUpdate(status.id, "inherit");
49188
+ const { ok, output: output2 } = applyPluginUpdate(status.id, "inherit");
48695
49189
  process.stdout.write(ok ? `\u2713 ${status.name} updated.
48696
49190
  ` : `\u2717 ${status.name} update failed.
49191
+ `);
49192
+ if (!ok && output2 !== "") process.stderr.write(` ${output2}
48697
49193
  `);
48698
49194
  return ok;
48699
49195
  }
@@ -48717,10 +49213,10 @@ import {
48717
49213
  writeFileSync as writeFileSync10
48718
49214
  } from "fs";
48719
49215
  import { homedir as homedir9 } from "os";
48720
- import { basename as basename8, dirname as dirname13, isAbsolute as isAbsolute3, join as join41, relative as relative3, resolve as resolve7 } from "path";
49216
+ import { basename as basename9, dirname as dirname14, isAbsolute as isAbsolute3, join as join42, relative as relative3, resolve as resolve8 } from "path";
48721
49217
  var DEFAULT_MAX_REWRITE_BYTES = 32 * 1024 * 1024;
48722
49218
  function transcriptRoots(userHome) {
48723
- return [join41(userHome ?? homedir9(), ".claude", "projects")];
49219
+ return [join42(userHome ?? homedir9(), ".claude", "projects")];
48724
49220
  }
48725
49221
  function readContainedFile(realPath, maxBytes = DEFAULT_MAX_REWRITE_BYTES) {
48726
49222
  try {
@@ -48744,7 +49240,7 @@ function isWithinRoot(realTarget, root) {
48744
49240
  return rel !== "" && !rel.startsWith("..") && !isAbsolute3(rel);
48745
49241
  }
48746
49242
  function containedRealPath(filePath, roots) {
48747
- const realTarget = realPathOrNull(resolve7(filePath));
49243
+ const realTarget = realPathOrNull(resolve8(filePath));
48748
49244
  if (realTarget === null) return null;
48749
49245
  return roots.some((root) => isWithinRoot(realTarget, root)) ? realTarget : null;
48750
49246
  }
@@ -48761,8 +49257,8 @@ function isProcessAlive(pid) {
48761
49257
  }
48762
49258
  }
48763
49259
  function sweepStrandedTemps(realPath) {
48764
- const dir = dirname13(realPath);
48765
- const prefix = `${basename8(realPath)}.`;
49260
+ const dir = dirname14(realPath);
49261
+ const prefix = `${basename9(realPath)}.`;
48766
49262
  let names;
48767
49263
  try {
48768
49264
  names = readdirSync8(dir);
@@ -48776,7 +49272,7 @@ function sweepStrandedTemps(realPath) {
48776
49272
  const pid = Number(pidPart);
48777
49273
  if (pid !== process.pid && isProcessAlive(pid)) continue;
48778
49274
  try {
48779
- const stranded = join41(dir, name);
49275
+ const stranded = join42(dir, name);
48780
49276
  if (!lstatSync5(stranded).isFile()) continue;
48781
49277
  rmSync9(stranded, { force: true });
48782
49278
  } catch {
@@ -48870,7 +49366,6 @@ function selectOutOfPolicy(rows, ruleActions) {
48870
49366
  }
48871
49367
  selection.outOfPolicy.push({
48872
49368
  pointerId: row.pointerId,
48873
- valueFingerprint: row.valueFingerprint,
48874
49369
  ruleId: row.ruleId,
48875
49370
  action
48876
49371
  });
@@ -48907,12 +49402,12 @@ async function analyseText(text, deps) {
48907
49402
  const tokens = new Set(found);
48908
49403
  let unattributable = 0;
48909
49404
  for (const token of tokens) {
48910
- const identity = await deps.identify(token);
48911
- if (identity === null) {
49405
+ const pointerId = await deps.identify(token);
49406
+ if (pointerId === null) {
48912
49407
  unattributable += 1;
48913
49408
  continue;
48914
49409
  }
48915
- const entry = deps.entryFor(identity.valueFingerprint);
49410
+ const entry = deps.entryFor(pointerId);
48916
49411
  if (entry === void 0) continue;
48917
49412
  hits.set(token, entry);
48918
49413
  }
@@ -49011,7 +49506,7 @@ async function runPrune2(argv, io) {
49011
49506
  `);
49012
49507
  return;
49013
49508
  }
49014
- const byFingerprint = new Map(selection.outOfPolicy.map((e) => [e.valueFingerprint, e]));
49509
+ const byPointerId = new Map(selection.outOfPolicy.map((e) => [e.pointerId, e]));
49015
49510
  const ledger = sightingLedger(db);
49016
49511
  const locations = /* @__PURE__ */ new Set();
49017
49512
  let surfaceSighted = 0;
@@ -49031,8 +49526,8 @@ async function runPrune2(argv, io) {
49031
49526
  isConsented: () => isVaultConsentValid(readWorkspaceSettings(base).vaultConsent)
49032
49527
  });
49033
49528
  const analyse = async (text) => analyseText(text, {
49034
- entryFor: (fingerprint) => byFingerprint.get(fingerprint),
49035
- identify: (token) => vault.resolvePointerIdentity(token)
49529
+ entryFor: (pointerId) => byPointerId.get(pointerId),
49530
+ identify: (token) => vault.resolvePointerRowId(token)
49036
49531
  });
49037
49532
  const reports = [];
49038
49533
  const clearedLocations = /* @__PURE__ */ new Set();