@skillsmith/core 0.8.2 → 0.10.0

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 (347) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/api/client.d.ts.map +1 -1
  4. package/dist/src/api/client.js +6 -0
  5. package/dist/src/api/client.js.map +1 -1
  6. package/dist/src/api/client.test.d.ts +9 -0
  7. package/dist/src/api/client.test.d.ts.map +1 -0
  8. package/dist/src/api/client.test.js +81 -0
  9. package/dist/src/api/client.test.js.map +1 -0
  10. package/dist/src/config/device-identity.d.ts +113 -0
  11. package/dist/src/config/device-identity.d.ts.map +1 -0
  12. package/dist/src/config/device-identity.js +171 -0
  13. package/dist/src/config/device-identity.js.map +1 -0
  14. package/dist/src/config/device-identity.test.d.ts +10 -0
  15. package/dist/src/config/device-identity.test.d.ts.map +1 -0
  16. package/dist/src/config/device-identity.test.js +213 -0
  17. package/dist/src/config/device-identity.test.js.map +1 -0
  18. package/dist/src/config/index.d.ts +9 -0
  19. package/dist/src/config/index.d.ts.map +1 -1
  20. package/dist/src/config/index.js.map +1 -1
  21. package/dist/src/exports/services.d.ts +3 -1
  22. package/dist/src/exports/services.d.ts.map +1 -1
  23. package/dist/src/exports/services.js +11 -1
  24. package/dist/src/exports/services.js.map +1 -1
  25. package/dist/src/index.d.ts +4 -3
  26. package/dist/src/index.d.ts.map +1 -1
  27. package/dist/src/index.js +7 -2
  28. package/dist/src/index.js.map +1 -1
  29. package/dist/src/install/agent-config-merge.json-array.d.ts +29 -0
  30. package/dist/src/install/agent-config-merge.json-array.d.ts.map +1 -0
  31. package/dist/src/install/agent-config-merge.json-array.js +100 -0
  32. package/dist/src/install/agent-config-merge.json-array.js.map +1 -0
  33. package/dist/src/install/agent-config-merge.json.d.ts +37 -0
  34. package/dist/src/install/agent-config-merge.json.d.ts.map +1 -0
  35. package/dist/src/install/agent-config-merge.json.js +134 -0
  36. package/dist/src/install/agent-config-merge.json.js.map +1 -0
  37. package/dist/src/install/agent-config-merge.toml-block.d.ts +48 -0
  38. package/dist/src/install/agent-config-merge.toml-block.d.ts.map +1 -0
  39. package/dist/src/install/agent-config-merge.toml-block.js +107 -0
  40. package/dist/src/install/agent-config-merge.toml-block.js.map +1 -0
  41. package/dist/src/install/agent-config-merge.types.d.ts +87 -0
  42. package/dist/src/install/agent-config-merge.types.d.ts.map +1 -0
  43. package/dist/src/install/agent-config-merge.types.js +83 -0
  44. package/dist/src/install/agent-config-merge.types.js.map +1 -0
  45. package/dist/src/install/agent-config-merge.yaml.d.ts +46 -0
  46. package/dist/src/install/agent-config-merge.yaml.d.ts.map +1 -0
  47. package/dist/src/install/agent-config-merge.yaml.js +133 -0
  48. package/dist/src/install/agent-config-merge.yaml.js.map +1 -0
  49. package/dist/src/install/agent-config-merge.yaml.test.d.ts +2 -0
  50. package/dist/src/install/agent-config-merge.yaml.test.d.ts.map +1 -0
  51. package/dist/src/install/agent-config-merge.yaml.test.js +210 -0
  52. package/dist/src/install/agent-config-merge.yaml.test.js.map +1 -0
  53. package/dist/src/install/agent-harness-targets.d.ts +98 -0
  54. package/dist/src/install/agent-harness-targets.d.ts.map +1 -0
  55. package/dist/src/install/agent-harness-targets.js +154 -0
  56. package/dist/src/install/agent-harness-targets.js.map +1 -0
  57. package/dist/src/install/agent-home-relocate.d.ts +29 -0
  58. package/dist/src/install/agent-home-relocate.d.ts.map +1 -0
  59. package/dist/src/install/agent-home-relocate.js +38 -0
  60. package/dist/src/install/agent-home-relocate.js.map +1 -0
  61. package/dist/src/install/agent-manifest-path-guard.d.ts +55 -0
  62. package/dist/src/install/agent-manifest-path-guard.d.ts.map +1 -0
  63. package/dist/src/install/agent-manifest-path-guard.js +109 -0
  64. package/dist/src/install/agent-manifest-path-guard.js.map +1 -0
  65. package/dist/src/install/agent-manifest-path-guard.test.d.ts +2 -0
  66. package/dist/src/install/agent-manifest-path-guard.test.d.ts.map +1 -0
  67. package/dist/src/install/agent-manifest-path-guard.test.js +72 -0
  68. package/dist/src/install/agent-manifest-path-guard.test.js.map +1 -0
  69. package/dist/src/install/agent-manifest.d.ts +58 -0
  70. package/dist/src/install/agent-manifest.d.ts.map +1 -0
  71. package/dist/src/install/agent-manifest.js +103 -0
  72. package/dist/src/install/agent-manifest.js.map +1 -0
  73. package/dist/src/install/agent-pack-installer.d.ts +39 -0
  74. package/dist/src/install/agent-pack-installer.d.ts.map +1 -0
  75. package/dist/src/install/agent-pack-installer.entry.d.ts +55 -0
  76. package/dist/src/install/agent-pack-installer.entry.d.ts.map +1 -0
  77. package/dist/src/install/agent-pack-installer.entry.js +90 -0
  78. package/dist/src/install/agent-pack-installer.entry.js.map +1 -0
  79. package/dist/src/install/agent-pack-installer.fs-helpers.d.ts +33 -0
  80. package/dist/src/install/agent-pack-installer.fs-helpers.d.ts.map +1 -0
  81. package/dist/src/install/agent-pack-installer.fs-helpers.js +59 -0
  82. package/dist/src/install/agent-pack-installer.fs-helpers.js.map +1 -0
  83. package/dist/src/install/agent-pack-installer.harness.d.ts +66 -0
  84. package/dist/src/install/agent-pack-installer.harness.d.ts.map +1 -0
  85. package/dist/src/install/agent-pack-installer.harness.js +310 -0
  86. package/dist/src/install/agent-pack-installer.harness.js.map +1 -0
  87. package/dist/src/install/agent-pack-installer.js +221 -0
  88. package/dist/src/install/agent-pack-installer.js.map +1 -0
  89. package/dist/src/install/agent-pack-installer.preserve.test.d.ts +11 -0
  90. package/dist/src/install/agent-pack-installer.preserve.test.d.ts.map +1 -0
  91. package/dist/src/install/agent-pack-installer.preserve.test.js +72 -0
  92. package/dist/src/install/agent-pack-installer.preserve.test.js.map +1 -0
  93. package/dist/src/install/agent-pack-installer.test.d.ts +2 -0
  94. package/dist/src/install/agent-pack-installer.test.d.ts.map +1 -0
  95. package/dist/src/install/agent-pack-installer.test.js +350 -0
  96. package/dist/src/install/agent-pack-installer.test.js.map +1 -0
  97. package/dist/src/install/agent-pack-installer.types.d.ts +51 -0
  98. package/dist/src/install/agent-pack-installer.types.d.ts.map +1 -0
  99. package/dist/src/install/agent-pack-installer.types.js +16 -0
  100. package/dist/src/install/agent-pack-installer.types.js.map +1 -0
  101. package/dist/src/install/agent-pack-uninstaller.d.ts +43 -0
  102. package/dist/src/install/agent-pack-uninstaller.d.ts.map +1 -0
  103. package/dist/src/install/agent-pack-uninstaller.js +113 -0
  104. package/dist/src/install/agent-pack-uninstaller.js.map +1 -0
  105. package/dist/src/install/agent-pack-uninstaller.test.d.ts +2 -0
  106. package/dist/src/install/agent-pack-uninstaller.test.d.ts.map +1 -0
  107. package/dist/src/install/agent-pack-uninstaller.test.js +212 -0
  108. package/dist/src/install/agent-pack-uninstaller.test.js.map +1 -0
  109. package/dist/src/install/index.d.ts +8 -1
  110. package/dist/src/install/index.d.ts.map +1 -1
  111. package/dist/src/install/index.js +8 -1
  112. package/dist/src/install/index.js.map +1 -1
  113. package/dist/src/install/paths.d.ts +17 -1
  114. package/dist/src/install/paths.d.ts.map +1 -1
  115. package/dist/src/install/paths.js +26 -0
  116. package/dist/src/install/paths.js.map +1 -1
  117. package/dist/src/install/paths.test.d.ts +2 -0
  118. package/dist/src/install/paths.test.d.ts.map +1 -0
  119. package/dist/src/install/paths.test.js +76 -0
  120. package/dist/src/install/paths.test.js.map +1 -0
  121. package/dist/src/journal/hash.d.ts +13 -0
  122. package/dist/src/journal/hash.d.ts.map +1 -0
  123. package/dist/src/journal/hash.js +16 -0
  124. package/dist/src/journal/hash.js.map +1 -0
  125. package/dist/src/journal/index.d.ts +15 -0
  126. package/dist/src/journal/index.d.ts.map +1 -0
  127. package/dist/src/journal/index.js +15 -0
  128. package/dist/src/journal/index.js.map +1 -0
  129. package/dist/src/journal/journal.test.d.ts +16 -0
  130. package/dist/src/journal/journal.test.d.ts.map +1 -0
  131. package/dist/src/journal/journal.test.js +171 -0
  132. package/dist/src/journal/journal.test.js.map +1 -0
  133. package/dist/src/journal/path.d.ts +44 -0
  134. package/dist/src/journal/path.d.ts.map +1 -0
  135. package/dist/src/journal/path.js +61 -0
  136. package/dist/src/journal/path.js.map +1 -0
  137. package/dist/src/journal/reader.d.ts +38 -0
  138. package/dist/src/journal/reader.d.ts.map +1 -0
  139. package/dist/src/journal/reader.js +93 -0
  140. package/dist/src/journal/reader.js.map +1 -0
  141. package/dist/src/journal/types.d.ts +87 -0
  142. package/dist/src/journal/types.d.ts.map +1 -0
  143. package/dist/src/journal/types.js +21 -0
  144. package/dist/src/journal/types.js.map +1 -0
  145. package/dist/src/journal/writer.d.ts +52 -0
  146. package/dist/src/journal/writer.d.ts.map +1 -0
  147. package/dist/src/journal/writer.js +125 -0
  148. package/dist/src/journal/writer.js.map +1 -0
  149. package/dist/src/paywall-triggers/index.d.ts +13 -0
  150. package/dist/src/paywall-triggers/index.d.ts.map +1 -0
  151. package/dist/src/paywall-triggers/index.js +13 -0
  152. package/dist/src/paywall-triggers/index.js.map +1 -0
  153. package/dist/src/paywall-triggers/path.d.ts +47 -0
  154. package/dist/src/paywall-triggers/path.d.ts.map +1 -0
  155. package/dist/src/paywall-triggers/path.js +73 -0
  156. package/dist/src/paywall-triggers/path.js.map +1 -0
  157. package/dist/src/paywall-triggers/store.d.ts +75 -0
  158. package/dist/src/paywall-triggers/store.d.ts.map +1 -0
  159. package/dist/src/paywall-triggers/store.js +122 -0
  160. package/dist/src/paywall-triggers/store.js.map +1 -0
  161. package/dist/src/paywall-triggers/store.test.d.ts +2 -0
  162. package/dist/src/paywall-triggers/store.test.d.ts.map +1 -0
  163. package/dist/src/paywall-triggers/store.test.js +121 -0
  164. package/dist/src/paywall-triggers/store.test.js.map +1 -0
  165. package/dist/src/paywall-triggers/types.d.ts +24 -0
  166. package/dist/src/paywall-triggers/types.d.ts.map +1 -0
  167. package/dist/src/paywall-triggers/types.js +13 -0
  168. package/dist/src/paywall-triggers/types.js.map +1 -0
  169. package/dist/src/security/scanner/SecurityScanner.compound.d.ts +13 -0
  170. package/dist/src/security/scanner/SecurityScanner.compound.d.ts.map +1 -0
  171. package/dist/src/security/scanner/SecurityScanner.compound.js +127 -0
  172. package/dist/src/security/scanner/SecurityScanner.compound.js.map +1 -0
  173. package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
  174. package/dist/src/security/scanner/SecurityScanner.js +10 -1
  175. package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
  176. package/dist/src/security/scanner/SecurityScanner.pii.d.ts +23 -0
  177. package/dist/src/security/scanner/SecurityScanner.pii.d.ts.map +1 -0
  178. package/dist/src/security/scanner/SecurityScanner.pii.js +152 -0
  179. package/dist/src/security/scanner/SecurityScanner.pii.js.map +1 -0
  180. package/dist/src/security/scanner/SecurityScanner.scanners.d.ts +5 -2
  181. package/dist/src/security/scanner/SecurityScanner.scanners.d.ts.map +1 -1
  182. package/dist/src/security/scanner/SecurityScanner.scanners.js +63 -70
  183. package/dist/src/security/scanner/SecurityScanner.scanners.js.map +1 -1
  184. package/dist/src/security/scanner/patterns.d.ts +2 -0
  185. package/dist/src/security/scanner/patterns.d.ts.map +1 -1
  186. package/dist/src/security/scanner/patterns.js +79 -11
  187. package/dist/src/security/scanner/patterns.js.map +1 -1
  188. package/dist/src/security/scanner/types.d.ts +2 -0
  189. package/dist/src/security/scanner/types.d.ts.map +1 -1
  190. package/dist/src/services/agent-pack/agent-pack.test.d.ts +18 -0
  191. package/dist/src/services/agent-pack/agent-pack.test.d.ts.map +1 -0
  192. package/dist/src/services/agent-pack/agent-pack.test.js +344 -0
  193. package/dist/src/services/agent-pack/agent-pack.test.js.map +1 -0
  194. package/dist/src/services/agent-pack/hooks.d.ts +29 -0
  195. package/dist/src/services/agent-pack/hooks.d.ts.map +1 -0
  196. package/dist/src/services/agent-pack/hooks.js +139 -0
  197. package/dist/src/services/agent-pack/hooks.js.map +1 -0
  198. package/dist/src/services/agent-pack/index.d.ts +26 -0
  199. package/dist/src/services/agent-pack/index.d.ts.map +1 -0
  200. package/dist/src/services/agent-pack/index.js +109 -0
  201. package/dist/src/services/agent-pack/index.js.map +1 -0
  202. package/dist/src/services/agent-pack/prompt-source.d.ts +47 -0
  203. package/dist/src/services/agent-pack/prompt-source.d.ts.map +1 -0
  204. package/dist/src/services/agent-pack/prompt-source.js +182 -0
  205. package/dist/src/services/agent-pack/prompt-source.js.map +1 -0
  206. package/dist/src/services/agent-pack/shims.d.ts +40 -0
  207. package/dist/src/services/agent-pack/shims.d.ts.map +1 -0
  208. package/dist/src/services/agent-pack/shims.js +96 -0
  209. package/dist/src/services/agent-pack/shims.js.map +1 -0
  210. package/dist/src/services/agent-pack/skill-md.d.ts +35 -0
  211. package/dist/src/services/agent-pack/skill-md.d.ts.map +1 -0
  212. package/dist/src/services/agent-pack/skill-md.js +89 -0
  213. package/dist/src/services/agent-pack/skill-md.js.map +1 -0
  214. package/dist/src/services/agent-pack/types.d.ts +118 -0
  215. package/dist/src/services/agent-pack/types.d.ts.map +1 -0
  216. package/dist/src/services/agent-pack/types.js +61 -0
  217. package/dist/src/services/agent-pack/types.js.map +1 -0
  218. package/dist/src/services/agent-tool-profile.d.ts +59 -0
  219. package/dist/src/services/agent-tool-profile.d.ts.map +1 -0
  220. package/dist/src/services/agent-tool-profile.js +76 -0
  221. package/dist/src/services/agent-tool-profile.js.map +1 -0
  222. package/dist/src/services/agent-tool-profile.test.d.ts +2 -0
  223. package/dist/src/services/agent-tool-profile.test.d.ts.map +1 -0
  224. package/dist/src/services/agent-tool-profile.test.js +28 -0
  225. package/dist/src/services/agent-tool-profile.test.js.map +1 -0
  226. package/dist/src/services/bundled-sibling-scan.d.ts +111 -0
  227. package/dist/src/services/bundled-sibling-scan.d.ts.map +1 -0
  228. package/dist/src/services/bundled-sibling-scan.js +170 -0
  229. package/dist/src/services/bundled-sibling-scan.js.map +1 -0
  230. package/dist/src/services/skill-installation.io.d.ts +16 -5
  231. package/dist/src/services/skill-installation.io.d.ts.map +1 -1
  232. package/dist/src/services/skill-installation.io.js +44 -20
  233. package/dist/src/services/skill-installation.io.js.map +1 -1
  234. package/dist/src/services/skill-installation.policy.d.ts +96 -0
  235. package/dist/src/services/skill-installation.policy.d.ts.map +1 -0
  236. package/dist/src/services/skill-installation.policy.js +144 -0
  237. package/dist/src/services/skill-installation.policy.js.map +1 -0
  238. package/dist/src/services/skill-installation.service.d.ts.map +1 -1
  239. package/dist/src/services/skill-installation.service.js +9 -3
  240. package/dist/src/services/skill-installation.service.js.map +1 -1
  241. package/dist/src/sources/index.d.ts +1 -0
  242. package/dist/src/sources/index.d.ts.map +1 -1
  243. package/dist/src/sources/index.js +4 -0
  244. package/dist/src/sources/index.js.map +1 -1
  245. package/dist/src/sync/index.d.ts +6 -0
  246. package/dist/src/sync/index.d.ts.map +1 -1
  247. package/dist/src/sync/index.js +8 -0
  248. package/dist/src/sync/index.js.map +1 -1
  249. package/dist/src/sync/inventory-builder.d.ts +21 -0
  250. package/dist/src/sync/inventory-builder.d.ts.map +1 -0
  251. package/dist/src/sync/inventory-builder.js +26 -0
  252. package/dist/src/sync/inventory-builder.js.map +1 -0
  253. package/dist/src/sync/inventory-client.d.ts +80 -0
  254. package/dist/src/sync/inventory-client.d.ts.map +1 -0
  255. package/dist/src/sync/inventory-client.js +204 -0
  256. package/dist/src/sync/inventory-client.js.map +1 -0
  257. package/dist/src/sync/inventory-client.test.d.ts +14 -0
  258. package/dist/src/sync/inventory-client.test.d.ts.map +1 -0
  259. package/dist/src/sync/inventory-client.test.js +212 -0
  260. package/dist/src/sync/inventory-client.test.js.map +1 -0
  261. package/dist/src/sync/inventory-collector.d.ts +35 -0
  262. package/dist/src/sync/inventory-collector.d.ts.map +1 -0
  263. package/dist/src/sync/inventory-collector.js +176 -0
  264. package/dist/src/sync/inventory-collector.js.map +1 -0
  265. package/dist/src/sync/inventory-collector.test.d.ts +14 -0
  266. package/dist/src/sync/inventory-collector.test.d.ts.map +1 -0
  267. package/dist/src/sync/inventory-collector.test.js +156 -0
  268. package/dist/src/sync/inventory-collector.test.js.map +1 -0
  269. package/dist/src/sync/inventory-device.d.ts +36 -0
  270. package/dist/src/sync/inventory-device.d.ts.map +1 -0
  271. package/dist/src/sync/inventory-device.js +58 -0
  272. package/dist/src/sync/inventory-device.js.map +1 -0
  273. package/dist/src/sync/inventory-push.d.ts +45 -0
  274. package/dist/src/sync/inventory-push.d.ts.map +1 -0
  275. package/dist/src/sync/inventory-push.js +62 -0
  276. package/dist/src/sync/inventory-push.js.map +1 -0
  277. package/dist/src/sync/inventory-push.test.d.ts +16 -0
  278. package/dist/src/sync/inventory-push.test.d.ts.map +1 -0
  279. package/dist/src/sync/inventory-push.test.js +104 -0
  280. package/dist/src/sync/inventory-push.test.js.map +1 -0
  281. package/dist/src/sync/inventory-types.d.ts +110 -0
  282. package/dist/src/sync/inventory-types.d.ts.map +1 -0
  283. package/dist/src/sync/inventory-types.js +45 -0
  284. package/dist/src/sync/inventory-types.js.map +1 -0
  285. package/dist/src/telemetry/agent-marker.d.ts +137 -0
  286. package/dist/src/telemetry/agent-marker.d.ts.map +1 -0
  287. package/dist/src/telemetry/agent-marker.js +242 -0
  288. package/dist/src/telemetry/agent-marker.js.map +1 -0
  289. package/dist/src/telemetry/agent-marker.test.d.ts +13 -0
  290. package/dist/src/telemetry/agent-marker.test.d.ts.map +1 -0
  291. package/dist/src/telemetry/agent-marker.test.js +202 -0
  292. package/dist/src/telemetry/agent-marker.test.js.map +1 -0
  293. package/dist/src/telemetry/index.d.ts +2 -1
  294. package/dist/src/telemetry/index.d.ts.map +1 -1
  295. package/dist/src/telemetry/index.js +6 -1
  296. package/dist/src/telemetry/index.js.map +1 -1
  297. package/dist/src/telemetry/posthog.d.ts +10 -0
  298. package/dist/src/telemetry/posthog.d.ts.map +1 -1
  299. package/dist/src/telemetry/posthog.js +5 -1
  300. package/dist/src/telemetry/posthog.js.map +1 -1
  301. package/dist/src/telemetry/wrap.d.ts +28 -7
  302. package/dist/src/telemetry/wrap.d.ts.map +1 -1
  303. package/dist/src/telemetry/wrap.gate.test.d.ts +22 -0
  304. package/dist/src/telemetry/wrap.gate.test.d.ts.map +1 -0
  305. package/dist/src/telemetry/wrap.gate.test.js +197 -0
  306. package/dist/src/telemetry/wrap.gate.test.js.map +1 -0
  307. package/dist/src/telemetry/wrap.js +111 -26
  308. package/dist/src/telemetry/wrap.js.map +1 -1
  309. package/dist/src/telemetry/wrap.marker.test.d.ts +16 -0
  310. package/dist/src/telemetry/wrap.marker.test.d.ts.map +1 -0
  311. package/dist/src/telemetry/wrap.marker.test.js +185 -0
  312. package/dist/src/telemetry/wrap.marker.test.js.map +1 -0
  313. package/dist/src/telemetry/wrap.test.js +4 -0
  314. package/dist/src/telemetry/wrap.test.js.map +1 -1
  315. package/dist/tests/SecurityScanner.exec.test.js +60 -0
  316. package/dist/tests/SecurityScanner.exec.test.js.map +1 -1
  317. package/dist/tests/security/ContinuousSecurity.test.js +10 -4
  318. package/dist/tests/security/ContinuousSecurity.test.js.map +1 -1
  319. package/dist/tests/security/SecurityScanner.chmod-evasion.test.d.ts +2 -0
  320. package/dist/tests/security/SecurityScanner.chmod-evasion.test.d.ts.map +1 -0
  321. package/dist/tests/security/SecurityScanner.chmod-evasion.test.js +126 -0
  322. package/dist/tests/security/SecurityScanner.chmod-evasion.test.js.map +1 -0
  323. package/dist/tests/security/chmod-compound.test.d.ts +2 -0
  324. package/dist/tests/security/chmod-compound.test.d.ts.map +1 -0
  325. package/dist/tests/security/chmod-compound.test.js +188 -0
  326. package/dist/tests/security/chmod-compound.test.js.map +1 -0
  327. package/dist/tests/security/pii-detection.test.js +131 -0
  328. package/dist/tests/security/pii-detection.test.js.map +1 -1
  329. package/dist/tests/security/scanner-regression-guard.test.d.ts +23 -7
  330. package/dist/tests/security/scanner-regression-guard.test.d.ts.map +1 -1
  331. package/dist/tests/security/scanner-regression-guard.test.js +27 -11
  332. package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
  333. package/dist/tests/security/sensitive-path-fp.test.d.ts +2 -0
  334. package/dist/tests/security/sensitive-path-fp.test.d.ts.map +1 -0
  335. package/dist/tests/security/sensitive-path-fp.test.js +142 -0
  336. package/dist/tests/security/sensitive-path-fp.test.js.map +1 -0
  337. package/dist/tests/services/bundled-sibling-scan.test.d.ts +2 -0
  338. package/dist/tests/services/bundled-sibling-scan.test.d.ts.map +1 -0
  339. package/dist/tests/services/bundled-sibling-scan.test.js +139 -0
  340. package/dist/tests/services/bundled-sibling-scan.test.js.map +1 -0
  341. package/dist/tests/unit/services/skill-installation.io.test.js +166 -0
  342. package/dist/tests/unit/services/skill-installation.io.test.js.map +1 -1
  343. package/dist/tests/unit/services/skill-installation.policy.test.d.ts +8 -0
  344. package/dist/tests/unit/services/skill-installation.policy.test.d.ts.map +1 -0
  345. package/dist/tests/unit/services/skill-installation.policy.test.js +151 -0
  346. package/dist/tests/unit/services/skill-installation.policy.test.js.map +1 -0
  347. package/package.json +23 -3
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Device-identity builder for the cross-harness inventory payload
3
+ * (SMI-5392, umbrella SMI-5382).
4
+ *
5
+ * Produces the {@link InventoryDevice} half of an {@link InventoryUploadPayload}.
6
+ * Field minimization follows ADR-124: the raw hostname is NEVER sent by default
7
+ * (`hostname_display` is `null` this wave); only a salt-free sha256 `hostname_hash`
8
+ * is included as a soft duplicate-device hint. The hash is not trivially
9
+ * reversible, but a low-entropy hostname is dictionary-recoverable — this is
10
+ * acceptable per ADR-124 because the hash is scoped to the user's own
11
+ * authenticated account, never exposed cross-tenant.
12
+ *
13
+ * @module @skillsmith/core/sync/inventory-device
14
+ */
15
+ import { type InventoryDevice } from './inventory-types.js';
16
+ /** Options accepted by {@link buildInventoryDevice}. */
17
+ export interface BuildInventoryDeviceOptions {
18
+ /** Skillsmith CLI version that produced the snapshot (defaults to `null`). */
19
+ cliVersion?: string | null;
20
+ }
21
+ /**
22
+ * Build the {@link InventoryDevice} descriptor for this machine.
23
+ *
24
+ * - `device_id` is the stable client-generated UUID (created on first call).
25
+ * - `label` is the user's optional device label from `~/.skillsmith/config.json`
26
+ * (`inventory.deviceLabel`); there is no dedicated getter in `device-identity`,
27
+ * so it is read directly from config and capped to `LABEL_MAX`.
28
+ * - `hostname_display` is always `null` this wave (ADR-124 minimization).
29
+ * - `hostname_hash` is the sha256 hex of `os.hostname()` — a soft duplicate hint.
30
+ *
31
+ * @param opts - Optional CLI version to stamp on the snapshot.
32
+ * @returns A fully-minimized device descriptor.
33
+ * @see SMI-5392
34
+ */
35
+ export declare function buildInventoryDevice(opts?: BuildInventoryDeviceOptions): InventoryDevice;
36
+ //# sourceMappingURL=inventory-device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory-device.d.ts","sourceRoot":"","sources":["../../../src/sync/inventory-device.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE7E,wDAAwD;AACxD,MAAM,WAAW,2BAA2B;IAC1C,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,2BAA2B,GAAG,eAAe,CAcxF"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Device-identity builder for the cross-harness inventory payload
3
+ * (SMI-5392, umbrella SMI-5382).
4
+ *
5
+ * Produces the {@link InventoryDevice} half of an {@link InventoryUploadPayload}.
6
+ * Field minimization follows ADR-124: the raw hostname is NEVER sent by default
7
+ * (`hostname_display` is `null` this wave); only a salt-free sha256 `hostname_hash`
8
+ * is included as a soft duplicate-device hint. The hash is not trivially
9
+ * reversible, but a low-entropy hostname is dictionary-recoverable — this is
10
+ * acceptable per ADR-124 because the hash is scoped to the user's own
11
+ * authenticated account, never exposed cross-tenant.
12
+ *
13
+ * @module @skillsmith/core/sync/inventory-device
14
+ */
15
+ import { hostname } from 'node:os';
16
+ import { createHash } from 'node:crypto';
17
+ import { getOrCreateDeviceId } from '../config/device-identity.js';
18
+ import { loadConfig } from '../config/index.js';
19
+ import { INVENTORY_LIMITS } from './inventory-types.js';
20
+ /**
21
+ * Truncate `value` to at most `max` characters, returning `null` for nullish
22
+ * input. Guards every length-capped column so a malformed local value can't
23
+ * trip a DB CHECK constraint mid-reconcile.
24
+ */
25
+ function capped(value, max) {
26
+ if (value == null)
27
+ return null;
28
+ return value.length > max ? value.slice(0, max) : value;
29
+ }
30
+ /**
31
+ * Build the {@link InventoryDevice} descriptor for this machine.
32
+ *
33
+ * - `device_id` is the stable client-generated UUID (created on first call).
34
+ * - `label` is the user's optional device label from `~/.skillsmith/config.json`
35
+ * (`inventory.deviceLabel`); there is no dedicated getter in `device-identity`,
36
+ * so it is read directly from config and capped to `LABEL_MAX`.
37
+ * - `hostname_display` is always `null` this wave (ADR-124 minimization).
38
+ * - `hostname_hash` is the sha256 hex of `os.hostname()` — a soft duplicate hint.
39
+ *
40
+ * @param opts - Optional CLI version to stamp on the snapshot.
41
+ * @returns A fully-minimized device descriptor.
42
+ * @see SMI-5392
43
+ */
44
+ export function buildInventoryDevice(opts) {
45
+ const deviceId = getOrCreateDeviceId();
46
+ const deviceLabel = loadConfig().inventory?.deviceLabel;
47
+ const hostnameHash = createHash('sha256').update(hostname(), 'utf8').digest('hex');
48
+ return {
49
+ device_id: deviceId,
50
+ label: capped(deviceLabel, INVENTORY_LIMITS.LABEL_MAX),
51
+ hostname_display: null,
52
+ hostname_hash: capped(hostnameHash, INVENTORY_LIMITS.HOSTNAME_HASH_MAX),
53
+ platform: capped(process.platform, INVENTORY_LIMITS.PLATFORM_MAX),
54
+ arch: capped(process.arch, INVENTORY_LIMITS.ARCH_MAX),
55
+ cli_version: capped(opts?.cliVersion, INVENTORY_LIMITS.CLI_VERSION_MAX),
56
+ };
57
+ }
58
+ //# sourceMappingURL=inventory-device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory-device.js","sourceRoot":"","sources":["../../../src/sync/inventory-device.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,gBAAgB,EAAwB,MAAM,sBAAsB,CAAA;AAQ7E;;;;GAIG;AACH,SAAS,MAAM,CAAC,KAAgC,EAAE,GAAW;IAC3D,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAA;IAC9B,OAAO,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AACzD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAkC;IACrE,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAA;IACtC,MAAM,WAAW,GAAG,UAAU,EAAE,CAAC,SAAS,EAAE,WAAW,CAAA;IACvD,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAElF,OAAO;QACL,SAAS,EAAE,QAAQ;QACnB,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC,SAAS,CAAC;QACtD,gBAAgB,EAAE,IAAI;QACtB,aAAa,EAAE,MAAM,CAAC,YAAY,EAAE,gBAAgB,CAAC,iBAAiB,CAAC;QACvE,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,YAAY,CAAC;QACjE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC,QAAQ,CAAC;QACrD,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,gBAAgB,CAAC,eAAe,CAAC;KACxE,CAAA;AACH,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Inventory push orchestrator (SMI-5392, umbrella SMI-5382).
3
+ *
4
+ * The single entry point both the CLI command and the MCP tool call to push this
5
+ * device's inventory. Wires together the local opt-out gate, the payload builder,
6
+ * the upload client, and the auto-push throttle.
7
+ *
8
+ * @module @skillsmith/core/sync/inventory-push
9
+ */
10
+ import type { BuildInventoryDeviceOptions } from './inventory-device.js';
11
+ import type { InventoryUploadResult } from './inventory-types.js';
12
+ /** Options accepted by {@link pushInventory}. */
13
+ export type PushInventoryOptions = BuildInventoryDeviceOptions;
14
+ /** Options accepted by {@link maybeAutoPush}. */
15
+ export interface MaybeAutoPushOptions extends BuildInventoryDeviceOptions {
16
+ /** Injectable clock for deterministic throttle tests (defaults to `Date.now()`). */
17
+ now?: number;
18
+ }
19
+ /**
20
+ * Build and upload this device's inventory snapshot.
21
+ *
22
+ * When the local opt-out flag (`SKILLSMITH_INVENTORY_DISABLE`) is set, this is a
23
+ * pure no-op: NO network call, and NO device-id creation. On a server-applied
24
+ * upload, the last-push timestamp is persisted for the auto-push throttle. A
25
+ * consent-off `{ applied: false, reason: 'consent_disabled' }` result is returned
26
+ * as-is and does NOT advance the throttle (so consent re-enablement pushes promptly).
27
+ *
28
+ * @param opts - Optional CLI version to stamp on the snapshot.
29
+ * @returns The upload result (or the local-disable no-op).
30
+ * @see SMI-5392
31
+ */
32
+ export declare function pushInventory(opts?: PushInventoryOptions): Promise<InventoryUploadResult>;
33
+ /**
34
+ * Auto-push entry point for the session-start hook.
35
+ *
36
+ * Returns `null` (without pushing) when sync is locally disabled or the throttle
37
+ * window has not elapsed. Upload errors are SWALLOWED — an auto-push must never
38
+ * throw into a session hook — logged to `console.error` and reported as `null`.
39
+ *
40
+ * @param opts - Optional CLI version + injectable clock.
41
+ * @returns The upload result, or `null` when skipped / throttled / errored.
42
+ * @see SMI-5392
43
+ */
44
+ export declare function maybeAutoPush(opts?: MaybeAutoPushOptions): Promise<InventoryUploadResult | null>;
45
+ //# sourceMappingURL=inventory-push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory-push.d.ts","sourceRoot":"","sources":["../../../src/sync/inventory-push.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAEjE,iDAAiD;AACjD,MAAM,MAAM,oBAAoB,GAAG,2BAA2B,CAAA;AAE9D,iDAAiD;AACjD,MAAM,WAAW,oBAAqB,SAAQ,2BAA2B;IACvE,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,IAAI,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAa/F;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,IAAI,CAAC,EAAE,oBAAoB,GAC1B,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAYvC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Inventory push orchestrator (SMI-5392, umbrella SMI-5382).
3
+ *
4
+ * The single entry point both the CLI command and the MCP tool call to push this
5
+ * device's inventory. Wires together the local opt-out gate, the payload builder,
6
+ * the upload client, and the auto-push throttle.
7
+ *
8
+ * @module @skillsmith/core/sync/inventory-push
9
+ */
10
+ import { getLastInventoryPushAt, isInventorySyncDisabledLocally, recordInventoryPush, shouldAutoPush, } from '../config/device-identity.js';
11
+ import { buildInventoryPayload } from './inventory-builder.js';
12
+ import { uploadInventory } from './inventory-client.js';
13
+ /**
14
+ * Build and upload this device's inventory snapshot.
15
+ *
16
+ * When the local opt-out flag (`SKILLSMITH_INVENTORY_DISABLE`) is set, this is a
17
+ * pure no-op: NO network call, and NO device-id creation. On a server-applied
18
+ * upload, the last-push timestamp is persisted for the auto-push throttle. A
19
+ * consent-off `{ applied: false, reason: 'consent_disabled' }` result is returned
20
+ * as-is and does NOT advance the throttle (so consent re-enablement pushes promptly).
21
+ *
22
+ * @param opts - Optional CLI version to stamp on the snapshot.
23
+ * @returns The upload result (or the local-disable no-op).
24
+ * @see SMI-5392
25
+ */
26
+ export async function pushInventory(opts) {
27
+ if (isInventorySyncDisabledLocally()) {
28
+ return { ok: true, applied: false, reason: 'disabled_locally' };
29
+ }
30
+ const payload = await buildInventoryPayload(opts);
31
+ const result = await uploadInventory(payload);
32
+ if (result.applied) {
33
+ recordInventoryPush(new Date().toISOString());
34
+ }
35
+ return result;
36
+ }
37
+ /**
38
+ * Auto-push entry point for the session-start hook.
39
+ *
40
+ * Returns `null` (without pushing) when sync is locally disabled or the throttle
41
+ * window has not elapsed. Upload errors are SWALLOWED — an auto-push must never
42
+ * throw into a session hook — logged to `console.error` and reported as `null`.
43
+ *
44
+ * @param opts - Optional CLI version + injectable clock.
45
+ * @returns The upload result, or `null` when skipped / throttled / errored.
46
+ * @see SMI-5392
47
+ */
48
+ export async function maybeAutoPush(opts) {
49
+ if (isInventorySyncDisabledLocally())
50
+ return null;
51
+ const now = opts?.now ?? Date.now();
52
+ if (!shouldAutoPush(now, getLastInventoryPushAt()))
53
+ return null;
54
+ try {
55
+ return await pushInventory(opts);
56
+ }
57
+ catch (error) {
58
+ console.error('[skillsmith] inventory auto-push failed:', error);
59
+ return null;
60
+ }
61
+ }
62
+ //# sourceMappingURL=inventory-push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory-push.js","sourceRoot":"","sources":["../../../src/sync/inventory-push.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,sBAAsB,EACtB,8BAA8B,EAC9B,mBAAmB,EACnB,cAAc,GACf,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAavD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAA2B;IAC7D,IAAI,8BAA8B,EAAE,EAAE,CAAC;QACrC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAA;IACjE,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,CAAA;IAE7C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,mBAAmB,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;IAC/C,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAA2B;IAE3B,IAAI,8BAA8B,EAAE;QAAE,OAAO,IAAI,CAAA;IAEjD,MAAM,GAAG,GAAG,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAA;IACnC,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,sBAAsB,EAAE,CAAC;QAAE,OAAO,IAAI,CAAA;IAE/D,IAAI,CAAC;QACH,OAAO,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAA;QAChE,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * inventory-push tests (SMI-5392).
3
+ *
4
+ * Mocks the payload builder and upload client; keeps the real (pure)
5
+ * `isInventorySyncDisabledLocally` + `shouldAutoPush` so the env-flag and
6
+ * throttle paths exercise production logic, while `recordInventoryPush` and
7
+ * `getLastInventoryPushAt` are stubbed for observation/control.
8
+ *
9
+ * IP-1: SKILLSMITH_INVENTORY_DISABLE set -> disabled_locally no-op, no upload.
10
+ * IP-2: applied result -> recordInventoryPush called.
11
+ * IP-3: consent-off result -> recordInventoryPush NOT called.
12
+ * IP-4: maybeAutoPush throttled (recent lastPushAt) -> null without pushing.
13
+ * IP-5: maybeAutoPush swallows an upload error and returns null.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=inventory-push.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory-push.test.d.ts","sourceRoot":"","sources":["../../../src/sync/inventory-push.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * inventory-push tests (SMI-5392).
3
+ *
4
+ * Mocks the payload builder and upload client; keeps the real (pure)
5
+ * `isInventorySyncDisabledLocally` + `shouldAutoPush` so the env-flag and
6
+ * throttle paths exercise production logic, while `recordInventoryPush` and
7
+ * `getLastInventoryPushAt` are stubbed for observation/control.
8
+ *
9
+ * IP-1: SKILLSMITH_INVENTORY_DISABLE set -> disabled_locally no-op, no upload.
10
+ * IP-2: applied result -> recordInventoryPush called.
11
+ * IP-3: consent-off result -> recordInventoryPush NOT called.
12
+ * IP-4: maybeAutoPush throttled (recent lastPushAt) -> null without pushing.
13
+ * IP-5: maybeAutoPush swallows an upload error and returns null.
14
+ */
15
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
16
+ vi.mock('./inventory-builder.js', () => ({ buildInventoryPayload: vi.fn() }));
17
+ vi.mock('./inventory-client.js', () => ({ uploadInventory: vi.fn() }));
18
+ vi.mock('../config/device-identity.js', async (importActual) => {
19
+ const actual = await importActual();
20
+ return {
21
+ ...actual,
22
+ recordInventoryPush: vi.fn(),
23
+ getLastInventoryPushAt: vi.fn(() => undefined),
24
+ };
25
+ });
26
+ import { buildInventoryPayload } from './inventory-builder.js';
27
+ import { uploadInventory } from './inventory-client.js';
28
+ import { recordInventoryPush, getLastInventoryPushAt } from '../config/device-identity.js';
29
+ import { pushInventory, maybeAutoPush } from './inventory-push.js';
30
+ const samplePayload = { device: { device_id: 'd' }, skills: [] };
31
+ describe('inventory-push', () => {
32
+ beforeEach(() => {
33
+ vi.clearAllMocks();
34
+ delete process.env.SKILLSMITH_INVENTORY_DISABLE;
35
+ vi.mocked(buildInventoryPayload).mockResolvedValue(samplePayload);
36
+ vi.mocked(getLastInventoryPushAt).mockReturnValue(undefined);
37
+ });
38
+ afterEach(() => {
39
+ delete process.env.SKILLSMITH_INVENTORY_DISABLE;
40
+ vi.restoreAllMocks();
41
+ });
42
+ it('IP-1: returns disabled_locally without uploading when the env flag is set', async () => {
43
+ process.env.SKILLSMITH_INVENTORY_DISABLE = '1';
44
+ const result = await pushInventory();
45
+ expect(result).toEqual({ ok: true, applied: false, reason: 'disabled_locally' });
46
+ expect(buildInventoryPayload).not.toHaveBeenCalled();
47
+ expect(uploadInventory).not.toHaveBeenCalled();
48
+ expect(recordInventoryPush).not.toHaveBeenCalled();
49
+ });
50
+ it('IP-2: records the push timestamp when the result is applied', async () => {
51
+ vi.mocked(uploadInventory).mockResolvedValue({ ok: true, applied: true, device_id: 'd' });
52
+ const result = await pushInventory();
53
+ expect(result.applied).toBe(true);
54
+ expect(recordInventoryPush).toHaveBeenCalledTimes(1);
55
+ expect(recordInventoryPush).toHaveBeenCalledWith(expect.any(String));
56
+ });
57
+ it('IP-3: does not record a push when consent is disabled server-side', async () => {
58
+ vi.mocked(uploadInventory).mockResolvedValue({
59
+ ok: true,
60
+ applied: false,
61
+ reason: 'consent_disabled',
62
+ });
63
+ const result = await pushInventory();
64
+ expect(result.applied).toBe(false);
65
+ expect(recordInventoryPush).not.toHaveBeenCalled();
66
+ });
67
+ it('IP-4: maybeAutoPush returns null without pushing when throttled', async () => {
68
+ vi.mocked(getLastInventoryPushAt).mockReturnValue(new Date(Date.now() - 1_000).toISOString());
69
+ const result = await maybeAutoPush({ now: Date.now() });
70
+ expect(result).toBeNull();
71
+ expect(buildInventoryPayload).not.toHaveBeenCalled();
72
+ expect(uploadInventory).not.toHaveBeenCalled();
73
+ });
74
+ it('IP-5: maybeAutoPush swallows an upload error and returns null', async () => {
75
+ const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
76
+ vi.mocked(uploadInventory).mockRejectedValue(new Error('boom'));
77
+ const result = await maybeAutoPush();
78
+ expect(result).toBeNull();
79
+ expect(errorSpy).toHaveBeenCalled();
80
+ });
81
+ it('IP-6: maybeAutoPush returns null without uploading when sync is locally disabled', async () => {
82
+ process.env.SKILLSMITH_INVENTORY_DISABLE = '1';
83
+ const result = await maybeAutoPush();
84
+ expect(result).toBeNull();
85
+ expect(buildInventoryPayload).not.toHaveBeenCalled();
86
+ expect(uploadInventory).not.toHaveBeenCalled();
87
+ });
88
+ it('IP-7: maybeAutoPush returns the applied result and records the push timestamp', async () => {
89
+ // getLastInventoryPushAt returns undefined (set in beforeEach) so shouldAutoPush is true.
90
+ const applied = {
91
+ ok: true,
92
+ applied: true,
93
+ device_id: 'd',
94
+ skills_present: 5,
95
+ skills_absent: 0,
96
+ };
97
+ vi.mocked(uploadInventory).mockResolvedValue(applied);
98
+ const result = await maybeAutoPush();
99
+ expect(result).toEqual(applied);
100
+ expect(recordInventoryPush).toHaveBeenCalledTimes(1);
101
+ expect(recordInventoryPush).toHaveBeenCalledWith(expect.any(String));
102
+ });
103
+ });
104
+ //# sourceMappingURL=inventory-push.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory-push.test.js","sourceRoot":"","sources":["../../../src/sync/inventory-push.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Cross-harness inventory payload contract (SMI-5389, umbrella SMI-5382).
3
+ *
4
+ * This is the SINGLE canonical declaration of the wire shape that the local
5
+ * agent pushes to `POST /functions/v1/inventory-upload`. The CLI (Wave 3) and
6
+ * website (Wave 4) import these types directly. The Deno edge function cannot
7
+ * import a Node package, so `supabase/functions/inventory-upload/payload.ts`
8
+ * mirrors this shape structurally and validates it at runtime — keep the two in
9
+ * lock-step (the edge validator references this module by path in its header).
10
+ *
11
+ * ADR-125 (control plane + data model), ADR-124 (consent + field minimization).
12
+ */
13
+ /**
14
+ * Per-machine identity + metadata. `device_id` is a client-generated UUID
15
+ * persisted in `~/.skillsmith/config.json` (ADR-125 Spike S2). Every other field
16
+ * is optional and minimized by default (ADR-124): a raw hostname is only sent on
17
+ * explicit opt-in; otherwise send a label and/or `hostname_hash`.
18
+ */
19
+ export interface InventoryDevice {
20
+ /** Client-generated stable UUID. Required. */
21
+ device_id: string;
22
+ /** User-facing label (e.g. "work laptop"). */
23
+ label?: string | null;
24
+ /** Display hostname — truncated/redacted by default. */
25
+ hostname_display?: string | null;
26
+ /** Hash of the raw hostname for a soft duplicate-device hint (no auto-merge). */
27
+ hostname_hash?: string | null;
28
+ /** `process.platform` (e.g. "darwin", "linux", "win32"). */
29
+ platform?: string | null;
30
+ /** `process.arch` (e.g. "arm64", "x64"). */
31
+ arch?: string | null;
32
+ /** Skillsmith CLI version that produced the snapshot. */
33
+ cli_version?: string | null;
34
+ }
35
+ /** What the local agent does with a skill when the registry advances. */
36
+ export type InventoryUpdatePolicy = 'auto' | 'manual' | 'never';
37
+ /**
38
+ * One observed skill on one harness on this device. `skill_id` is the registry
39
+ * id (`author/name`); local/unmatched skills still report their best id and
40
+ * resolve to the `unknown` drift state server-side.
41
+ */
42
+ export interface InventorySkillEntry {
43
+ /** Harness slug (e.g. "claude-code", "opencode"). Required. */
44
+ harness: string;
45
+ /** Skill id, conventionally `author/name`. Required. */
46
+ skill_id: string;
47
+ /** Installed version string, if known. */
48
+ version?: string | null;
49
+ /** Where it was installed from (registry, local path, git, …). */
50
+ source?: string | null;
51
+ /** Author claim from SKILL.md front-matter — self-asserted (unverified). */
52
+ author?: string | null;
53
+ /** License claim from SKILL.md front-matter — self-asserted (unverified). */
54
+ license?: string | null;
55
+ /** Repository URL claim from SKILL.md front-matter — self-asserted (unverified). */
56
+ repository?: string | null;
57
+ /** Content hash of the installed skill, for registry drift detection. */
58
+ content_hash?: string | null;
59
+ /** Pinned version, if the user pinned it (suppresses drift/stale flags). */
60
+ pinned_version?: string | null;
61
+ /** Update policy for this skill. */
62
+ update_policy?: InventoryUpdatePolicy | null;
63
+ }
64
+ /** Full request body for `POST /functions/v1/inventory-upload`. */
65
+ export interface InventoryUploadPayload {
66
+ device: InventoryDevice;
67
+ skills: InventorySkillEntry[];
68
+ }
69
+ /**
70
+ * Response body from `inventory-upload` (mirrors the `reconcile_device_inventory`
71
+ * RPC return). `applied: false` with `reason: 'consent_disabled'` is the
72
+ * consent-off no-op — a success, not an error.
73
+ */
74
+ export interface InventoryUploadResult {
75
+ ok: boolean;
76
+ applied: boolean;
77
+ reason?: string;
78
+ device_id?: string;
79
+ skills_present?: number;
80
+ skills_absent?: number;
81
+ }
82
+ /**
83
+ * Shared caps. Mirrors the column CHECK constraints in
84
+ * `20260626000001_user_inventory.sql` and the payload bound in
85
+ * `reconcile_device_inventory`. The edge validator and the local agent both
86
+ * enforce these so a malformed push fails fast with a 400 rather than tripping a
87
+ * DB constraint mid-reconcile.
88
+ */
89
+ export declare const INVENTORY_LIMITS: {
90
+ readonly MAX_SKILLS: 5000;
91
+ readonly LABEL_MAX: 100;
92
+ readonly HOSTNAME_DISPLAY_MAX: 100;
93
+ readonly HOSTNAME_HASH_MAX: 64;
94
+ readonly PLATFORM_MAX: 32;
95
+ readonly ARCH_MAX: 32;
96
+ readonly CLI_VERSION_MAX: 32;
97
+ readonly HARNESS_MAX: 32;
98
+ readonly SKILL_ID_MAX: 255;
99
+ readonly VERSION_MAX: 64;
100
+ readonly SOURCE_MAX: 255;
101
+ readonly AUTHOR_MAX: 200;
102
+ readonly LICENSE_MAX: 64;
103
+ readonly REPOSITORY_MAX: 512;
104
+ readonly CONTENT_HASH_MAX: 128;
105
+ readonly PINNED_VERSION_MAX: 64;
106
+ readonly UPDATE_POLICY_MAX: 16;
107
+ };
108
+ /** Allowed `update_policy` values (mirrors the DB CHECK constraint). */
109
+ export declare const INVENTORY_UPDATE_POLICIES: readonly InventoryUpdatePolicy[];
110
+ //# sourceMappingURL=inventory-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory-types.d.ts","sourceRoot":"","sources":["../../../src/sync/inventory-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAA;IACjB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,yEAAyE;AACzE,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE/D;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAA;IACf,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAA;IAChB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,oCAAoC;IACpC,aAAa,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAA;CAC7C;AAED,mEAAmE;AACnE,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,CAAA;IACvB,MAAM,EAAE,mBAAmB,EAAE,CAAA;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,OAAO,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;CAkBnB,CAAA;AAEV,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,EAAE,SAAS,qBAAqB,EAI5D,CAAA"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Cross-harness inventory payload contract (SMI-5389, umbrella SMI-5382).
3
+ *
4
+ * This is the SINGLE canonical declaration of the wire shape that the local
5
+ * agent pushes to `POST /functions/v1/inventory-upload`. The CLI (Wave 3) and
6
+ * website (Wave 4) import these types directly. The Deno edge function cannot
7
+ * import a Node package, so `supabase/functions/inventory-upload/payload.ts`
8
+ * mirrors this shape structurally and validates it at runtime — keep the two in
9
+ * lock-step (the edge validator references this module by path in its header).
10
+ *
11
+ * ADR-125 (control plane + data model), ADR-124 (consent + field minimization).
12
+ */
13
+ /**
14
+ * Shared caps. Mirrors the column CHECK constraints in
15
+ * `20260626000001_user_inventory.sql` and the payload bound in
16
+ * `reconcile_device_inventory`. The edge validator and the local agent both
17
+ * enforce these so a malformed push fails fast with a 400 rather than tripping a
18
+ * DB constraint mid-reconcile.
19
+ */
20
+ export const INVENTORY_LIMITS = {
21
+ MAX_SKILLS: 5000,
22
+ LABEL_MAX: 100,
23
+ HOSTNAME_DISPLAY_MAX: 100,
24
+ HOSTNAME_HASH_MAX: 64,
25
+ PLATFORM_MAX: 32,
26
+ ARCH_MAX: 32,
27
+ CLI_VERSION_MAX: 32,
28
+ HARNESS_MAX: 32,
29
+ SKILL_ID_MAX: 255,
30
+ VERSION_MAX: 64,
31
+ SOURCE_MAX: 255,
32
+ AUTHOR_MAX: 200,
33
+ LICENSE_MAX: 64,
34
+ REPOSITORY_MAX: 512,
35
+ CONTENT_HASH_MAX: 128,
36
+ PINNED_VERSION_MAX: 64,
37
+ UPDATE_POLICY_MAX: 16,
38
+ };
39
+ /** Allowed `update_policy` values (mirrors the DB CHECK constraint). */
40
+ export const INVENTORY_UPDATE_POLICIES = [
41
+ 'auto',
42
+ 'manual',
43
+ 'never',
44
+ ];
45
+ //# sourceMappingURL=inventory-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory-types.js","sourceRoot":"","sources":["../../../src/sync/inventory-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA4EH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,GAAG;IACd,oBAAoB,EAAE,GAAG;IACzB,iBAAiB,EAAE,EAAE;IACrB,YAAY,EAAE,EAAE;IAChB,QAAQ,EAAE,EAAE;IACZ,eAAe,EAAE,EAAE;IACnB,WAAW,EAAE,EAAE;IACf,YAAY,EAAE,GAAG;IACjB,WAAW,EAAE,EAAE;IACf,UAAU,EAAE,GAAG;IACf,UAAU,EAAE,GAAG;IACf,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,GAAG;IACnB,gBAAgB,EAAE,GAAG;IACrB,kBAAkB,EAAE,EAAE;IACtB,iBAAiB,EAAE,EAAE;CACb,CAAA;AAEV,wEAAwE;AACxE,MAAM,CAAC,MAAM,yBAAyB,GAAqC;IACzE,MAAM;IACN,QAAQ;IACR,OAAO;CACC,CAAA"}