@camstack/core 0.1.14 → 0.1.16

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 (352) hide show
  1. package/dist/addon/addon-api-factory.d.ts +36 -0
  2. package/dist/addon/addon-api-factory.d.ts.map +1 -0
  3. package/dist/addon-routes/addon-route-registry.d.ts +38 -0
  4. package/dist/addon-routes/addon-route-registry.d.ts.map +1 -0
  5. package/dist/auth/api-key-manager.d.ts +27 -0
  6. package/dist/auth/api-key-manager.d.ts.map +1 -0
  7. package/dist/auth/auth-manager.d.ts +47 -0
  8. package/dist/auth/auth-manager.d.ts.map +1 -0
  9. package/dist/auth/parse-record.d.ts +19 -0
  10. package/dist/auth/parse-record.d.ts.map +1 -0
  11. package/dist/auth/scoped-token-manager.d.ts +18 -0
  12. package/dist/auth/scoped-token-manager.d.ts.map +1 -0
  13. package/dist/auth/user-manager.d.ts +34 -0
  14. package/dist/auth/user-manager.d.ts.map +1 -0
  15. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts +54 -0
  16. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts.map +1 -0
  17. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +226 -0
  18. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js.map +1 -0
  19. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +218 -0
  20. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs.map +1 -0
  21. package/dist/builtins/addon-pages-aggregator/index.d.ts +2 -0
  22. package/dist/builtins/addon-pages-aggregator/index.d.ts.map +1 -0
  23. package/dist/builtins/addon-pages-aggregator/index.js +7 -0
  24. package/dist/builtins/addon-pages-aggregator/index.mjs +2 -0
  25. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts +33 -0
  26. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts.map +1 -0
  27. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +202 -0
  28. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js.map +1 -0
  29. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +194 -0
  30. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs.map +1 -0
  31. package/dist/builtins/addon-widgets-aggregator/index.d.ts +2 -0
  32. package/dist/builtins/addon-widgets-aggregator/index.d.ts.map +1 -0
  33. package/dist/builtins/addon-widgets-aggregator/index.js +7 -0
  34. package/dist/builtins/addon-widgets-aggregator/index.mjs +2 -0
  35. package/dist/builtins/alerts/alerts.addon.d.ts +82 -0
  36. package/dist/builtins/alerts/alerts.addon.d.ts.map +1 -0
  37. package/dist/builtins/alerts/alerts.addon.js +603 -0
  38. package/dist/builtins/alerts/alerts.addon.js.map +1 -0
  39. package/dist/builtins/alerts/alerts.addon.mjs +597 -0
  40. package/dist/builtins/alerts/alerts.addon.mjs.map +1 -0
  41. package/dist/builtins/alerts/index.d.ts +2 -0
  42. package/dist/builtins/alerts/index.d.ts.map +1 -0
  43. package/dist/builtins/alerts/index.js +3 -0
  44. package/dist/builtins/alerts/index.mjs +2 -0
  45. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts +8 -0
  46. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts.map +1 -0
  47. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js +56 -0
  48. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js.map +1 -0
  49. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs +50 -0
  50. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs.map +1 -0
  51. package/dist/builtins/auth-orchestrator/index.d.ts +2 -0
  52. package/dist/builtins/auth-orchestrator/index.d.ts.map +1 -0
  53. package/dist/builtins/auth-orchestrator/index.js +7 -0
  54. package/dist/builtins/auth-orchestrator/index.mjs +2 -0
  55. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +148 -0
  56. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts.map +1 -0
  57. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +7639 -0
  58. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js.map +1 -0
  59. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +7627 -0
  60. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs.map +1 -0
  61. package/dist/builtins/backup-orchestrator/cron-helpers.d.ts +24 -0
  62. package/dist/builtins/backup-orchestrator/cron-helpers.d.ts.map +1 -0
  63. package/dist/builtins/backup-orchestrator/destination-policy.d.ts +73 -0
  64. package/dist/builtins/backup-orchestrator/destination-policy.d.ts.map +1 -0
  65. package/dist/builtins/backup-orchestrator/download-helpers.d.ts +13 -0
  66. package/dist/builtins/backup-orchestrator/download-helpers.d.ts.map +1 -0
  67. package/dist/builtins/backup-orchestrator/index.d.ts +3 -0
  68. package/dist/builtins/backup-orchestrator/index.d.ts.map +1 -0
  69. package/dist/builtins/backup-orchestrator/index.js +7 -0
  70. package/dist/builtins/backup-orchestrator/index.mjs +2 -0
  71. package/dist/builtins/backup-orchestrator/manifest-store.d.ts +78 -0
  72. package/dist/builtins/backup-orchestrator/manifest-store.d.ts.map +1 -0
  73. package/dist/builtins/console-logging/console-destination.d.ts +14 -0
  74. package/dist/builtins/console-logging/console-destination.d.ts.map +1 -0
  75. package/dist/builtins/console-logging/console-logging.addon.d.ts +26 -0
  76. package/dist/builtins/console-logging/console-logging.addon.d.ts.map +1 -0
  77. package/dist/builtins/console-logging/index.d.ts +4 -0
  78. package/dist/builtins/console-logging/index.d.ts.map +1 -0
  79. package/dist/builtins/console-logging/index.js +106 -0
  80. package/dist/builtins/console-logging/index.js.map +1 -0
  81. package/dist/builtins/console-logging/index.mjs +97 -0
  82. package/dist/builtins/console-logging/index.mjs.map +1 -0
  83. package/dist/builtins/device-manager/device-event-propagator.d.ts +27 -0
  84. package/dist/builtins/device-manager/device-event-propagator.d.ts.map +1 -0
  85. package/dist/builtins/device-manager/device-manager.addon.d.ts +259 -0
  86. package/dist/builtins/device-manager/device-manager.addon.d.ts.map +1 -0
  87. package/dist/builtins/device-manager/device-manager.addon.js +2153 -0
  88. package/dist/builtins/device-manager/device-manager.addon.js.map +1 -0
  89. package/dist/builtins/device-manager/device-manager.addon.mjs +2147 -0
  90. package/dist/builtins/device-manager/device-manager.addon.mjs.map +1 -0
  91. package/dist/builtins/device-manager/index.d.ts +3 -0
  92. package/dist/builtins/device-manager/index.d.ts.map +1 -0
  93. package/dist/builtins/device-manager/index.js +7 -0
  94. package/dist/builtins/device-manager/index.mjs +2 -0
  95. package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +45 -0
  96. package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts.map +1 -0
  97. package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts +16 -0
  98. package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts.map +1 -0
  99. package/dist/builtins/hub-forwarder/index.d.ts +4 -0
  100. package/dist/builtins/hub-forwarder/index.d.ts.map +1 -0
  101. package/dist/builtins/hub-forwarder/index.js +156 -0
  102. package/dist/builtins/hub-forwarder/index.js.map +1 -0
  103. package/dist/builtins/hub-forwarder/index.mjs +147 -0
  104. package/dist/builtins/hub-forwarder/index.mjs.map +1 -0
  105. package/dist/builtins/local-auth/auth-schema.d.ts +12 -0
  106. package/dist/builtins/local-auth/auth-schema.d.ts.map +1 -0
  107. package/dist/builtins/local-auth/index.d.ts +2 -0
  108. package/dist/builtins/local-auth/index.d.ts.map +1 -0
  109. package/dist/builtins/local-auth/index.js +3 -0
  110. package/dist/builtins/local-auth/index.mjs +2 -0
  111. package/dist/builtins/local-auth/local-auth.addon.d.ts +17 -0
  112. package/dist/builtins/local-auth/local-auth.addon.d.ts.map +1 -0
  113. package/dist/builtins/local-auth/local-auth.addon.js +6895 -0
  114. package/dist/builtins/local-auth/local-auth.addon.js.map +1 -0
  115. package/dist/builtins/local-auth/local-auth.addon.mjs +6885 -0
  116. package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -0
  117. package/dist/builtins/local-network/index.d.ts +3 -0
  118. package/dist/builtins/local-network/index.d.ts.map +1 -0
  119. package/dist/builtins/local-network/index.js +9 -0
  120. package/dist/builtins/local-network/index.mjs +2 -0
  121. package/dist/builtins/local-network/local-network.addon.d.ts +102 -0
  122. package/dist/builtins/local-network/local-network.addon.d.ts.map +1 -0
  123. package/dist/builtins/local-network/local-network.addon.js +404 -0
  124. package/dist/builtins/local-network/local-network.addon.js.map +1 -0
  125. package/dist/builtins/local-network/local-network.addon.mjs +392 -0
  126. package/dist/builtins/local-network/local-network.addon.mjs.map +1 -0
  127. package/dist/builtins/mesh-orchestrator/index.d.ts +2 -0
  128. package/dist/builtins/mesh-orchestrator/index.d.ts.map +1 -0
  129. package/dist/builtins/mesh-orchestrator/index.js +7 -0
  130. package/dist/builtins/mesh-orchestrator/index.mjs +2 -0
  131. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts +9 -0
  132. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts.map +1 -0
  133. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js +83 -0
  134. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js.map +1 -0
  135. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs +77 -0
  136. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs.map +1 -0
  137. package/dist/builtins/native-metrics/index.d.ts +3 -0
  138. package/dist/builtins/native-metrics/index.d.ts.map +1 -0
  139. package/dist/builtins/native-metrics/native-metrics-provider.d.ts +49 -0
  140. package/dist/builtins/native-metrics/native-metrics-provider.d.ts.map +1 -0
  141. package/dist/builtins/native-metrics/native-metrics.addon.d.ts +74 -0
  142. package/dist/builtins/native-metrics/native-metrics.addon.d.ts.map +1 -0
  143. package/dist/builtins/native-metrics/native-metrics.addon.js +924 -0
  144. package/dist/builtins/native-metrics/native-metrics.addon.js.map +1 -0
  145. package/dist/builtins/native-metrics/native-metrics.addon.mjs +916 -0
  146. package/dist/builtins/native-metrics/native-metrics.addon.mjs.map +1 -0
  147. package/dist/builtins/platform-probe/index.d.ts +12 -0
  148. package/dist/builtins/platform-probe/index.d.ts.map +1 -0
  149. package/dist/builtins/platform-probe/index.js +539 -0
  150. package/dist/builtins/platform-probe/index.js.map +1 -0
  151. package/dist/builtins/platform-probe/index.mjs +530 -0
  152. package/dist/builtins/platform-probe/index.mjs.map +1 -0
  153. package/dist/builtins/platform-probe/inference-config-resolver.d.ts +30 -0
  154. package/dist/builtins/platform-probe/inference-config-resolver.d.ts.map +1 -0
  155. package/dist/builtins/platform-probe/platform-scorer.d.ts +22 -0
  156. package/dist/builtins/platform-probe/platform-scorer.d.ts.map +1 -0
  157. package/dist/builtins/remote-access-orchestrator/index.d.ts +2 -0
  158. package/dist/builtins/remote-access-orchestrator/index.d.ts.map +1 -0
  159. package/dist/builtins/remote-access-orchestrator/index.js +7 -0
  160. package/dist/builtins/remote-access-orchestrator/index.mjs +2 -0
  161. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +9 -0
  162. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts.map +1 -0
  163. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +72 -0
  164. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js.map +1 -0
  165. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +66 -0
  166. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs.map +1 -0
  167. package/dist/builtins/snapshot/index.d.ts +3 -0
  168. package/dist/builtins/snapshot/index.d.ts.map +1 -0
  169. package/dist/builtins/snapshot/index.js +494 -0
  170. package/dist/builtins/snapshot/index.js.map +1 -0
  171. package/dist/builtins/snapshot/index.mjs +488 -0
  172. package/dist/builtins/snapshot/index.mjs.map +1 -0
  173. package/dist/builtins/snapshot/snapshot.addon.d.ts +121 -0
  174. package/dist/builtins/snapshot/snapshot.addon.d.ts.map +1 -0
  175. package/dist/builtins/sqlite-storage/config-store.d.ts +9 -0
  176. package/dist/builtins/sqlite-storage/config-store.d.ts.map +1 -0
  177. package/dist/builtins/sqlite-storage/device-store.d.ts +24 -0
  178. package/dist/builtins/sqlite-storage/device-store.d.ts.map +1 -0
  179. package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts +87 -0
  180. package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts.map +1 -0
  181. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +32 -2
  182. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts.map +1 -0
  183. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +311 -205
  184. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js.map +1 -1
  185. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +305 -7
  186. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs.map +1 -1
  187. package/dist/builtins/sqlite-storage/index.d.ts +12 -4
  188. package/dist/builtins/sqlite-storage/index.d.ts.map +1 -0
  189. package/dist/builtins/sqlite-storage/index.js +258 -1097
  190. package/dist/builtins/sqlite-storage/index.js.map +1 -1
  191. package/dist/builtins/sqlite-storage/index.mjs +268 -28
  192. package/dist/builtins/sqlite-storage/index.mjs.map +1 -1
  193. package/dist/builtins/sqlite-storage/integration-registry.d.ts +28 -0
  194. package/dist/builtins/sqlite-storage/integration-registry.d.ts.map +1 -0
  195. package/dist/builtins/sqlite-storage/settings-store.d.ts +40 -0
  196. package/dist/builtins/sqlite-storage/settings-store.d.ts.map +1 -0
  197. package/dist/builtins/sqlite-storage/sql-schema.d.ts +33 -0
  198. package/dist/builtins/sqlite-storage/sql-schema.d.ts.map +1 -0
  199. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +94 -0
  200. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts.map +1 -0
  201. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +15 -2
  202. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts.map +1 -0
  203. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +588 -417
  204. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js.map +1 -1
  205. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +582 -7
  206. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs.map +1 -1
  207. package/dist/builtins/storage-orchestrator/index.d.ts +7 -0
  208. package/dist/builtins/storage-orchestrator/index.d.ts.map +1 -0
  209. package/dist/builtins/storage-orchestrator/index.js +9 -0
  210. package/dist/builtins/storage-orchestrator/index.mjs +2 -0
  211. package/dist/builtins/storage-orchestrator/location-store.d.ts +50 -0
  212. package/dist/builtins/storage-orchestrator/location-store.d.ts.map +1 -0
  213. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +60 -0
  214. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts.map +1 -0
  215. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +755 -0
  216. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js.map +1 -0
  217. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +746 -0
  218. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs.map +1 -0
  219. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +121 -0
  220. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts.map +1 -0
  221. package/dist/builtins/system-backup/system-backup.service.d.ts +138 -0
  222. package/dist/builtins/system-backup/system-backup.service.d.ts.map +1 -0
  223. package/dist/builtins/system-config/index.d.ts +2 -0
  224. package/dist/builtins/system-config/index.d.ts.map +1 -0
  225. package/dist/builtins/system-config/index.js +7 -0
  226. package/dist/builtins/system-config/index.mjs +2 -0
  227. package/dist/builtins/system-config/system-config.addon.d.ts +11 -0
  228. package/dist/builtins/system-config/system-config.addon.d.ts.map +1 -0
  229. package/dist/builtins/system-config/system-config.addon.js +234 -0
  230. package/dist/builtins/system-config/system-config.addon.js.map +1 -0
  231. package/dist/builtins/system-config/system-config.addon.mjs +228 -0
  232. package/dist/builtins/system-config/system-config.addon.mjs.map +1 -0
  233. package/dist/builtins/turn-orchestrator/index.d.ts +2 -0
  234. package/dist/builtins/turn-orchestrator/index.d.ts.map +1 -0
  235. package/dist/builtins/turn-orchestrator/index.js +7 -0
  236. package/dist/builtins/turn-orchestrator/index.mjs +2 -0
  237. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts +10 -0
  238. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts.map +1 -0
  239. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js +78 -0
  240. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js.map +1 -0
  241. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs +72 -0
  242. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs.map +1 -0
  243. package/dist/builtins/winston-logging/index.d.ts +4 -30
  244. package/dist/builtins/winston-logging/index.d.ts.map +1 -0
  245. package/dist/builtins/winston-logging/index.js +153 -180
  246. package/dist/builtins/winston-logging/index.js.map +1 -1
  247. package/dist/builtins/winston-logging/index.mjs +144 -8
  248. package/dist/builtins/winston-logging/index.mjs.map +1 -1
  249. package/dist/builtins/winston-logging/winston-destination.d.ts +22 -0
  250. package/dist/builtins/winston-logging/winston-destination.d.ts.map +1 -0
  251. package/dist/builtins/winston-logging/winston-logging.addon.d.ts +20 -0
  252. package/dist/builtins/winston-logging/winston-logging.addon.d.ts.map +1 -0
  253. package/dist/chunk-C13QxCFV.js +50 -0
  254. package/dist/chunk-hT5z_Zn9.mjs +35 -0
  255. package/dist/download/model-download-service.d.ts +42 -0
  256. package/dist/download/model-download-service.d.ts.map +1 -0
  257. package/dist/download/model-downloader.d.ts +32 -0
  258. package/dist/download/model-downloader.d.ts.map +1 -0
  259. package/dist/events/event-bus.d.ts +11 -0
  260. package/dist/events/event-bus.d.ts.map +1 -0
  261. package/dist/events/system-event-bus.d.ts +15 -0
  262. package/dist/events/system-event-bus.d.ts.map +1 -0
  263. package/dist/feature/feature-manager.d.ts +12 -0
  264. package/dist/feature/feature-manager.d.ts.map +1 -0
  265. package/dist/formatter-C-5An4Bl.mjs +164 -0
  266. package/dist/formatter-C-5An4Bl.mjs.map +1 -0
  267. package/dist/formatter-Dr_6NNZc.js +169 -0
  268. package/dist/formatter-Dr_6NNZc.js.map +1 -0
  269. package/dist/index.d.ts +76 -1137
  270. package/dist/index.d.ts.map +1 -0
  271. package/dist/index.js +7761 -7017
  272. package/dist/index.js.map +1 -1
  273. package/dist/index.mjs +7699 -3798
  274. package/dist/index.mjs.map +1 -1
  275. package/dist/lifecycle/lifecycle-state-machine.d.ts +29 -0
  276. package/dist/lifecycle/lifecycle-state-machine.d.ts.map +1 -0
  277. package/dist/logging/formatter.d.ts +31 -0
  278. package/dist/logging/formatter.d.ts.map +1 -0
  279. package/dist/logging/log-manager.d.ts +52 -0
  280. package/dist/logging/log-manager.d.ts.map +1 -0
  281. package/dist/logging/log-ring-buffer.d.ts +48 -0
  282. package/dist/logging/log-ring-buffer.d.ts.map +1 -0
  283. package/dist/logging/scoped-logger.d.ts +18 -0
  284. package/dist/logging/scoped-logger.d.ts.map +1 -0
  285. package/dist/network/network-quality.d.ts +12 -0
  286. package/dist/network/network-quality.d.ts.map +1 -0
  287. package/dist/notification/notification-service.d.ts +38 -0
  288. package/dist/notification/notification-service.d.ts.map +1 -0
  289. package/dist/notification/toast-service.d.ts +23 -0
  290. package/dist/notification/toast-service.d.ts.map +1 -0
  291. package/dist/pipeline/engine-manager-resolver.d.ts +16 -0
  292. package/dist/pipeline/engine-manager-resolver.d.ts.map +1 -0
  293. package/dist/pipeline/pipeline-runner.d.ts +9 -0
  294. package/dist/pipeline/pipeline-runner.d.ts.map +1 -0
  295. package/dist/pipeline/pipeline-validator.d.ts +14 -0
  296. package/dist/pipeline/pipeline-validator.d.ts.map +1 -0
  297. package/dist/process/resource-monitor.d.ts +12 -0
  298. package/dist/process/resource-monitor.d.ts.map +1 -0
  299. package/dist/python/python-env-manager.d.ts +13 -0
  300. package/dist/python/python-env-manager.d.ts.map +1 -0
  301. package/dist/repl/interfaces.d.ts +32 -0
  302. package/dist/repl/interfaces.d.ts.map +1 -0
  303. package/dist/repl/repl-engine.d.ts +9 -0
  304. package/dist/repl/repl-engine.d.ts.map +1 -0
  305. package/dist/resource-monitor-CmuWlmap.js +76 -0
  306. package/dist/resource-monitor-CmuWlmap.js.map +1 -0
  307. package/dist/resource-monitor-DcQdKGYU.mjs +59 -0
  308. package/dist/resource-monitor-DcQdKGYU.mjs.map +1 -0
  309. package/dist/storage/fs-storage-backend.d.ts +41 -0
  310. package/dist/storage/fs-storage-backend.d.ts.map +1 -0
  311. package/dist/storage/storage-location-manager.d.ts +24 -0
  312. package/dist/storage/storage-location-manager.d.ts.map +1 -0
  313. package/dist/storage/storage-manager.d.ts +77 -0
  314. package/dist/storage/storage-manager.d.ts.map +1 -0
  315. package/dist/tls/cert-manager.d.ts +27 -0
  316. package/dist/tls/cert-manager.d.ts.map +1 -0
  317. package/dist/tls/index.d.ts +2 -0
  318. package/dist/tls/index.d.ts.map +1 -0
  319. package/package.json +230 -13
  320. package/dist/builtins/local-backup/index.d.mts +0 -42
  321. package/dist/builtins/local-backup/index.d.ts +0 -42
  322. package/dist/builtins/local-backup/index.js +0 -188
  323. package/dist/builtins/local-backup/index.js.map +0 -1
  324. package/dist/builtins/local-backup/index.mjs +0 -10
  325. package/dist/builtins/local-backup/index.mjs.map +0 -1
  326. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.mts +0 -2
  327. package/dist/builtins/sqlite-storage/index.d.mts +0 -4
  328. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.mts +0 -2
  329. package/dist/builtins/winston-logging/index.d.mts +0 -30
  330. package/dist/chunk-2F3XZYRW.mjs +0 -89
  331. package/dist/chunk-2F3XZYRW.mjs.map +0 -1
  332. package/dist/chunk-LQFPAEQF.mjs +0 -147
  333. package/dist/chunk-LQFPAEQF.mjs.map +0 -1
  334. package/dist/chunk-R3DIIBBX.mjs +0 -532
  335. package/dist/chunk-R3DIIBBX.mjs.map +0 -1
  336. package/dist/chunk-SMNR44VG.mjs +0 -386
  337. package/dist/chunk-SMNR44VG.mjs.map +0 -1
  338. package/dist/chunk-SO4LROOT.mjs +0 -150
  339. package/dist/chunk-SO4LROOT.mjs.map +0 -1
  340. package/dist/chunk-SPA4JBKN.mjs +0 -175
  341. package/dist/chunk-SPA4JBKN.mjs.map +0 -1
  342. package/dist/dist-3BY63UQ5.mjs +0 -2151
  343. package/dist/dist-3BY63UQ5.mjs.map +0 -1
  344. package/dist/filesystem-storage.addon-C42r589X.d.mts +0 -57
  345. package/dist/filesystem-storage.addon-C42r589X.d.ts +0 -57
  346. package/dist/index.d.mts +0 -1137
  347. package/dist/sql-schema-CKz78rId.d.mts +0 -97
  348. package/dist/sql-schema-CKz78rId.d.ts +0 -97
  349. package/dist/sqlite-settings.addon-KwG-uKMP.d.mts +0 -79
  350. package/dist/sqlite-settings.addon-KwG-uKMP.d.ts +0 -79
  351. package/dist/storage-location-manager-KKDQNAKA.mjs +0 -7
  352. package/dist/storage-location-manager-KKDQNAKA.mjs.map +0 -1
@@ -0,0 +1,3 @@
1
+ export { LocalNetworkAddon, classifyKind, prefixLen } from './local-network.addon.js';
2
+ export { LocalNetworkAddon as default } from './local-network.addon.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/builtins/local-network/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACrF,OAAO,EAAE,iBAAiB,IAAI,OAAO,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,9 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_builtins_local_network_local_network_addon = require("./local-network.addon.js");
6
+ exports.LocalNetworkAddon = require_builtins_local_network_local_network_addon.LocalNetworkAddon;
7
+ exports.classifyKind = require_builtins_local_network_local_network_addon.classifyKind;
8
+ exports.default = require_builtins_local_network_local_network_addon.LocalNetworkAddon;
9
+ exports.prefixLen = require_builtins_local_network_local_network_addon.prefixLen;
@@ -0,0 +1,2 @@
1
+ import { LocalNetworkAddon, classifyKind, prefixLen } from "./local-network.addon.mjs";
2
+ export { LocalNetworkAddon, LocalNetworkAddon as default, classifyKind, prefixLen };
@@ -0,0 +1,102 @@
1
+ import { ProviderRegistration, LocalInterface, ConnectionEndpoint, BaseAddon } from '@camstack/types';
2
+ interface LocalNetworkConfig {
3
+ /** Empty = "auto" (every non-loopback / non-link-local address
4
+ * participates). Non-empty restricts the candidate set to only
5
+ * those operator-pinned addresses. */
6
+ readonly allowedAddresses: readonly string[];
7
+ /** Sentinel — `true` after the first-boot auto-seed runs. Lets the
8
+ * addon distinguish "fresh install, never touched" (false → seed
9
+ * with LAN/Wi-Fi addresses) from "operator explicitly cleared the
10
+ * allowlist" (true + empty → respect operator's choice). */
11
+ readonly bootSeeded: boolean;
12
+ }
13
+ export declare class LocalNetworkAddon extends BaseAddon<LocalNetworkConfig> {
14
+ private pollTimer;
15
+ private lastSnapshotKey;
16
+ /** Optional public hostname tracked from `NetworkTunnelStarted`/
17
+ * `Stopped` events on the bus. */
18
+ private publicHostname;
19
+ constructor();
20
+ protected onInitialize(): Promise<ProviderRegistration[]>;
21
+ protected onShutdown(): Promise<void>;
22
+ /**
23
+ * Other hub addons (e.g. cloudflare-tunnel) signal the active public
24
+ * FQDN by emitting `NetworkTunnelStarted` on the bus — handled in
25
+ * `onInitialize`. This setter exists for tests + future direct
26
+ * callers; cleared by passing an empty string.
27
+ */
28
+ setPublicHostname(hostname: string): void;
29
+ private enumerate;
30
+ private detectChanges;
31
+ }
32
+ /**
33
+ * Lift `os.networkInterfaces()` into our `LocalInterface[]` shape with
34
+ * kind classification + preferred flag. Pure — takes the raw result so
35
+ * tests can feed synthetic data.
36
+ */
37
+ export declare function enumerateOsInterfaces(ifaces: NodeJS.Dict<NodeJS.NetworkInterfaceInfo[]>): readonly LocalInterface[];
38
+ /**
39
+ * Filter the interface list by the operator's allowlist. Empty
40
+ * allowlist = no-op (every interface passes); otherwise only entries
41
+ * whose `address` matches an allowlist entry remain. Loopback always
42
+ * survives so the SDK keeps `127.0.0.1` as the last-resort fallback.
43
+ */
44
+ export declare function applyAllowlist(interfaces: readonly LocalInterface[], allowed: readonly string[]): readonly LocalInterface[];
45
+ /**
46
+ * Rank interfaces and pick the auto-selected outbound one. See the
47
+ * cap's `getPreferred` doc for the heuristic.
48
+ */
49
+ export declare function pickPreferred(interfaces: readonly LocalInterface[]): LocalInterface | null;
50
+ /**
51
+ * Build the ordered candidate URL list. Priority schema:
52
+ * 0 — preferred LAN IPv4
53
+ * 10+ — other LAN IPv4
54
+ * 100 — public tunnel hostname (always HTTPS)
55
+ * 200+ — LAN IPv6
56
+ * 1000 — loopback (last resort)
57
+ *
58
+ * `scheme` controls LAN + loopback URLs. Browsers running over HTTPS
59
+ * block `http://` candidates as mixed content, so callers loaded over
60
+ * HTTPS should pass `scheme: 'https'` even when probing a LAN IP — the
61
+ * hub's cert manager already issues a SAN-multi cert covering local
62
+ * interfaces. The public tunnel always emits `https://` (Cloudflare
63
+ * terminates TLS for us).
64
+ */
65
+ export declare function buildEndpoints(interfaces: readonly LocalInterface[], port: number, includeLoopback: boolean, ipv4Only: boolean, publicHostname: string, scheme?: 'http' | 'https'): ConnectionEndpoint[];
66
+ /**
67
+ * First-boot heuristic: which addresses should the allowlist start
68
+ * with? Includes LAN + Wi-Fi IPv4 addresses + plausible IPv6:
69
+ *
70
+ * - **IPv4**: skip link-local (`169.254.*`), keep the rest.
71
+ * - **IPv6**: skip link-local (`fe80::*`), unspecified, and
72
+ * multicast. Keep ULAs (`fc00::/7` → `fc??:` / `fd??:`) and Global
73
+ * Unicast addresses (`2000::/3` → `2???`/`3???`). Privacy-extension
74
+ * temporary addresses get included by default; the operator can
75
+ * prune them from the Network Addresses tab if the rotating IPs
76
+ * become a nuisance.
77
+ *
78
+ * Skips docker/vpn/loopback/other entirely — those stay opt-in.
79
+ */
80
+ export declare function autoSeedAllowlist(interfaces: readonly LocalInterface[]): string[];
81
+ /**
82
+ * Per-interface tooltip text surfaced on the "Unlikely usable" badge.
83
+ * Server-side so the UI doesn't re-derive the rationale (single source
84
+ * of truth). Returns `''` for plausible entries; the addon overlays
85
+ * this on the `LocalInterface.plausibleReason` field.
86
+ */
87
+ export declare function explainNonPlausible(input: {
88
+ readonly kind: LocalInterface['kind'];
89
+ readonly family: 'IPv4' | 'IPv6';
90
+ readonly address: string;
91
+ readonly internal: boolean;
92
+ }): string;
93
+ /**
94
+ * Per-address gate used by `autoSeedAllowlist`. Exposed for tests so
95
+ * we can pin every classification rule without standing up the addon.
96
+ */
97
+ export declare function isPlausibleAutoSeed(address: string, family: 'IPv4' | 'IPv6'): boolean;
98
+ export declare function classifyKind(name: string, address: string, internal: boolean): LocalInterface['kind'];
99
+ /** Convert an IPv4/IPv6 netmask string to its prefix length (CIDR). */
100
+ export declare function prefixLen(netmask: string): number;
101
+ export {};
102
+ //# sourceMappingURL=local-network.addon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-network.addon.d.ts","sourceRoot":"","sources":["../../../src/builtins/local-network/local-network.addon.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,oBAAoB,EAEpB,cAAc,EACd,kBAAkB,EACnB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,SAAS,EAAyC,MAAM,iBAAiB,CAAA;AAclF,UAAU,kBAAkB;IAC1B;;2CAEuC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5C;;;iEAG6D;IAC7D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAC7B;AAED,qBAAa,iBAAkB,SAAQ,SAAS,CAAC,kBAAkB,CAAC;IAClE,OAAO,CAAC,SAAS,CAA8B;IAC/C,OAAO,CAAC,eAAe,CAAK;IAC5B;uCACmC;IACnC,OAAO,CAAC,cAAc,CAAK;;cAMX,YAAY,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;cAgG/C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3C;;;;;OAKG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAUzC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,aAAa;CAkBtB;AAID;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC,GACjD,SAAS,cAAc,EAAE,CAqD3B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,SAAS,cAAc,EAAE,EACrC,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,SAAS,cAAc,EAAE,CAI3B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,GAAG,cAAc,GAAG,IAAI,CAoB1F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,SAAS,cAAc,EAAE,EACrC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,OAAO,EACxB,QAAQ,EAAE,OAAO,EACjB,cAAc,EAAE,MAAM,EACtB,MAAM,GAAE,MAAM,GAAG,OAAgB,GAChC,kBAAkB,EAAE,CAwFtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,EAAE,CAQjF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC3B,GAAG,MAAM,CAcT;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAgBrF;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,OAAO,GAChB,cAAc,CAAC,MAAM,CAAC,CAaxB;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAyBjD"}
@@ -0,0 +1,404 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_chunk = require("../../chunk-C13QxCFV.js");
3
+ let _camstack_types = require("@camstack/types");
4
+ let node_os = require("node:os");
5
+ node_os = require_chunk.__toESM(node_os);
6
+ //#region src/builtins/local-network/local-network.addon.ts
7
+ /**
8
+ * local-network — hub-only system cap implementation.
9
+ *
10
+ * Wraps `os.networkInterfaces()` with:
11
+ * - Coarse kind classification (lan/wifi/docker/vpn/loopback/other)
12
+ * - Auto-select heuristic for the outbound interface
13
+ * - Periodic poll (30s) + diff to emit `LocalNetworkChanged` events
14
+ * so subscribers can react to DHCP renewals, VPN connect, etc.
15
+ * - `getConnectionEndpoints()` — ranked URL list for SDK clients
16
+ *
17
+ * Does NOT poll the cloudflare-tunnel state directly; the public
18
+ * tunnel hostname (if any) is provided by `network-access` consumers
19
+ * via `NetworkTunnelStarted/Stopped` events on the bus, so the cap
20
+ * stays free of cross-addon dependencies.
21
+ */
22
+ var POLL_INTERVAL_MS = 3e4;
23
+ var LocalNetworkAddon = class extends _camstack_types.BaseAddon {
24
+ pollTimer = null;
25
+ lastSnapshotKey = "";
26
+ /** Optional public hostname tracked from `NetworkTunnelStarted`/
27
+ * `Stopped` events on the bus. */
28
+ publicHostname = "";
29
+ constructor() {
30
+ super({
31
+ allowedAddresses: [],
32
+ bootSeeded: false
33
+ });
34
+ }
35
+ async onInitialize() {
36
+ if (!this.config.bootSeeded) {
37
+ const seed = autoSeedAllowlist(this.enumerate());
38
+ await this.updateGlobalSettings({
39
+ allowedAddresses: seed,
40
+ bootSeeded: true
41
+ });
42
+ this.ctx.logger.info("local-network: first-boot auto-seed", { meta: { addresses: seed } });
43
+ }
44
+ const provider = {
45
+ list: async () => ({
46
+ interfaces: this.enumerate(),
47
+ probedAt: Date.now()
48
+ }),
49
+ getPreferred: async () => pickPreferred(applyAllowlist(this.enumerate(), this.config.allowedAddresses)),
50
+ getConnectionEndpoints: async (input) => {
51
+ const includeLoopback = input.includeLoopback ?? true;
52
+ const ipv4Only = input.ipv4Only ?? false;
53
+ const scheme = input.scheme ?? "http";
54
+ const allow = this.config.allowedAddresses;
55
+ return { endpoints: buildEndpoints(applyAllowlist(this.enumerate(), allow), input.port, includeLoopback, ipv4Only, this.publicHostname, scheme) };
56
+ },
57
+ getAllowedAddresses: async () => ({ addresses: this.config.allowedAddresses }),
58
+ resetAllowlistToBestMatch: async () => {
59
+ const seed = autoSeedAllowlist(this.enumerate());
60
+ await this.updateGlobalSettings({
61
+ allowedAddresses: seed,
62
+ bootSeeded: true
63
+ });
64
+ this.ctx.logger.info("local-network: allowlist reset to auto-seed", { meta: { count: seed.length } });
65
+ return { addresses: seed };
66
+ },
67
+ setAllowedAddresses: async ({ addresses }) => {
68
+ const known = new Set(this.enumerate().map((i) => i.address));
69
+ const cleaned = [...new Set(addresses)].filter((a) => known.has(a));
70
+ await this.updateGlobalSettings({ allowedAddresses: cleaned });
71
+ this.ctx.logger.info("local-network: allowlist updated", { meta: {
72
+ count: cleaned.length,
73
+ dropped: addresses.length - cleaned.length
74
+ } });
75
+ return { success: true };
76
+ }
77
+ };
78
+ this.lastSnapshotKey = snapshotKey(this.enumerate());
79
+ this.pollTimer = setInterval(() => this.detectChanges(), POLL_INTERVAL_MS);
80
+ this.pollTimer.unref?.();
81
+ this.ctx.eventBus?.subscribe({ category: _camstack_types.EventCategory.NetworkTunnelStarted }, (event) => {
82
+ const data = event.data ?? {};
83
+ if (typeof data.url === "string") try {
84
+ const hostname = new URL(data.url).hostname;
85
+ if (hostname && !hostname.endsWith(".placeholder") && !hostname.startsWith("pending.")) this.setPublicHostname(hostname);
86
+ } catch {}
87
+ });
88
+ this.ctx.eventBus?.subscribe({ category: _camstack_types.EventCategory.NetworkTunnelStopped }, () => this.setPublicHostname(""));
89
+ this.ctx.logger.info("local-network initialized", { meta: { interfaceCount: this.enumerate().length } });
90
+ return [{
91
+ capability: _camstack_types.localNetworkCapability,
92
+ provider
93
+ }];
94
+ }
95
+ async onShutdown() {
96
+ if (this.pollTimer) {
97
+ clearInterval(this.pollTimer);
98
+ this.pollTimer = null;
99
+ }
100
+ }
101
+ /**
102
+ * Other hub addons (e.g. cloudflare-tunnel) signal the active public
103
+ * FQDN by emitting `NetworkTunnelStarted` on the bus — handled in
104
+ * `onInitialize`. This setter exists for tests + future direct
105
+ * callers; cleared by passing an empty string.
106
+ */
107
+ setPublicHostname(hostname) {
108
+ if (this.publicHostname === hostname) return;
109
+ this.publicHostname = hostname;
110
+ this.ctx.logger.info("local-network: public hostname updated", { meta: { hostname: hostname || "(cleared)" } });
111
+ }
112
+ enumerate() {
113
+ return enumerateOsInterfaces(node_os.networkInterfaces());
114
+ }
115
+ detectChanges() {
116
+ const interfaces = this.enumerate();
117
+ const key = snapshotKey(interfaces);
118
+ if (key === this.lastSnapshotKey) return;
119
+ this.ctx.logger.info("local-network: interface set changed", { meta: {
120
+ count: interfaces.length,
121
+ key
122
+ } });
123
+ this.lastSnapshotKey = key;
124
+ this.ctx.eventBus?.emit({
125
+ id: `local-network-changed-${Date.now()}`,
126
+ timestamp: /* @__PURE__ */ new Date(),
127
+ source: {
128
+ type: "core",
129
+ id: "local-network"
130
+ },
131
+ category: _camstack_types.EventCategory.LocalNetworkChanged,
132
+ data: { count: interfaces.length }
133
+ });
134
+ }
135
+ };
136
+ /**
137
+ * Lift `os.networkInterfaces()` into our `LocalInterface[]` shape with
138
+ * kind classification + preferred flag. Pure — takes the raw result so
139
+ * tests can feed synthetic data.
140
+ */
141
+ function enumerateOsInterfaces(ifaces) {
142
+ const raw = [];
143
+ for (const [name, addrs] of Object.entries(ifaces)) {
144
+ if (!addrs) continue;
145
+ for (const a of addrs) {
146
+ if (a.family !== "IPv4" && a.family !== "IPv6") continue;
147
+ raw.push({
148
+ name,
149
+ family: a.family,
150
+ address: a.address,
151
+ cidr: a.cidr ?? "",
152
+ netmask: a.netmask,
153
+ internal: a.internal,
154
+ mac: a.mac
155
+ });
156
+ }
157
+ }
158
+ const classified = raw.map((r) => {
159
+ const kind = classifyKind(r.name, r.address, r.internal);
160
+ const reachableKind = kind === "lan" || kind === "wifi";
161
+ const plausible = !r.internal && reachableKind && isPlausibleAutoSeed(r.address, r.family);
162
+ const plausibleReason = plausible ? "" : explainNonPlausible({
163
+ kind,
164
+ family: r.family,
165
+ address: r.address,
166
+ internal: r.internal
167
+ });
168
+ return {
169
+ name: r.name,
170
+ family: r.family,
171
+ address: r.address,
172
+ cidr: r.cidr,
173
+ netmask: r.netmask,
174
+ internal: r.internal,
175
+ mac: r.mac,
176
+ kind,
177
+ preferred: false,
178
+ plausible,
179
+ plausibleReason
180
+ };
181
+ });
182
+ const preferred = pickPreferred(classified);
183
+ return classified.map((iface) => ({
184
+ ...iface,
185
+ preferred: preferred !== null && iface.name === preferred.name && iface.address === preferred.address
186
+ }));
187
+ }
188
+ /**
189
+ * Filter the interface list by the operator's allowlist. Empty
190
+ * allowlist = no-op (every interface passes); otherwise only entries
191
+ * whose `address` matches an allowlist entry remain. Loopback always
192
+ * survives so the SDK keeps `127.0.0.1` as the last-resort fallback.
193
+ */
194
+ function applyAllowlist(interfaces, allowed) {
195
+ if (allowed.length === 0) return interfaces;
196
+ const set = new Set(allowed);
197
+ return interfaces.filter((i) => i.kind === "loopback" || set.has(i.address));
198
+ }
199
+ /**
200
+ * Rank interfaces and pick the auto-selected outbound one. See the
201
+ * cap's `getPreferred` doc for the heuristic.
202
+ */
203
+ function pickPreferred(interfaces) {
204
+ const candidates = interfaces.filter((i) => !i.internal && i.family === "IPv4" && !i.address.startsWith("169.254.") && i.kind !== "loopback");
205
+ if (candidates.length === 0) return null;
206
+ const kindRank = {
207
+ lan: 1,
208
+ wifi: 2,
209
+ vpn: 3,
210
+ docker: 4,
211
+ other: 5,
212
+ loopback: 99
213
+ };
214
+ return [...candidates].sort((a, b) => {
215
+ const ra = kindRank[a.kind];
216
+ const rb = kindRank[b.kind];
217
+ if (ra !== rb) return ra - rb;
218
+ return prefixLen(b.netmask) - prefixLen(a.netmask);
219
+ })[0] ?? null;
220
+ }
221
+ /**
222
+ * Build the ordered candidate URL list. Priority schema:
223
+ * 0 — preferred LAN IPv4
224
+ * 10+ — other LAN IPv4
225
+ * 100 — public tunnel hostname (always HTTPS)
226
+ * 200+ — LAN IPv6
227
+ * 1000 — loopback (last resort)
228
+ *
229
+ * `scheme` controls LAN + loopback URLs. Browsers running over HTTPS
230
+ * block `http://` candidates as mixed content, so callers loaded over
231
+ * HTTPS should pass `scheme: 'https'` even when probing a LAN IP — the
232
+ * hub's cert manager already issues a SAN-multi cert covering local
233
+ * interfaces. The public tunnel always emits `https://` (Cloudflare
234
+ * terminates TLS for us).
235
+ */
236
+ function buildEndpoints(interfaces, port, includeLoopback, ipv4Only, publicHostname, scheme = "http") {
237
+ const out = [];
238
+ let priority = 0;
239
+ const preferred = pickPreferred(interfaces);
240
+ const emit = (iface, kind, label, baseUrl, pri) => {
241
+ out.push({
242
+ label,
243
+ baseUrl,
244
+ kind,
245
+ interfaceKind: iface.kind,
246
+ plausible: iface.plausible,
247
+ plausibleReason: iface.plausibleReason,
248
+ priority: pri
249
+ });
250
+ };
251
+ if (preferred) emit(preferred, "lan-ipv4", `${formatKind(preferred.kind)} — ${preferred.name}`, `${scheme}://${preferred.address}:${port}`, priority++);
252
+ for (const iface of interfaces) {
253
+ if (iface.internal || iface.family !== "IPv4") continue;
254
+ if (iface.kind === "loopback") continue;
255
+ if (preferred && iface.name === preferred.name && iface.address === preferred.address) continue;
256
+ if (iface.address.startsWith("169.254.")) continue;
257
+ emit(iface, "lan-ipv4", `${formatKind(iface.kind)} — ${iface.name}`, `${scheme}://${iface.address}:${port}`, 10 + priority++);
258
+ }
259
+ if (publicHostname) out.push({
260
+ label: "Public tunnel",
261
+ baseUrl: `https://${publicHostname}`,
262
+ kind: "public",
263
+ interfaceKind: "public",
264
+ plausible: true,
265
+ plausibleReason: "",
266
+ priority: 100
267
+ });
268
+ if (!ipv4Only) {
269
+ let v6prio = 200;
270
+ for (const iface of interfaces) {
271
+ if (iface.internal || iface.family !== "IPv6") continue;
272
+ if (iface.kind === "loopback") continue;
273
+ if (iface.address.startsWith("fe80:")) continue;
274
+ emit(iface, "lan-ipv6", `${formatKind(iface.kind)} — ${iface.name} (IPv6)`, `${scheme}://[${iface.address}]:${port}`, v6prio++);
275
+ }
276
+ }
277
+ if (includeLoopback) out.push({
278
+ label: "Loopback",
279
+ baseUrl: `${scheme}://127.0.0.1:${port}`,
280
+ kind: "loopback",
281
+ interfaceKind: "loopback",
282
+ plausible: false,
283
+ plausibleReason: "Loopback — last-resort fallback when no other endpoint responds.",
284
+ priority: 1e3
285
+ });
286
+ return out.sort((a, b) => a.priority - b.priority);
287
+ }
288
+ /**
289
+ * First-boot heuristic: which addresses should the allowlist start
290
+ * with? Includes LAN + Wi-Fi IPv4 addresses + plausible IPv6:
291
+ *
292
+ * - **IPv4**: skip link-local (`169.254.*`), keep the rest.
293
+ * - **IPv6**: skip link-local (`fe80::*`), unspecified, and
294
+ * multicast. Keep ULAs (`fc00::/7` → `fc??:` / `fd??:`) and Global
295
+ * Unicast addresses (`2000::/3` → `2???`/`3???`). Privacy-extension
296
+ * temporary addresses get included by default; the operator can
297
+ * prune them from the Network Addresses tab if the rotating IPs
298
+ * become a nuisance.
299
+ *
300
+ * Skips docker/vpn/loopback/other entirely — those stay opt-in.
301
+ */
302
+ function autoSeedAllowlist(interfaces) {
303
+ return [...new Set(interfaces.filter((i) => !i.internal && (i.kind === "lan" || i.kind === "wifi") && isPlausibleAutoSeed(i.address, i.family)).map((i) => i.address))];
304
+ }
305
+ /**
306
+ * Per-interface tooltip text surfaced on the "Unlikely usable" badge.
307
+ * Server-side so the UI doesn't re-derive the rationale (single source
308
+ * of truth). Returns `''` for plausible entries; the addon overlays
309
+ * this on the `LocalInterface.plausibleReason` field.
310
+ */
311
+ function explainNonPlausible(input) {
312
+ if (input.internal) return "Internal interface (loopback) — not reachable from clients.";
313
+ if (input.kind === "docker") return "Docker bridge — only reachable from inside the container network.";
314
+ if (input.kind === "vpn") return "VPN tunnel — only reachable while the VPN is connected.";
315
+ if (input.kind === "other") return "Unrecognised interface kind — verify reachability before pinning.";
316
+ if (input.family === "IPv6") {
317
+ const a = input.address.toLowerCase();
318
+ if (a.startsWith("fe80:")) return "IPv6 link-local — only reachable on the same link, not routed.";
319
+ if (a.startsWith("ff")) return "IPv6 multicast — not a unicast address.";
320
+ if (a === "::" || a === "::1") return "IPv6 loopback / unspecified — not a public address.";
321
+ return "IPv6 address outside the ULA / GUA ranges — verify before pinning.";
322
+ }
323
+ if (input.address.startsWith("169.254.")) return "IPv4 link-local (RFC 3927) — only valid when DHCP fails.";
324
+ return "Address looks unusual for client traffic — verify before pinning.";
325
+ }
326
+ /**
327
+ * Per-address gate used by `autoSeedAllowlist`. Exposed for tests so
328
+ * we can pin every classification rule without standing up the addon.
329
+ */
330
+ function isPlausibleAutoSeed(address, family) {
331
+ if (family === "IPv4") {
332
+ if (address.startsWith("169.254.")) return false;
333
+ return true;
334
+ }
335
+ const a = address.toLowerCase();
336
+ if (a === "::" || a === "::1") return false;
337
+ if (a.startsWith("fe80:")) return false;
338
+ if (a.startsWith("ff")) return false;
339
+ if (/^f[cd][0-9a-f]{0,2}:/.test(a)) return true;
340
+ if (/^[23][0-9a-f]{0,3}:/.test(a)) return true;
341
+ return false;
342
+ }
343
+ function classifyKind(name, address, internal) {
344
+ if (internal || name === "lo" || name.startsWith("lo")) return "loopback";
345
+ const n = name.toLowerCase();
346
+ if (n.startsWith("docker") || n.startsWith("br-") || n.startsWith("veth")) return "docker";
347
+ if (n.startsWith("tun") || n.startsWith("utun") || n.startsWith("wg") || n.startsWith("tap")) return "vpn";
348
+ if (n.startsWith("wlan") || n.startsWith("wlp") || n.startsWith("wlx")) return "wifi";
349
+ if (n.startsWith("eth") || /^en\d+$/.test(n)) {
350
+ if (process.platform === "darwin" && /^en[1-9]\d*$/.test(n)) return "wifi";
351
+ return "lan";
352
+ }
353
+ if (address === "127.0.0.1" || address === "::1") return "loopback";
354
+ return "other";
355
+ }
356
+ /** Convert an IPv4/IPv6 netmask string to its prefix length (CIDR). */
357
+ function prefixLen(netmask) {
358
+ if (!netmask) return 0;
359
+ if (netmask.includes(":")) {
360
+ let bits = 0;
361
+ for (const group of netmask.split(":")) {
362
+ if (!group) continue;
363
+ const n = parseInt(group, 16);
364
+ if (!Number.isFinite(n)) break;
365
+ for (let mask = 32768; mask; mask >>= 1) if (n & mask) bits++;
366
+ else return bits;
367
+ }
368
+ return bits;
369
+ }
370
+ let bits = 0;
371
+ for (const part of netmask.split(".")) {
372
+ const n = parseInt(part, 10);
373
+ if (!Number.isFinite(n)) break;
374
+ for (let mask = 128; mask; mask >>= 1) if (n & mask) bits++;
375
+ else return bits;
376
+ }
377
+ return bits;
378
+ }
379
+ function snapshotKey(interfaces) {
380
+ return [...interfaces].map((i) => `${i.name}|${i.family}|${i.address}|${i.netmask}`).sort().join("\n");
381
+ }
382
+ function formatKind(kind) {
383
+ switch (kind) {
384
+ case "lan": return "LAN";
385
+ case "wifi": return "Wi-Fi";
386
+ case "vpn": return "VPN";
387
+ case "docker": return "Docker";
388
+ case "loopback": return "Loopback";
389
+ case "other": return "Other";
390
+ }
391
+ }
392
+ //#endregion
393
+ exports.LocalNetworkAddon = LocalNetworkAddon;
394
+ exports.applyAllowlist = applyAllowlist;
395
+ exports.autoSeedAllowlist = autoSeedAllowlist;
396
+ exports.buildEndpoints = buildEndpoints;
397
+ exports.classifyKind = classifyKind;
398
+ exports.enumerateOsInterfaces = enumerateOsInterfaces;
399
+ exports.explainNonPlausible = explainNonPlausible;
400
+ exports.isPlausibleAutoSeed = isPlausibleAutoSeed;
401
+ exports.pickPreferred = pickPreferred;
402
+ exports.prefixLen = prefixLen;
403
+
404
+ //# sourceMappingURL=local-network.addon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-network.addon.js","names":[],"sources":["../../../src/builtins/local-network/local-network.addon.ts"],"sourcesContent":["/**\n * local-network — hub-only system cap implementation.\n *\n * Wraps `os.networkInterfaces()` with:\n * - Coarse kind classification (lan/wifi/docker/vpn/loopback/other)\n * - Auto-select heuristic for the outbound interface\n * - Periodic poll (30s) + diff to emit `LocalNetworkChanged` events\n * so subscribers can react to DHCP renewals, VPN connect, etc.\n * - `getConnectionEndpoints()` — ranked URL list for SDK clients\n *\n * Does NOT poll the cloudflare-tunnel state directly; the public\n * tunnel hostname (if any) is provided by `network-access` consumers\n * via `NetworkTunnelStarted/Stopped` events on the bus, so the cap\n * stays free of cross-addon dependencies.\n */\nimport * as os from 'node:os'\n\nimport type {\n ProviderRegistration,\n ILocalNetworkProvider,\n LocalInterface,\n ConnectionEndpoint,\n} from '@camstack/types'\nimport { BaseAddon, localNetworkCapability, EventCategory } from '@camstack/types'\n\ninterface RawIface {\n readonly name: string\n readonly family: 'IPv4' | 'IPv6'\n readonly address: string\n readonly cidr: string\n readonly netmask: string\n readonly internal: boolean\n readonly mac: string\n}\n\nconst POLL_INTERVAL_MS = 30_000\n\ninterface LocalNetworkConfig {\n /** Empty = \"auto\" (every non-loopback / non-link-local address\n * participates). Non-empty restricts the candidate set to only\n * those operator-pinned addresses. */\n readonly allowedAddresses: readonly string[]\n /** Sentinel — `true` after the first-boot auto-seed runs. Lets the\n * addon distinguish \"fresh install, never touched\" (false → seed\n * with LAN/Wi-Fi addresses) from \"operator explicitly cleared the\n * allowlist\" (true + empty → respect operator's choice). */\n readonly bootSeeded: boolean\n}\n\nexport class LocalNetworkAddon extends BaseAddon<LocalNetworkConfig> {\n private pollTimer: NodeJS.Timeout | null = null\n private lastSnapshotKey = ''\n /** Optional public hostname tracked from `NetworkTunnelStarted`/\n * `Stopped` events on the bus. */\n private publicHostname = ''\n\n constructor() {\n super({ allowedAddresses: [], bootSeeded: false })\n }\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n // First-boot auto-seed: on fresh installs, pre-populate the\n // allowlist with addresses from interfaces classified as `lan` or\n // `wifi`. Operators usually want those participating; docker/vpn\n // entries stay opt-in. Loopback is always implicit (no need to\n // include it explicitly).\n if (!this.config.bootSeeded) {\n const seed = autoSeedAllowlist(this.enumerate())\n await this.updateGlobalSettings({ allowedAddresses: seed, bootSeeded: true })\n this.ctx.logger.info('local-network: first-boot auto-seed', {\n meta: { addresses: seed },\n })\n }\n const provider: ILocalNetworkProvider = {\n list: async () => ({\n interfaces: this.enumerate(),\n probedAt: Date.now(),\n }),\n getPreferred: async () => pickPreferred(\n applyAllowlist(this.enumerate(), this.config.allowedAddresses),\n ),\n getConnectionEndpoints: async (input) => {\n const includeLoopback = input.includeLoopback ?? true\n const ipv4Only = input.ipv4Only ?? false\n const scheme = input.scheme ?? 'http'\n const allow = this.config.allowedAddresses\n const interfaces = applyAllowlist(this.enumerate(), allow)\n return {\n endpoints: buildEndpoints(interfaces, input.port, includeLoopback, ipv4Only, this.publicHostname, scheme),\n }\n },\n getAllowedAddresses: async () => ({ addresses: this.config.allowedAddresses }),\n resetAllowlistToBestMatch: async () => {\n const seed = autoSeedAllowlist(this.enumerate())\n await this.updateGlobalSettings({ allowedAddresses: seed, bootSeeded: true })\n this.ctx.logger.info('local-network: allowlist reset to auto-seed', {\n meta: { count: seed.length },\n })\n return { addresses: seed }\n },\n setAllowedAddresses: async ({ addresses }) => {\n // Validate against the current snapshot — drop anything that\n // doesn't actually exist on this host. Prevents an admin from\n // saving a typo'd address that would then silently filter out\n // every real candidate.\n const known = new Set(this.enumerate().map((i) => i.address))\n const cleaned: readonly string[] = [...new Set(addresses)].filter((a) => known.has(a))\n await this.updateGlobalSettings({ allowedAddresses: cleaned })\n this.ctx.logger.info('local-network: allowlist updated', {\n meta: { count: cleaned.length, dropped: addresses.length - cleaned.length },\n })\n return { success: true as const }\n },\n }\n\n // Seed the snapshot key so the first poll doesn't fire a false\n // change event on boot.\n this.lastSnapshotKey = snapshotKey(this.enumerate())\n\n this.pollTimer = setInterval(() => this.detectChanges(), POLL_INTERVAL_MS)\n this.pollTimer.unref?.()\n\n // Track the active public hostname by tailing the network-access\n // lifecycle events that every tunnel provider already emits. We\n // can't import cross-package so the parsing stays defensive.\n this.ctx.eventBus?.subscribe(\n { category: EventCategory.NetworkTunnelStarted },\n (event) => {\n const data = (event.data ?? {}) as { url?: unknown }\n if (typeof data.url === 'string') {\n try {\n const hostname = new URL(data.url).hostname\n // Ignore the pre-FQDN placeholders the tunnel emits before\n // cloudflared's stdout reports the real *.trycloudflare.com.\n if (hostname && !hostname.endsWith('.placeholder')\n && !hostname.startsWith('pending.')) {\n this.setPublicHostname(hostname)\n }\n } catch {\n // Malformed URL — leave the cached hostname as-is.\n }\n }\n },\n )\n this.ctx.eventBus?.subscribe(\n { category: EventCategory.NetworkTunnelStopped },\n () => this.setPublicHostname(''),\n )\n\n this.ctx.logger.info('local-network initialized', {\n meta: { interfaceCount: this.enumerate().length },\n })\n\n return [{ capability: localNetworkCapability, provider }]\n }\n\n protected async onShutdown(): Promise<void> {\n if (this.pollTimer) {\n clearInterval(this.pollTimer)\n this.pollTimer = null\n }\n }\n\n /**\n * Other hub addons (e.g. cloudflare-tunnel) signal the active public\n * FQDN by emitting `NetworkTunnelStarted` on the bus — handled in\n * `onInitialize`. This setter exists for tests + future direct\n * callers; cleared by passing an empty string.\n */\n setPublicHostname(hostname: string): void {\n if (this.publicHostname === hostname) return\n this.publicHostname = hostname\n this.ctx.logger.info('local-network: public hostname updated', {\n meta: { hostname: hostname || '(cleared)' },\n })\n }\n\n // ── Internals ──────────────────────────────────────────────────────\n\n private enumerate(): readonly LocalInterface[] {\n return enumerateOsInterfaces(os.networkInterfaces())\n }\n\n private detectChanges(): void {\n const interfaces = this.enumerate()\n const key = snapshotKey(interfaces)\n if (key === this.lastSnapshotKey) return\n\n this.ctx.logger.info('local-network: interface set changed', {\n meta: { count: interfaces.length, key },\n })\n this.lastSnapshotKey = key\n\n this.ctx.eventBus?.emit({\n id: `local-network-changed-${Date.now()}`,\n timestamp: new Date(),\n source: { type: 'core', id: 'local-network' },\n category: EventCategory.LocalNetworkChanged,\n data: { count: interfaces.length },\n })\n }\n}\n\n// ── Pure helpers (exported for tests + reusable by other consumers) ──\n\n/**\n * Lift `os.networkInterfaces()` into our `LocalInterface[]` shape with\n * kind classification + preferred flag. Pure — takes the raw result so\n * tests can feed synthetic data.\n */\nexport function enumerateOsInterfaces(\n ifaces: NodeJS.Dict<NodeJS.NetworkInterfaceInfo[]>,\n): readonly LocalInterface[] {\n const raw: RawIface[] = []\n for (const [name, addrs] of Object.entries(ifaces)) {\n if (!addrs) continue\n for (const a of addrs) {\n if (a.family !== 'IPv4' && a.family !== 'IPv6') continue\n raw.push({\n name,\n family: a.family,\n address: a.address,\n cidr: a.cidr ?? '',\n netmask: a.netmask,\n internal: a.internal,\n mac: a.mac,\n })\n }\n }\n\n const classified: LocalInterface[] = raw.map((r) => {\n const kind = classifyKind(r.name, r.address, r.internal)\n // \"Plausible\" = passes the RFC range gate AND comes from an\n // interface kind a client could realistically reach. Operators\n // can still pin a docker / vpn address — we just mark it visually\n // so the choice is intentional.\n const reachableKind = kind === 'lan' || kind === 'wifi'\n const plausible = !r.internal\n && reachableKind\n && isPlausibleAutoSeed(r.address, r.family)\n const plausibleReason = plausible\n ? ''\n : explainNonPlausible({ kind, family: r.family, address: r.address, internal: r.internal })\n return {\n name: r.name,\n family: r.family,\n address: r.address,\n cidr: r.cidr,\n netmask: r.netmask,\n internal: r.internal,\n mac: r.mac,\n kind,\n preferred: false,\n plausible,\n plausibleReason,\n }\n })\n\n const preferred = pickPreferred(classified)\n return classified.map((iface) => ({\n ...iface,\n preferred: preferred !== null\n && iface.name === preferred.name\n && iface.address === preferred.address,\n }))\n}\n\n/**\n * Filter the interface list by the operator's allowlist. Empty\n * allowlist = no-op (every interface passes); otherwise only entries\n * whose `address` matches an allowlist entry remain. Loopback always\n * survives so the SDK keeps `127.0.0.1` as the last-resort fallback.\n */\nexport function applyAllowlist(\n interfaces: readonly LocalInterface[],\n allowed: readonly string[],\n): readonly LocalInterface[] {\n if (allowed.length === 0) return interfaces\n const set = new Set(allowed)\n return interfaces.filter((i) => i.kind === 'loopback' || set.has(i.address))\n}\n\n/**\n * Rank interfaces and pick the auto-selected outbound one. See the\n * cap's `getPreferred` doc for the heuristic.\n */\nexport function pickPreferred(interfaces: readonly LocalInterface[]): LocalInterface | null {\n const candidates = interfaces.filter((i) =>\n !i.internal\n && i.family === 'IPv4'\n && !i.address.startsWith('169.254.') // RFC 3927 link-local\n && i.kind !== 'loopback',\n )\n if (candidates.length === 0) return null\n\n const kindRank: Record<LocalInterface['kind'], number> = {\n lan: 1, wifi: 2, vpn: 3, docker: 4, other: 5, loopback: 99,\n }\n const sorted = [...candidates].sort((a, b) => {\n const ra = kindRank[a.kind]\n const rb = kindRank[b.kind]\n if (ra !== rb) return ra - rb\n // Tie-break on netmask length — `/24` beats `/16`.\n return prefixLen(b.netmask) - prefixLen(a.netmask)\n })\n return sorted[0] ?? null\n}\n\n/**\n * Build the ordered candidate URL list. Priority schema:\n * 0 — preferred LAN IPv4\n * 10+ — other LAN IPv4\n * 100 — public tunnel hostname (always HTTPS)\n * 200+ — LAN IPv6\n * 1000 — loopback (last resort)\n *\n * `scheme` controls LAN + loopback URLs. Browsers running over HTTPS\n * block `http://` candidates as mixed content, so callers loaded over\n * HTTPS should pass `scheme: 'https'` even when probing a LAN IP — the\n * hub's cert manager already issues a SAN-multi cert covering local\n * interfaces. The public tunnel always emits `https://` (Cloudflare\n * terminates TLS for us).\n */\nexport function buildEndpoints(\n interfaces: readonly LocalInterface[],\n port: number,\n includeLoopback: boolean,\n ipv4Only: boolean,\n publicHostname: string,\n scheme: 'http' | 'https' = 'http',\n): ConnectionEndpoint[] {\n const out: ConnectionEndpoint[] = []\n let priority = 0\n const preferred = pickPreferred(interfaces)\n\n const emit = (\n iface: LocalInterface,\n kind: ConnectionEndpoint['kind'],\n label: string,\n baseUrl: string,\n pri: number,\n ): void => {\n out.push({\n label,\n baseUrl,\n kind,\n interfaceKind: iface.kind,\n plausible: iface.plausible,\n plausibleReason: iface.plausibleReason,\n priority: pri,\n })\n }\n\n if (preferred) {\n emit(\n preferred,\n 'lan-ipv4',\n `${formatKind(preferred.kind)} — ${preferred.name}`,\n `${scheme}://${preferred.address}:${port}`,\n priority++,\n )\n }\n\n for (const iface of interfaces) {\n if (iface.internal || iface.family !== 'IPv4') continue\n if (iface.kind === 'loopback') continue\n if (preferred && iface.name === preferred.name && iface.address === preferred.address) continue\n if (iface.address.startsWith('169.254.')) continue\n emit(\n iface,\n 'lan-ipv4',\n `${formatKind(iface.kind)} — ${iface.name}`,\n `${scheme}://${iface.address}:${port}`,\n 10 + priority++,\n )\n }\n\n if (publicHostname) {\n out.push({\n label: 'Public tunnel',\n baseUrl: `https://${publicHostname}`,\n kind: 'public',\n interfaceKind: 'public',\n plausible: true,\n plausibleReason: '',\n priority: 100,\n })\n }\n\n if (!ipv4Only) {\n let v6prio = 200\n for (const iface of interfaces) {\n if (iface.internal || iface.family !== 'IPv6') continue\n if (iface.kind === 'loopback') continue\n if (iface.address.startsWith('fe80:')) continue // link-local\n emit(\n iface,\n 'lan-ipv6',\n `${formatKind(iface.kind)} — ${iface.name} (IPv6)`,\n `${scheme}://[${iface.address}]:${port}`,\n v6prio++,\n )\n }\n }\n\n if (includeLoopback) {\n out.push({\n label: 'Loopback',\n baseUrl: `${scheme}://127.0.0.1:${port}`,\n kind: 'loopback',\n interfaceKind: 'loopback',\n plausible: false,\n plausibleReason: 'Loopback — last-resort fallback when no other endpoint responds.',\n priority: 1000,\n })\n }\n\n return out.sort((a, b) => a.priority - b.priority)\n}\n\n/**\n * First-boot heuristic: which addresses should the allowlist start\n * with? Includes LAN + Wi-Fi IPv4 addresses + plausible IPv6:\n *\n * - **IPv4**: skip link-local (`169.254.*`), keep the rest.\n * - **IPv6**: skip link-local (`fe80::*`), unspecified, and\n * multicast. Keep ULAs (`fc00::/7` → `fc??:` / `fd??:`) and Global\n * Unicast addresses (`2000::/3` → `2???`/`3???`). Privacy-extension\n * temporary addresses get included by default; the operator can\n * prune them from the Network Addresses tab if the rotating IPs\n * become a nuisance.\n *\n * Skips docker/vpn/loopback/other entirely — those stay opt-in.\n */\nexport function autoSeedAllowlist(interfaces: readonly LocalInterface[]): string[] {\n return [...new Set(\n interfaces\n .filter((i) => !i.internal\n && (i.kind === 'lan' || i.kind === 'wifi')\n && isPlausibleAutoSeed(i.address, i.family))\n .map((i) => i.address),\n )]\n}\n\n/**\n * Per-interface tooltip text surfaced on the \"Unlikely usable\" badge.\n * Server-side so the UI doesn't re-derive the rationale (single source\n * of truth). Returns `''` for plausible entries; the addon overlays\n * this on the `LocalInterface.plausibleReason` field.\n */\nexport function explainNonPlausible(input: {\n readonly kind: LocalInterface['kind']\n readonly family: 'IPv4' | 'IPv6'\n readonly address: string\n readonly internal: boolean\n}): string {\n if (input.internal) return 'Internal interface (loopback) — not reachable from clients.'\n if (input.kind === 'docker') return 'Docker bridge — only reachable from inside the container network.'\n if (input.kind === 'vpn') return 'VPN tunnel — only reachable while the VPN is connected.'\n if (input.kind === 'other') return 'Unrecognised interface kind — verify reachability before pinning.'\n if (input.family === 'IPv6') {\n const a = input.address.toLowerCase()\n if (a.startsWith('fe80:')) return 'IPv6 link-local — only reachable on the same link, not routed.'\n if (a.startsWith('ff')) return 'IPv6 multicast — not a unicast address.'\n if (a === '::' || a === '::1') return 'IPv6 loopback / unspecified — not a public address.'\n return 'IPv6 address outside the ULA / GUA ranges — verify before pinning.'\n }\n if (input.address.startsWith('169.254.')) return 'IPv4 link-local (RFC 3927) — only valid when DHCP fails.'\n return 'Address looks unusual for client traffic — verify before pinning.'\n}\n\n/**\n * Per-address gate used by `autoSeedAllowlist`. Exposed for tests so\n * we can pin every classification rule without standing up the addon.\n */\nexport function isPlausibleAutoSeed(address: string, family: 'IPv4' | 'IPv6'): boolean {\n if (family === 'IPv4') {\n if (address.startsWith('169.254.')) return false // RFC 3927 link-local\n return true\n }\n // IPv6 — normalise to lower-case once.\n const a = address.toLowerCase()\n if (a === '::' || a === '::1') return false\n if (a.startsWith('fe80:')) return false // link-local\n if (a.startsWith('ff')) return false // multicast (ff00::/8)\n // ULA (fc00::/7 → first hex group starts with `fc` or `fd`).\n if (/^f[cd][0-9a-f]{0,2}:/.test(a)) return true\n // GUA (2000::/3 → first nibble 2 or 3).\n if (/^[23][0-9a-f]{0,3}:/.test(a)) return true\n // Anything else (deprecated / experimental ranges) — leave opt-in.\n return false\n}\n\nexport function classifyKind(\n name: string,\n address: string,\n internal: boolean,\n): LocalInterface['kind'] {\n if (internal || name === 'lo' || name.startsWith('lo')) return 'loopback'\n const n = name.toLowerCase()\n if (n.startsWith('docker') || n.startsWith('br-') || n.startsWith('veth')) return 'docker'\n if (n.startsWith('tun') || n.startsWith('utun') || n.startsWith('wg') || n.startsWith('tap')) return 'vpn'\n if (n.startsWith('wlan') || n.startsWith('wlp') || n.startsWith('wlx')) return 'wifi'\n if (n.startsWith('eth') || /^en\\d+$/.test(n)) {\n // macOS en1+ is typically wifi; en0 is wired. Default heuristic.\n if (process.platform === 'darwin' && /^en[1-9]\\d*$/.test(n)) return 'wifi'\n return 'lan'\n }\n if (address === '127.0.0.1' || address === '::1') return 'loopback'\n return 'other'\n}\n\n/** Convert an IPv4/IPv6 netmask string to its prefix length (CIDR). */\nexport function prefixLen(netmask: string): number {\n if (!netmask) return 0\n if (netmask.includes(':')) {\n let bits = 0\n for (const group of netmask.split(':')) {\n if (!group) continue\n const n = parseInt(group, 16)\n if (!Number.isFinite(n)) break\n for (let mask = 0x8000; mask; mask >>= 1) {\n if (n & mask) bits++\n else return bits\n }\n }\n return bits\n }\n let bits = 0\n for (const part of netmask.split('.')) {\n const n = parseInt(part, 10)\n if (!Number.isFinite(n)) break\n for (let mask = 0x80; mask; mask >>= 1) {\n if (n & mask) bits++\n else return bits\n }\n }\n return bits\n}\n\nfunction snapshotKey(interfaces: readonly LocalInterface[]): string {\n return [...interfaces]\n .map((i) => `${i.name}|${i.family}|${i.address}|${i.netmask}`)\n .sort()\n .join('\\n')\n}\n\nfunction formatKind(kind: LocalInterface['kind']): string {\n switch (kind) {\n case 'lan': return 'LAN'\n case 'wifi': return 'Wi-Fi'\n case 'vpn': return 'VPN'\n case 'docker': return 'Docker'\n case 'loopback': return 'Loopback'\n case 'other': return 'Other'\n }\n}\n"],"mappings":"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"}