@undefineds.co/xpod 0.4.12 → 0.4.14

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 (272) hide show
  1. package/config/components-ignore.json +11 -7
  2. package/dist/acceptance/QleverSemanticConformance.js +7 -0
  3. package/dist/api/ai-gateway/providers/OfferingAuthorization.d.ts +6 -1
  4. package/dist/api/ai-gateway/providers/OfferingAuthorization.js +0 -3
  5. package/dist/api/ai-gateway/providers/ProviderRegistry.js +1 -1
  6. package/dist/api/container/index.js +1 -0
  7. package/dist/api/container/local.js +30 -12
  8. package/dist/api/container/routes.js +2 -0
  9. package/dist/api/container/types.d.ts +2 -0
  10. package/dist/api/handlers/AdminHandler.d.ts +17 -1
  11. package/dist/api/handlers/AdminHandler.js +40 -3
  12. package/dist/api/handlers/EdgeNodeSignalHandler.js +10 -2
  13. package/dist/api/handlers/NetworkSettingsHandler.d.ts +37 -5
  14. package/dist/api/handlers/NetworkSettingsHandler.js +39 -11
  15. package/dist/api/handlers/ProvisionHandler.d.ts +6 -1
  16. package/dist/api/handlers/ProvisionHandler.js +7 -2
  17. package/dist/api/handlers/ReachabilityHandler.d.ts +6 -0
  18. package/dist/api/handlers/ReachabilityHandler.js +22 -5
  19. package/dist/api/network/NetworkEnvironmentConfigurationStore.d.ts +6 -1
  20. package/dist/api/network/NetworkEnvironmentConfigurationStore.js +72 -16
  21. package/dist/api/runtime.d.ts +9 -0
  22. package/dist/api/runtime.js +15 -2
  23. package/dist/cli/commands/start.d.ts +19 -1
  24. package/dist/cli/commands/start.js +71 -5
  25. package/dist/components/context.jsonld +30 -0
  26. package/dist/edge/EdgeNodeAgent.d.ts +6 -0
  27. package/dist/edge/EdgeNodeAgent.js +1 -1
  28. package/dist/edge/EdgeNodeAgentInitializer.d.ts +2 -0
  29. package/dist/edge/EdgeNodeAgentInitializer.js +1 -0
  30. package/dist/edge/EdgeNodeAgentInitializer.jsonld +19 -0
  31. package/dist/edge/EdgeNodeDnsCoordinator.d.ts +11 -1
  32. package/dist/edge/EdgeNodeDnsCoordinator.js +12 -2
  33. package/dist/edge/EdgeNodeHealthProbeService.d.ts +15 -0
  34. package/dist/edge/EdgeNodeHealthProbeService.js +44 -12
  35. package/dist/edge/EdgeNodeHealthProbeService.jsonld +77 -0
  36. package/dist/edge/ProbeTargetGuard.d.ts +35 -0
  37. package/dist/edge/ProbeTargetGuard.js +142 -0
  38. package/dist/edge/reachability/NodeAccessResolver.d.ts +16 -0
  39. package/dist/edge/reachability/NodeAccessResolver.js +30 -0
  40. package/dist/index.d.ts +3 -1
  41. package/dist/index.js +9 -3
  42. package/dist/main.js +7 -0
  43. package/dist/runtime/Proxy.d.ts +22 -0
  44. package/dist/runtime/Proxy.js +34 -7
  45. package/dist/runtime/bootstrap.d.ts +11 -0
  46. package/dist/runtime/bootstrap.js +21 -1
  47. package/dist/runtime/css-process.d.ts +1 -0
  48. package/dist/runtime/css-process.js +1 -0
  49. package/dist/runtime/host/node/NodeRuntimeHost.js +4 -1
  50. package/dist/runtime/host/types.d.ts +6 -0
  51. package/dist/runtime/index.d.ts +1 -1
  52. package/dist/runtime/index.js +5 -1
  53. package/dist/runtime/lifecycle.js +1 -0
  54. package/dist/runtime/port-finder.d.ts +30 -0
  55. package/dist/runtime/port-finder.js +83 -0
  56. package/dist/runtime/runner/node/NodeGatewayRuntimeRunner.js +1 -0
  57. package/dist/runtime/runner/types.d.ts +5 -0
  58. package/dist/runtime/runtime-types.d.ts +1 -0
  59. package/dist/storage/rdf/PostgresRdfEngine.js +10 -4
  60. package/dist/storage/rdf/RdfAccessScope.js +15 -1
  61. package/dist/storage/rdf/RdfEngineRdfJsSource.js +10 -2
  62. package/dist/test-utils/local-managed-client-p2p-e2e-smoke.js +1 -1
  63. package/dist/tunnel/LocalTunnelProvider.d.ts +15 -0
  64. package/dist/tunnel/LocalTunnelProvider.js +87 -18
  65. package/dist/tunnel/LocalTunnelProvider.jsonld +27 -0
  66. package/dist/tunnel/NgrokTunnelProvider.d.ts +4 -0
  67. package/dist/tunnel/NgrokTunnelProvider.js +117 -43
  68. package/dist/tunnel/NgrokTunnelProvider.jsonld +4 -0
  69. package/dist/tunnel/SakuraFrpTunnelProvider.d.ts +65 -3
  70. package/dist/tunnel/SakuraFrpTunnelProvider.js +268 -25
  71. package/dist/tunnel/TunnelLifecycle.d.ts +14 -0
  72. package/dist/tunnel/TunnelLifecycle.js +34 -0
  73. package/dist/tunnel/TunnelProfiles.d.ts +33 -3
  74. package/dist/tunnel/TunnelProfiles.js +105 -78
  75. package/dist/tunnel/TunnelProvider.d.ts +15 -2
  76. package/dist/tunnel/TunnelProvider.jsonld +8 -0
  77. package/dist/tunnel/TunnelProviderCatalog.d.ts +62 -0
  78. package/dist/tunnel/TunnelProviderCatalog.js +130 -0
  79. package/node_modules/@undefineds.co/ai-connections/dist/AiApiKeyPool.d.ts +1 -1
  80. package/node_modules/@undefineds.co/ai-connections/dist/AiApiKeyPool.js +1 -1
  81. package/node_modules/@undefineds.co/ai-connections/dist/AiAuthorizationActions.d.ts +1 -1
  82. package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.d.ts +1 -1
  83. package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.js +3 -3
  84. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectDialog.d.ts +1 -1
  85. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.d.ts +1 -1
  86. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.js +2 -2
  87. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.d.ts +1 -1
  88. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialRow.d.ts +1 -1
  89. package/node_modules/@undefineds.co/ai-connections/dist/AiCustomProviderDialog.d.ts +1 -1
  90. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeyRow.d.ts +1 -1
  91. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.d.ts +1 -1
  92. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayModelsSection.d.ts +1 -1
  93. package/node_modules/@undefineds.co/ai-connections/dist/AiOfferingDetails.d.ts +1 -1
  94. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.d.ts +1 -1
  95. package/node_modules/@undefineds.co/ai-connections/dist/AiQuotaCard.d.ts +1 -1
  96. package/node_modules/@undefineds.co/ai-connections/dist/AiSortableCredentialList.d.ts +1 -1
  97. package/node_modules/@undefineds.co/ai-connections/dist/authorization-methods.d.ts +13 -11
  98. package/node_modules/@undefineds.co/ai-connections/dist/authorization-methods.js +16 -13
  99. package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.d.ts +1 -1
  100. package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.js +3 -3
  101. package/node_modules/@undefineds.co/ai-connections/dist/collections.d.ts +1 -1
  102. package/node_modules/@undefineds.co/ai-connections/dist/collections.js +3 -3
  103. package/node_modules/@undefineds.co/ai-connections/dist/{ai-connections-client.d.ts → contract/ai-connections-client.d.ts} +4 -2
  104. package/node_modules/@undefineds.co/ai-connections/dist/{ai-connections-client.js → contract/ai-connections-client.js} +4 -2
  105. package/node_modules/@undefineds.co/ai-connections/dist/{client → contract/client}/normalize.d.ts +17 -7
  106. package/node_modules/@undefineds.co/ai-connections/dist/{client → contract/client}/normalize.js +18 -213
  107. package/node_modules/@undefineds.co/ai-connections/dist/{client → contract/client}/request.js +3 -3
  108. package/node_modules/@undefineds.co/ai-connections/dist/{client → contract/client}/types.d.ts +11 -2
  109. package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/index.cjs +8 -8
  110. package/node_modules/@undefineds.co/ai-connections/dist/contract/index.d.ts +9 -0
  111. package/node_modules/@undefineds.co/ai-connections/dist/contract/index.js +9 -0
  112. package/node_modules/@undefineds.co/ai-connections/dist/{provider-catalog.cjs → contract/provider-catalog.cjs} +5 -28
  113. package/node_modules/@undefineds.co/ai-connections/dist/{provider-catalog.d.ts → contract/provider-catalog.d.ts} +9 -8
  114. package/node_modules/@undefineds.co/ai-connections/dist/{provider-catalog.js → contract/provider-catalog.js} +11 -31
  115. package/node_modules/@undefineds.co/ai-connections/dist/controller.d.ts +1 -1
  116. package/node_modules/@undefineds.co/ai-connections/dist/controller.js +3 -2
  117. package/node_modules/@undefineds.co/ai-connections/dist/credential-labels.d.ts +1 -1
  118. package/node_modules/@undefineds.co/ai-connections/dist/display-wording.d.ts +20 -0
  119. package/node_modules/@undefineds.co/ai-connections/dist/display-wording.js +73 -0
  120. package/node_modules/@undefineds.co/ai-connections/dist/error-wording.d.ts +24 -0
  121. package/node_modules/@undefineds.co/ai-connections/dist/error-wording.js +253 -0
  122. package/node_modules/@undefineds.co/ai-connections/dist/gateway-endpoints.js +1 -1
  123. package/node_modules/@undefineds.co/ai-connections/dist/index.d.ts +2 -3
  124. package/node_modules/@undefineds.co/ai-connections/dist/index.js +2 -3
  125. package/node_modules/@undefineds.co/ai-connections/dist/offering-endpoints.d.ts +1 -1
  126. package/node_modules/@undefineds.co/ai-connections/dist/offering-label.d.ts +1 -1
  127. package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.d.ts +1 -1
  128. package/node_modules/@undefineds.co/ai-connections/dist/service-access.js +1 -1
  129. package/node_modules/@undefineds.co/ai-connections/dist/useAiConnectDialog.d.ts +1 -1
  130. package/node_modules/@undefineds.co/ai-connections/package.json +25 -18
  131. package/node_modules/@undefineds.co/shared-ui/dist/index.d.ts +4 -2
  132. package/node_modules/@undefineds.co/shared-ui/dist/index.js +4 -2
  133. package/node_modules/@undefineds.co/shared-ui/dist/login/LoginModal.d.ts +4 -1
  134. package/node_modules/@undefineds.co/shared-ui/dist/login/LoginModal.js +12 -6
  135. package/node_modules/@undefineds.co/shared-ui/dist/login/LoginView.d.ts +1 -1
  136. package/node_modules/@undefineds.co/shared-ui/dist/login/host-types.d.ts +7 -1
  137. package/node_modules/@undefineds.co/shared-ui/dist/login/login-branding.d.ts +6 -0
  138. package/node_modules/@undefineds.co/shared-ui/dist/login/login-branding.js +18 -0
  139. package/node_modules/@undefineds.co/shared-ui/dist/user-facing-errors.d.ts +14 -2
  140. package/node_modules/@undefineds.co/shared-ui/dist/user-facing-errors.js +26 -17
  141. package/node_modules/@undefineds.co/solid-sdk/dist/login-store.d.ts +3 -3
  142. package/node_modules/@undefineds.co/solid-sdk/dist/login-store.js +3 -3
  143. package/package.json +4 -3
  144. package/static/auth-callback/assets/{AiConfigContext-DnQs1ZpW.js → AiConfigContext-DCXpjzpj.js} +1 -1
  145. package/static/auth-callback/assets/{AiConfigPage-DOtvlxH0.js → AiConfigPage-fe-xMIXa.js} +1 -1
  146. package/static/auth-callback/assets/{DocumentProcessingPanel-BS2voQgL.js → DocumentProcessingPanel-BGnkfMuU.js} +1 -1
  147. package/static/auth-callback/assets/{IndexLifecyclePanel-Cvt0cJtN.js → IndexLifecyclePanel-42Jups0j.js} +1 -1
  148. package/static/auth-callback/assets/{IndexSubjectPanel-Dhf01GqF.js → IndexSubjectPanel-CYyLOlQU.js} +1 -1
  149. package/static/auth-callback/assets/{ModelAssignmentsPanel-BJutWaAF.js → ModelAssignmentsPanel-BOvUH4yr.js} +1 -1
  150. package/static/auth-callback/assets/{ModelsPage-BRS0sje3.js → ModelsPage-DwyITxt7.js} +6 -6
  151. package/static/auth-callback/assets/NetworkPage-CG9RelJA.js +2 -0
  152. package/static/auth-callback/assets/{PaneListHeader-QQeJGTp4.js → PaneListHeader-yvd5ohs6.js} +1 -1
  153. package/static/auth-callback/assets/{SearchIndexingPanel-MyNUSEwT.js → SearchIndexingPanel-2_a6ezzj.js} +1 -1
  154. package/static/auth-callback/assets/{StatusSubjectPanel-DQkEVsFs.js → StatusSubjectPanel-8qtVxnzC.js} +1 -1
  155. package/static/auth-callback/assets/{StatusWorkspace-Dkv63Uwk.js → StatusWorkspace-CBdRahCF.js} +1 -1
  156. package/static/auth-callback/assets/{SystemSettingsPage-TIsUfX5d.js → SystemSettingsPage-BZJ6vWkg.js} +1 -1
  157. package/static/auth-callback/assets/{SystemSettingsSubjectPanel-BJWEt2-7.js → SystemSettingsSubjectPanel-xm08UhXP.js} +1 -1
  158. package/static/auth-callback/assets/XpodAiConnectionsPodStore-V6vgGfuw.js +3 -0
  159. package/static/auth-callback/assets/{activity-5hNeNKnL.js → activity-CeM7xly8.js} +1 -1
  160. package/static/auth-callback/assets/ai-connections-C6yaE6WQ.js +1 -0
  161. package/static/auth-callback/assets/{auth-callback-CAFZ3R0B.js → auth-callback-DTG8cSj7.js} +3 -3
  162. package/static/auth-callback/assets/{badge-CAIPI0CB.js → badge-qJo2Zr4d.js} +1 -1
  163. package/static/auth-callback/assets/{collection-runtime-D9s7h9YA.js → collection-runtime-Bztsz31a.js} +1 -1
  164. package/static/auth-callback/assets/{dialog-BjA109aX.js → dialog-D-h6x5x0.js} +1 -1
  165. package/static/auth-callback/assets/{download-B3Up5W2G.js → download-C2ir4lmR.js} +1 -1
  166. package/static/auth-callback/assets/{external-link-BTXgSPzB.js → external-link-THLDL4On.js} +1 -1
  167. package/static/auth-callback/assets/{index-CirW4CJf.js → index-BRpv4yO3.js} +1 -1
  168. package/static/auth-callback/assets/{index-BppXlxcp.js → index-BlVZb9A7.js} +1 -1
  169. package/static/auth-callback/assets/index-D983R1FV.js +4 -0
  170. package/static/auth-callback/assets/{index-browser-DtU38ni3.js → index-browser-3FvR0aaf.js} +1 -1
  171. package/static/auth-callback/assets/{key-round-CQCOrZ7x.js → key-round-C9U5j1Ly.js} +1 -1
  172. package/static/auth-callback/assets/{rotate-ccw-C1zM2KtS.js → rotate-ccw-DP45cD4o.js} +1 -1
  173. package/static/auth-callback/assets/{skeleton-Cqp7_M9-.js → skeleton-Dn4EiSCS.js} +1 -1
  174. package/static/auth-callback/assets/{waypoints-Bj6gAUSQ.js → waypoints-uqFQ3uEG.js} +1 -1
  175. package/static/auth-callback/assets/{workspace-layout-DK8mDzrY.js → workspace-layout-DLYK0Wwu.js} +1 -1
  176. package/static/auth-callback/auth-callback.html +1 -1
  177. package/static/dashboard/assets/{AiConfigContext-BsE7MqX8.js → AiConfigContext-DJcMECNw.js} +1 -1
  178. package/static/dashboard/assets/{AiConfigPage-DvM-lRXa.js → AiConfigPage-BvE7dOTy.js} +1 -1
  179. package/static/dashboard/assets/{DocumentProcessingPanel-BPfdlfuf.js → DocumentProcessingPanel-D9780krf.js} +1 -1
  180. package/static/dashboard/assets/{IndexLifecyclePanel--m0AGxvh.js → IndexLifecyclePanel-SjsUcnbM.js} +1 -1
  181. package/static/dashboard/assets/{IndexSubjectPanel-Bb7m1k3d.js → IndexSubjectPanel-C-ym2Tqi.js} +1 -1
  182. package/static/dashboard/assets/{ModelAssignmentsPanel-BLi_zbMa.js → ModelAssignmentsPanel-BRjZ-arB.js} +1 -1
  183. package/static/dashboard/assets/{ModelsPage-CxdpgnfR.js → ModelsPage-BtTU6du3.js} +6 -6
  184. package/static/dashboard/assets/NetworkPage-CV9qpkDg.js +2 -0
  185. package/static/dashboard/assets/{PaneListHeader-BBCMei0r.js → PaneListHeader-KyPTTBsv.js} +1 -1
  186. package/static/dashboard/assets/{SearchIndexingPanel-Ck4Y-xjR.js → SearchIndexingPanel-DolHGawg.js} +1 -1
  187. package/static/dashboard/assets/{StatusSubjectPanel-D1KWfAXE.js → StatusSubjectPanel-_YZvKiYi.js} +1 -1
  188. package/static/dashboard/assets/{StatusWorkspace-JbA5gzXx.js → StatusWorkspace-Dlbh_G40.js} +1 -1
  189. package/static/dashboard/assets/{SystemSettingsPage-BbwQWsSR.js → SystemSettingsPage-Be7QSIoz.js} +1 -1
  190. package/static/dashboard/assets/{SystemSettingsSubjectPanel-N117nMt5.js → SystemSettingsSubjectPanel-DBp0gja7.js} +1 -1
  191. package/static/dashboard/assets/{XpodAiConnectionsPodStore-CdDOb4SV.js → XpodAiConnectionsPodStore-ClpSjzpP.js} +7 -7
  192. package/static/dashboard/assets/{activity-DX1I96o_.js → activity-lsNbTXJu.js} +1 -1
  193. package/static/dashboard/assets/ai-connections-CXp5gd1J.js +1 -0
  194. package/static/dashboard/assets/{badge-k2vhtDqH.js → badge-CVatKjaG.js} +1 -1
  195. package/static/dashboard/assets/{collection-runtime-BFQ8teQJ.js → collection-runtime-Ec4UnY28.js} +1 -1
  196. package/static/dashboard/assets/{dashboard-DWZ-fmCT.js → dashboard-BEzsRsvF.js} +2 -2
  197. package/static/dashboard/assets/{dialog-1CCw-iHT.js → dialog-BuyelQ4V.js} +1 -1
  198. package/static/dashboard/assets/{download-C6-SNY1q.js → download-B4Nf678F.js} +1 -1
  199. package/static/dashboard/assets/{external-link-BgPcZ_j2.js → external-link-PYv9CvKL.js} +1 -1
  200. package/static/dashboard/assets/index-C9XPE-mI.js +4 -0
  201. package/static/dashboard/assets/{index-D7A8U6Pt.js → index-Cx69bTNh.js} +1 -1
  202. package/static/dashboard/assets/{index-6LcIUIYO.js → index-awr7ulur.js} +1 -1
  203. package/static/dashboard/assets/{key-round-BOd7Jo0Q.js → key-round-VsY80U1Z.js} +1 -1
  204. package/static/dashboard/assets/{rotate-ccw-CCgJqsvx.js → rotate-ccw-Cz1K4vE9.js} +1 -1
  205. package/static/dashboard/assets/{skeleton-Bc7abAn5.js → skeleton-BhNv_8tO.js} +1 -1
  206. package/static/dashboard/assets/{waypoints-s-opmJxx.js → waypoints-DYS9XFYV.js} +1 -1
  207. package/static/dashboard/assets/{workspace-layout-DqIQeTBV.js → workspace-layout-OZJAFx5V.js} +1 -1
  208. package/static/dashboard/dashboard.html +1 -1
  209. package/static/settings/assets/{AiConfigContext-BB9KZySa.js → AiConfigContext-B8JS3MXF.js} +1 -1
  210. package/static/settings/assets/{AiConfigPage-DGSXUkLs.js → AiConfigPage-C3Zl8LUl.js} +1 -1
  211. package/static/settings/assets/{DocumentProcessingPanel-Da2Re6Rg.js → DocumentProcessingPanel-DpDZAQvf.js} +1 -1
  212. package/static/settings/assets/{IndexLifecyclePanel-BSZuIzgr.js → IndexLifecyclePanel-Ec1XF88t.js} +1 -1
  213. package/static/settings/assets/{IndexSubjectPanel-CFd0ay-r.js → IndexSubjectPanel-BulT9BmO.js} +1 -1
  214. package/static/settings/assets/{ModelAssignmentsPanel-CSAryvWJ.js → ModelAssignmentsPanel-BcGSmYjb.js} +1 -1
  215. package/static/settings/assets/{ModelsPage-BQwCwLHU.js → ModelsPage-CvTCKy1T.js} +6 -6
  216. package/static/settings/assets/NetworkPage-DQF5u9Bn.js +2 -0
  217. package/static/settings/assets/{PaneListHeader-Bjh3hRdQ.js → PaneListHeader-D40hqcVl.js} +1 -1
  218. package/static/settings/assets/{SearchIndexingPanel-MjKL5QLU.js → SearchIndexingPanel-iCUPOx_0.js} +1 -1
  219. package/static/settings/assets/{StatusSubjectPanel-Bvl6K4mx.js → StatusSubjectPanel-E--ZHSql.js} +1 -1
  220. package/static/settings/assets/{StatusWorkspace-B0NzrP--.js → StatusWorkspace-YjDAx1II.js} +1 -1
  221. package/static/settings/assets/{SystemSettingsPage-D2z6Z4FE.js → SystemSettingsPage-CDdV3mC9.js} +1 -1
  222. package/static/settings/assets/{SystemSettingsSubjectPanel-4sxma4X4.js → SystemSettingsSubjectPanel-Br8WazDq.js} +1 -1
  223. package/static/settings/assets/XpodAiConnectionsPodStore-CLr38P_Z.js +3 -0
  224. package/static/settings/assets/{activity-CgJJGpjx.js → activity-C5DAHHTE.js} +1 -1
  225. package/static/settings/assets/ai-connections-C6yaE6WQ.js +1 -0
  226. package/static/settings/assets/{badge-C4NypVyT.js → badge-D8eIyxKt.js} +1 -1
  227. package/static/settings/assets/{collection-runtime-CTLCDxAi.js → collection-runtime-DLc9zil8.js} +1 -1
  228. package/static/settings/assets/{dialog-Csq0vWUi.js → dialog-CyuR7Va4.js} +1 -1
  229. package/static/settings/assets/{download-DaLJJ-Wp.js → download-c0oxZrCz.js} +1 -1
  230. package/static/settings/assets/{external-link--w_iW5Au.js → external-link-D3Z34fP_.js} +1 -1
  231. package/static/settings/assets/{index-BukHiu4y.js → index-CKGbRFlc.js} +1 -1
  232. package/static/settings/assets/index-CSr3-2Cj.js +4 -0
  233. package/static/settings/assets/{index-COmVnZi2.js → index-ComidxAm.js} +1 -1
  234. package/static/settings/assets/{index-browser-BGpvHwD0.js → index-browser-CAscEbae.js} +1 -1
  235. package/static/settings/assets/{key-round-Bk4YRjBu.js → key-round-DyjLmXuB.js} +1 -1
  236. package/static/settings/assets/{rotate-ccw-TCabbqsr.js → rotate-ccw-679HF_ec.js} +1 -1
  237. package/static/settings/assets/{settings-CJWpdbNC.js → settings-DKknqu4C.js} +3 -3
  238. package/static/settings/assets/{skeleton-JDHYVe7t.js → skeleton-CkopNkPB.js} +1 -1
  239. package/static/settings/assets/{waypoints-DDvEl-MU.js → waypoints-CrqfAftE.js} +1 -1
  240. package/static/settings/assets/{workspace-layout-DV5QU30U.js → workspace-layout-UN6c4qTG.js} +1 -1
  241. package/static/settings/settings.html +1 -1
  242. package/static/auth-callback/assets/NetworkPage-B3qBfANA.js +0 -2
  243. package/static/auth-callback/assets/XpodAiConnectionsPodStore-BJiXm-PF.js +0 -3
  244. package/static/auth-callback/assets/ai-connections-CryuHGKW.js +0 -1
  245. package/static/auth-callback/assets/index-DlLYWOhw.js +0 -4
  246. package/static/dashboard/assets/NetworkPage-BAIPw-D_.js +0 -2
  247. package/static/dashboard/assets/ai-connections-DwCRqOQa.js +0 -1
  248. package/static/dashboard/assets/index-UD6QOE7H.js +0 -4
  249. package/static/settings/assets/NetworkPage-BKymvsQc.js +0 -2
  250. package/static/settings/assets/XpodAiConnectionsPodStore-BkNQ8fZx.js +0 -3
  251. package/static/settings/assets/ai-connections-CryuHGKW.js +0 -1
  252. package/static/settings/assets/index-B0mQa59b.js +0 -4
  253. /package/node_modules/@undefineds.co/ai-connections/dist/{client → contract/client}/request.d.ts +0 -0
  254. /package/node_modules/@undefineds.co/ai-connections/dist/{client → contract/client}/types.js +0 -0
  255. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/base-adapter.d.ts +0 -0
  256. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/base-adapter.js +0 -0
  257. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/codex.d.ts +0 -0
  258. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/codex.js +0 -0
  259. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/index.d.ts +0 -0
  260. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/index.js +0 -0
  261. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/json-env-adapter.d.ts +0 -0
  262. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/json-env-adapter.js +0 -0
  263. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/pi.d.ts +0 -0
  264. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/pi.js +0 -0
  265. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/transaction.d.ts +0 -0
  266. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/transaction.js +0 -0
  267. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/types.d.ts +0 -0
  268. /package/node_modules/@undefineds.co/ai-connections/dist/{client-config → contract/client-config}/types.js +0 -0
  269. /package/node_modules/@undefineds.co/ai-connections/dist/{credential-storage.d.ts → contract/credential-storage.d.ts} +0 -0
  270. /package/node_modules/@undefineds.co/ai-connections/dist/{credential-storage.js → contract/credential-storage.js} +0 -0
  271. /package/node_modules/@undefineds.co/ai-connections/dist/{endpoint-urls.d.ts → contract/endpoint-urls.d.ts} +0 -0
  272. /package/node_modules/@undefineds.co/ai-connections/dist/{endpoint-urls.js → contract/endpoint-urls.js} +0 -0
@@ -42,7 +42,7 @@ function registerReachabilityRoutes(server, options) {
42
42
  }
43
43
  }, { optionalAuth: true });
44
44
  server.post('/v1/signal/nodes/:nodeId/sessions', async (request, response, params) => {
45
- const access = resolveSessionAccess(request, params.nodeId);
45
+ const access = await resolveSessionAccess(request, params.nodeId, options, 'node');
46
46
  if (!access.allowed) {
47
47
  sendJson(response, access.status, { error: access.error });
48
48
  return;
@@ -119,7 +119,7 @@ function registerReachabilityRoutes(server, options) {
119
119
  sendJson(response, 400, { error: 'kind must be p2p or relay' });
120
120
  });
121
121
  server.get('/v1/signal/nodes/:nodeId/sessions', async (request, response, params) => {
122
- const access = resolveSessionAccess(request, params.nodeId);
122
+ const access = await resolveSessionAccess(request, params.nodeId, options, 'node');
123
123
  if (!access.allowed) {
124
124
  sendJson(response, access.status, { error: access.error });
125
125
  return;
@@ -137,7 +137,7 @@ function registerReachabilityRoutes(server, options) {
137
137
  }
138
138
  });
139
139
  server.get('/v1/signal/nodes/:nodeId/sessions/:sessionId', async (request, response, params) => {
140
- const access = resolveSessionAccess(request, params.nodeId);
140
+ const access = await resolveSessionAccess(request, params.nodeId, options, 'session');
141
141
  if (!access.allowed) {
142
142
  sendJson(response, access.status, { error: access.error });
143
143
  return;
@@ -155,7 +155,7 @@ function registerReachabilityRoutes(server, options) {
155
155
  }
156
156
  });
157
157
  server.post('/v1/signal/nodes/:nodeId/sessions/:sessionId/candidates', async (request, response, params) => {
158
- const access = resolveSessionAccess(request, params.nodeId);
158
+ const access = await resolveSessionAccess(request, params.nodeId, options, 'session');
159
159
  if (!access.allowed) {
160
160
  sendJson(response, access.status, { error: access.error });
161
161
  return;
@@ -221,7 +221,7 @@ function resolveAccess(request, nodeId) {
221
221
  }
222
222
  return { allowed: true, audience: 'public' };
223
223
  }
224
- function resolveSessionAccess(request, nodeId) {
224
+ async function resolveSessionAccess(request, nodeId, options, target) {
225
225
  const auth = request.auth;
226
226
  if (!auth) {
227
227
  return { allowed: false, status: 401, error: 'Authentication required' };
@@ -233,9 +233,26 @@ function resolveSessionAccess(request, nodeId) {
233
233
  return { allowed: true, kind: 'node', nodeId: auth.nodeId };
234
234
  }
235
235
  if ((0, AuthContext_1.isServiceAuth)(auth)) {
236
+ // Service principals act for the deployment, so they must carry the scope that
237
+ // covers reachability sessions instead of being trusted by principal type alone.
238
+ if (!(0, AuthContext_1.hasScope)(auth, 'network:write')) {
239
+ return { allowed: false, status: 403, error: 'Creating a reachability session requires network:write' };
240
+ }
236
241
  return { allowed: true, kind: 'service' };
237
242
  }
238
243
  if ((0, AuthContext_1.isSolidAuth)(auth)) {
244
+ // Node-wide operations need a resolvable relationship to the node (Pod ownership or
245
+ // an explicit grant): being logged in says nothing about this node. Operations on one
246
+ // session are gated by session ownership instead, so the owner keeps access to their
247
+ // own session even when node-wide discovery is not available to them.
248
+ if (target === 'node') {
249
+ const permitted = options.canAccessNode
250
+ ? await options.canAccessNode(nodeId, auth.webId)
251
+ : false;
252
+ if (!permitted) {
253
+ return { allowed: false, status: 403, error: 'WebID is not authorized for this node' };
254
+ }
255
+ }
239
256
  return { allowed: true, kind: 'solid', webId: auth.webId };
240
257
  }
241
258
  return { allowed: false, status: 403, error: 'Unsupported reachability session credentials' };
@@ -2,7 +2,12 @@ import type { NetworkConfigurationPatch, NetworkConfigurationStore, NetworkDesir
2
2
  type Env = Record<string, string | undefined>;
3
3
  export interface NetworkEnvironmentConfigurationStoreOptions {
4
4
  read(): Env | Promise<Env>;
5
- write(patch: Record<string, string>): void | Promise<void>;
5
+ /**
6
+ * Persists a patch. `removals` lists keys that must be deleted from the environment
7
+ * instead of overwritten — deleting a profile has to take its credential with it,
8
+ * otherwise the leftover secret rebuilds the tunnel the user just closed.
9
+ */
10
+ write(patch: Record<string, string>, removals?: string[]): void | Promise<void>;
6
11
  }
7
12
  export declare class NetworkEnvironmentConfigurationStore implements NetworkConfigurationStore {
8
13
  private readonly options;
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NetworkEnvironmentConfigurationStore = void 0;
4
+ const TunnelProfiles_1 = require("../../tunnel/TunnelProfiles");
5
+ const TunnelProviderCatalog_1 = require("../../tunnel/TunnelProviderCatalog");
4
6
  class NetworkEnvironmentConfigurationStore {
5
7
  constructor(options) {
6
8
  this.options = options;
@@ -10,9 +12,13 @@ class NetworkEnvironmentConfigurationStore {
10
12
  }
11
13
  async update(patch) {
12
14
  const current = await this.options.read();
13
- const envPatch = environmentPatch(patch, current);
14
- await this.options.write(envPatch);
15
- return configurationFromEnv({ ...current, ...envPatch });
15
+ const { envPatch, removals } = environmentPatch(patch, current);
16
+ await this.options.write(envPatch, removals);
17
+ const next = { ...current, ...envPatch };
18
+ for (const key of removals) {
19
+ delete next[key];
20
+ }
21
+ return configurationFromEnv(next);
16
22
  }
17
23
  }
18
24
  exports.NetworkEnvironmentConfigurationStore = NetworkEnvironmentConfigurationStore;
@@ -35,7 +41,12 @@ function configurationFromEnv(env) {
35
41
  ...(env.XPOD_HTTPS_KEY_PATH ? { certificateKeyPath: env.XPOD_HTTPS_KEY_PATH } : {}),
36
42
  renewBeforeDays: positiveInteger(env.XPOD_ACME_RENEW_BEFORE_DAYS, 30),
37
43
  },
38
- tunnelProfiles: { activeProfileId: env.XPOD_TUNNEL_ACTIVE_PROFILE_ID ?? '', profiles },
44
+ tunnelProfiles: {
45
+ activeProfileId: env.XPOD_TUNNEL_ACTIVE_PROFILE_ID !== undefined
46
+ ? (env.XPOD_TUNNEL_ACTIVE_PROFILE_ID.trim() || TunnelProfiles_1.TUNNEL_ACTIVE_PROFILE_NONE)
47
+ : '',
48
+ profiles,
49
+ },
39
50
  p2p: {
40
51
  enabled: env.XPOD_P2P_ENABLED === 'true',
41
52
  signalService: env.XPOD_P2P_SIGNAL_SERVICE ?? '',
@@ -45,6 +56,7 @@ function configurationFromEnv(env) {
45
56
  }
46
57
  function environmentPatch(patch, current) {
47
58
  const output = {};
59
+ const removals = new Set();
48
60
  if (patch.domainDns) {
49
61
  assign(output, 'XPOD_DNS_DOMAIN', patch.domainDns.domain);
50
62
  assign(output, 'XPOD_DDNS_ENABLED', boolString(patch.domainDns.ddnsEnabled));
@@ -57,8 +69,10 @@ function environmentPatch(patch, current) {
57
69
  assign(output, 'XPOD_HTTPS_MODE', patch.https.enabled === undefined ? undefined : patch.https.enabled ? 'acme' : 'off');
58
70
  assign(output, 'XPOD_ACME_EMAIL', patch.https.acmeEmail);
59
71
  assign(output, 'XPOD_ACME_DOMAINS', patch.https.domains?.join(','));
60
- assign(output, 'XPOD_HTTPS_CERT_PATH', patch.https.certificatePath);
61
- assign(output, 'XPOD_HTTPS_KEY_PATH', patch.https.certificateKeyPath);
72
+ // The runtime reads the ACME key names; the settings page used to write
73
+ // XPOD_HTTPS_* which nothing consumed.
74
+ assign(output, 'XPOD_ACME_CERTIFICATE_PATH', patch.https.certificatePath);
75
+ assign(output, 'XPOD_ACME_CERTIFICATE_KEY_PATH', patch.https.certificateKeyPath);
62
76
  assign(output, 'XPOD_ACME_RENEW_BEFORE_DAYS', numberString(patch.https.renewBeforeDays));
63
77
  }
64
78
  if (patch.p2p) {
@@ -67,19 +81,38 @@ function environmentPatch(patch, current) {
67
81
  assign(output, 'XPOD_P2P_FALLBACK_POLICY', patch.p2p.fallbackPolicy);
68
82
  }
69
83
  if (patch.tunnelProfiles) {
70
- assign(output, 'XPOD_TUNNEL_ACTIVE_PROFILE_ID', patch.tunnelProfiles.activeProfileId);
84
+ // An empty selection is the explicit off decision, stored as its own value so the
85
+ // runtime can tell it apart from "never configured".
86
+ assign(output, 'XPOD_TUNNEL_ACTIVE_PROFILE_ID', patch.tunnelProfiles.activeProfileId === ''
87
+ ? TunnelProfiles_1.TUNNEL_ACTIVE_PROFILE_NONE
88
+ : patch.tunnelProfiles.activeProfileId);
71
89
  if (patch.tunnelProfiles.profiles) {
72
- const serialized = patch.tunnelProfiles.profiles.map(({ credential, ...profile }) => profile);
90
+ const serialized = patch.tunnelProfiles.profiles.map(({ credential, publicEndpoint, ...profile }) => ({
91
+ ...profile,
92
+ // Canonical field name: the runtime reads publicUrl.
93
+ ...(profile.publicUrl ?? publicEndpoint ? { publicUrl: profile.publicUrl ?? publicEndpoint } : {}),
94
+ }));
73
95
  output.XPOD_TUNNEL_PROFILES = JSON.stringify(serialized);
74
- for (const profile of patch.tunnelProfiles.profiles)
75
- if (profile.credential !== undefined)
76
- output[tunnelCredentialKey(profile.provider)] = profile.credential;
96
+ for (const profile of patch.tunnelProfiles.profiles) {
97
+ if (profile.credential !== undefined && profile.credential !== '') {
98
+ output[(0, TunnelProfiles_1.tunnelProfileCredentialEnvKey)(profile.id)] = profile.credential;
99
+ }
100
+ }
101
+ // Credentials of profiles that are gone must go with them.
102
+ for (const key of Object.keys(current)) {
103
+ if (!(0, TunnelProviderCatalog_1.isTunnelProfileCredentialEnvKey)(key)) {
104
+ continue;
105
+ }
106
+ if (!patch.tunnelProfiles.profiles.some((profile) => (0, TunnelProfiles_1.tunnelProfileCredentialEnvKey)(profile.id) === key)) {
107
+ removals.add(key);
108
+ }
109
+ }
77
110
  }
78
111
  }
79
- return output;
112
+ return { envPatch: output, removals: [...removals] };
80
113
  }
81
114
  function parseProfiles(raw, env) {
82
- if (!raw)
115
+ if (raw === undefined)
83
116
  return [];
84
117
  try {
85
118
  const values = JSON.parse(raw);
@@ -89,21 +122,44 @@ function parseProfiles(raw, env) {
89
122
  if (!value || typeof value !== 'object' || Array.isArray(value))
90
123
  return [];
91
124
  const item = value;
92
- if (typeof item.id !== 'string' || typeof item.label !== 'string' || !['ngrok', 'cloudflare', 'frp'].includes(String(item.provider)))
125
+ if (typeof item.id !== 'string' || typeof item.label !== 'string' || !(0, TunnelProviderCatalog_1.isTunnelProviderId)(item.provider))
93
126
  return [];
94
127
  const provider = item.provider;
95
- return [{ id: item.id, provider, label: item.label, ...(typeof item.publicEndpoint === 'string' ? { publicEndpoint: item.publicEndpoint } : {}), credentialConfigured: Boolean(env[tunnelCredentialKey(provider)]), ...(plainStringRecord(item.parameters) ? { parameters: item.parameters } : {}) }];
128
+ const publicUrl = firstString(item.publicUrl, item.publicEndpoint);
129
+ const credentialKey = resolveCredentialKey(item.id, provider, env);
130
+ return [{
131
+ id: item.id,
132
+ provider,
133
+ label: item.label,
134
+ ...(publicUrl ? { publicUrl } : {}),
135
+ credentialConfigured: Boolean(env[credentialKey]),
136
+ ...(plainStringRecord(item.parameters) ? { parameters: item.parameters } : {}),
137
+ }];
96
138
  });
97
139
  }
98
140
  catch {
99
141
  return [];
100
142
  }
101
143
  }
144
+ /** Profile-scoped credential first; a provider-global key still serves legacy setups. */
145
+ function resolveCredentialKey(profileId, provider, env) {
146
+ const scopedKey = (0, TunnelProfiles_1.tunnelProfileCredentialEnvKey)(profileId);
147
+ if (env[scopedKey])
148
+ return scopedKey;
149
+ const legacyKey = (0, TunnelProviderCatalog_1.tunnelProviderDescriptor)(provider)?.legacyCredentialEnvKey;
150
+ return legacyKey && env[legacyKey] ? legacyKey : scopedKey;
151
+ }
152
+ function firstString(...values) {
153
+ for (const value of values) {
154
+ if (typeof value === 'string' && value.trim())
155
+ return value.trim();
156
+ }
157
+ return undefined;
158
+ }
102
159
  function splitList(value) { return value?.split(',').map((item) => item.trim()).filter(Boolean) ?? []; }
103
160
  function positiveInteger(value, fallback) { const parsed = Number(value); return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback; }
104
161
  function dnsCredential(env, provider) { return env[dnsCredentialKey(provider)]; }
105
162
  function dnsCredentialKey(provider) { return provider === 'tencent' ? 'XPOD_TENCENT_DNS_TOKEN' : provider === 'cloudflare' ? 'CLOUDFLARE_API_TOKEN' : 'XPOD_DNS_PROVIDER_TOKEN'; }
106
- function tunnelCredentialKey(provider) { return provider === 'ngrok' ? 'NGROK_AUTHTOKEN' : provider === 'cloudflare' ? 'CLOUDFLARE_TUNNEL_TOKEN' : 'FRP_TUNNEL_TOKEN'; }
107
163
  function p2pFallback(value) { return value === 'never' || value === 'prefer-p2p' ? value : 'when-direct-unavailable'; }
108
164
  function plainStringRecord(value) { return Boolean(value) && typeof value === 'object' && !Array.isArray(value) && Object.values(value).every((item) => typeof item === 'string'); }
109
165
  function boolString(value) { return value === undefined ? undefined : String(value); }
@@ -18,4 +18,13 @@ export interface ApiServiceHandle {
18
18
  stop: () => Promise<void>;
19
19
  }
20
20
  export declare function autoProvisionFirstRunLocal(config: ApiContainerConfig, logger: ReturnType<typeof getLoggerFor>): Promise<ApiContainerConfig>;
21
+ /**
22
+ * Port a managed tunnel forwards to.
23
+ *
24
+ * It must be the Gateway's ingress listener rather than the gateway port itself:
25
+ * a tunnel terminating on the gateway port reaches the Gateway from loopback and
26
+ * would let forwarded remote requests inherit local trust. Falls back to the
27
+ * historical gateway port only when no ingress listener was provisioned.
28
+ */
29
+ export declare function resolveTunnelIngressPort(env?: NodeJS.ProcessEnv): number;
21
30
  export declare function startApiService(options?: StartApiServiceOptions): Promise<ApiServiceHandle>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.autoProvisionFirstRunLocal = autoProvisionFirstRunLocal;
4
+ exports.resolveTunnelIngressPort = resolveTunnelIngressPort;
4
5
  exports.startApiService = startApiService;
5
6
  const awilix_1 = require("awilix");
6
7
  const global_logger_factory_1 = require("global-logger-factory");
@@ -314,6 +315,19 @@ async function reconcileLocalOwnerRoles(container, config, logger) {
314
315
  logger.error(`Failed to reconcile local owner roles: ${error}`);
315
316
  }
316
317
  }
318
+ /**
319
+ * Port a managed tunnel forwards to.
320
+ *
321
+ * It must be the Gateway's ingress listener rather than the gateway port itself:
322
+ * a tunnel terminating on the gateway port reaches the Gateway from loopback and
323
+ * would let forwarded remote requests inherit local trust. Falls back to the
324
+ * historical gateway port only when no ingress listener was provisioned.
325
+ */
326
+ function resolveTunnelIngressPort(env = process.env) {
327
+ const raw = env.XPOD_GATEWAY_INGRESS_PORT ?? env.XPOD_MAIN_PORT ?? env.CSS_PORT ?? env.PORT ?? '3000';
328
+ const parsed = Number.parseInt(raw, 10);
329
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 3000;
330
+ }
317
331
  async function startBackgroundServices(container, logger) {
318
332
  try {
319
333
  const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });
@@ -338,10 +352,9 @@ async function startBackgroundServices(container, logger) {
338
352
  const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true });
339
353
  if (localTunnelProvider) {
340
354
  logger.info('Starting local tunnel provider...');
341
- const localPort = Number.parseInt(process.env.XPOD_MAIN_PORT ?? process.env.CSS_PORT ?? process.env.PORT ?? '3000', 10);
342
355
  const config = await localTunnelProvider.setup({
343
356
  subdomain: 'local',
344
- localPort: Number.isFinite(localPort) && localPort > 0 ? localPort : 3000,
357
+ localPort: resolveTunnelIngressPort(),
345
358
  localProtocol: 'http',
346
359
  });
347
360
  await localTunnelProvider.start(config);
@@ -10,12 +10,30 @@ interface StartArgs {
10
10
  seedConfig?: string;
11
11
  }
12
12
  export declare const startCommand: CommandModule<object, StartArgs>;
13
+ /**
14
+ * Where remote-forwarded traffic lands on this machine.
15
+ *
16
+ * Order: explicit `XPOD_GATEWAY_INGRESS_PORT` → the active SakuraFrp tunnel's assigned local
17
+ * port → an OS-assigned loopback port. The first two are strict, because a tunnel that
18
+ * forwards to a specific port cannot follow us somewhere else.
19
+ */
20
+ export declare function resolveIngressPort(config: {
21
+ tunnelProfiles?: Array<{
22
+ id: string;
23
+ provider: string;
24
+ credentialEnvKey?: string;
25
+ credentialConfigured?: boolean;
26
+ }>;
27
+ tunnelActiveProfileId?: string;
28
+ }, mainPort: number): Promise<number>;
13
29
  export declare function resolveCliOidcIssuer(env: Record<string, string | undefined>, provisionedIssuer?: string, edition?: string): string | undefined;
14
- export declare function resolveManagedEdgeAgentConfig(config: Pick<ReturnType<typeof loadConfigFromEnv>, 'cloudApiEndpoint' | 'nodeId' | 'nodeToken'>, gatewayPort: number): {
30
+ export declare function resolveManagedEdgeAgentConfig(config: Pick<ReturnType<typeof loadConfigFromEnv>, 'cloudApiEndpoint' | 'nodeId' | 'nodeToken'>, gatewayPort: number, ingressPort?: number, runtimeEnv?: Record<string, string | undefined>): {
15
31
  signalEndpoint: string;
16
32
  nodeId: string;
17
33
  nodeToken: string;
18
34
  targetBaseUrl: string;
35
+ lanBaseUrl: string;
36
+ p2pEnabled: boolean;
19
37
  } | undefined;
20
38
  export declare function resolveChildDatabaseUrl(value: string, childCwd: string): string;
21
39
  export declare function resolveCanonicalRuntimeBaseUrl(provisionedPublicUrl: string | undefined, configuredBaseUrl: string | undefined, localFallbackUrl: string): string;
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.startCommand = void 0;
7
+ exports.resolveIngressPort = resolveIngressPort;
7
8
  exports.resolveCliOidcIssuer = resolveCliOidcIssuer;
8
9
  exports.resolveManagedEdgeAgentConfig = resolveManagedEdgeAgentConfig;
9
10
  exports.resolveChildDatabaseUrl = resolveChildDatabaseUrl;
@@ -15,6 +16,7 @@ const fs_1 = __importDefault(require("fs"));
15
16
  const global_logger_factory_1 = require("global-logger-factory");
16
17
  const supervisor_1 = require("../../supervisor");
17
18
  const runtime_1 = require("../../runtime");
19
+ const SakuraFrpTunnelProvider_1 = require("../../tunnel/SakuraFrpTunnelProvider");
18
20
  const css_process_1 = require("../../runtime/css-process");
19
21
  const oidc_issuer_1 = require("../../runtime/oidc-issuer");
20
22
  const AuthMode_1 = require("../../authorization/AuthMode");
@@ -70,6 +72,10 @@ exports.startCommand = {
70
72
  process.env[key] ??= value;
71
73
  }
72
74
  process.env.XPOD_ENV_FILE = envPath;
75
+ // The settings API persists to XPOD_ENV_PATH (falling back to `<cwd>/.env.local`).
76
+ // Without this, a deployment started with `-e custom.env` saved its configuration
77
+ // into a file the runtime never reads.
78
+ process.env.XPOD_ENV_PATH ??= envPath;
73
79
  }
74
80
  else if (argv.env || process.env.XPOD_ENV_FILE) {
75
81
  console.warn(`Env file not found: ${envPath}`);
@@ -101,6 +107,19 @@ exports.startCommand = {
101
107
  const cssPort = await (0, runtime_1.getFreePortForWildcard)(requestedCssPort);
102
108
  const requestedApiPort = resolveServicePort(process.env.API_PORT, cssPort + 1, new Set([mainPort, cssPort]));
103
109
  const apiPort = await (0, runtime_1.getFreePortForWildcard)(requestedApiPort);
110
+ // Remote forwarding (managed tunnels, P2P data plane) terminates on this machine, so
111
+ // its origin is a dedicated ingress port instead of the gateway port: the Gateway
112
+ // never treats requests accepted there as local. An explicit override is honoured;
113
+ // otherwise the OS assigns a loopback port, because neighbouring ports may already
114
+ // belong to another service this deployment planned.
115
+ // The port is a fact of whichever tunnel forwards to us: an explicit override pins it,
116
+ // and the SakuraFrp console's own 本地端口 is read back from the provider, so the
117
+ // operator never types the same number twice. Only an unmanaged ingress is ephemeral.
118
+ // A pinned port is taken as-is: silently moving it would leave the tunnel pointing at a
119
+ // port nobody listens on.
120
+ const ingressPort = await resolveIngressPort(provisionedConfig, mainPort);
121
+ // Published so the API can tell the operator which address a tunnel must forward to.
122
+ process.env.XPOD_GATEWAY_INGRESS_PORT = String(ingressPort);
104
123
  const runtimeRoot = path_1.default.join(process.cwd(), '.xpod/runtime/legacy-css');
105
124
  const identityDbUrl = resolveChildDatabaseUrl(process.env.CSS_IDENTITY_DB_URL ?? process.env.DATABASE_URL ?? 'sqlite:./data/identity.sqlite', runtimeRoot);
106
125
  process.env.CSS_IDENTITY_DB_URL = identityDbUrl;
@@ -135,7 +154,7 @@ exports.startCommand = {
135
154
  authMode,
136
155
  externalOidcIssuer,
137
156
  });
138
- const managedEdge = resolveManagedEdgeAgentConfig(provisionedConfig, mainPort);
157
+ const managedEdge = resolveManagedEdgeAgentConfig(provisionedConfig, mainPort, ingressPort, process.env);
139
158
  const cssArgs = (0, css_process_1.buildCssArgs)({
140
159
  cssBinary: '__internal-css',
141
160
  configPath: cssRuntimeConfig.configPath,
@@ -169,6 +188,7 @@ exports.startCommand = {
169
188
  apiPort,
170
189
  mainPort,
171
190
  cssPort,
191
+ ingressPort,
172
192
  baseUrl,
173
193
  rdfIndexPath,
174
194
  authMode,
@@ -180,6 +200,7 @@ exports.startCommand = {
180
200
  exitOnStop: true,
181
201
  baseUrl,
182
202
  internalAdminAuthSecret: gatewayAdminProxyAuthSecret,
203
+ ingressPort,
183
204
  });
184
205
  proxy.setTargets({
185
206
  css: `http://localhost:${cssPort}`,
@@ -195,8 +216,9 @@ exports.startCommand = {
195
216
  nodeToken: managedEdge.nodeToken,
196
217
  baseUrl,
197
218
  p2p: {
198
- enabled: true,
219
+ enabled: managedEdge.p2pEnabled,
199
220
  targetBaseUrl: managedEdge.targetBaseUrl,
221
+ lanBaseUrl: managedEdge.lanBaseUrl,
200
222
  },
201
223
  });
202
224
  }
@@ -210,20 +232,64 @@ exports.startCommand = {
210
232
  process.on('SIGINT', () => shutdown('SIGINT'));
211
233
  },
212
234
  };
235
+ /**
236
+ * Where remote-forwarded traffic lands on this machine.
237
+ *
238
+ * Order: explicit `XPOD_GATEWAY_INGRESS_PORT` → the active SakuraFrp tunnel's assigned local
239
+ * port → an OS-assigned loopback port. The first two are strict, because a tunnel that
240
+ * forwards to a specific port cannot follow us somewhere else.
241
+ */
242
+ async function resolveIngressPort(config, mainPort) {
243
+ const explicit = process.env.XPOD_GATEWAY_INGRESS_PORT?.trim();
244
+ if (explicit) {
245
+ return await (0, runtime_1.requireFreePortForWildcard)(Number.parseInt(explicit, 10));
246
+ }
247
+ const active = config.tunnelProfiles?.find((profile) => profile.id === config.tunnelActiveProfileId)
248
+ ?? config.tunnelProfiles?.find((profile) => profile.provider === 'sakura_frp');
249
+ if (active?.provider === 'sakura_frp') {
250
+ const credential = active.credentialEnvKey
251
+ ? process.env[active.credentialEnvKey] ?? process.env.SAKURA_TUNNEL_TOKEN
252
+ : process.env.SAKURA_TUNNEL_TOKEN;
253
+ const assigned = await (0, SakuraFrpTunnelProvider_1.resolveSakuraAssignedLocalPort)(credential);
254
+ if (assigned && assigned !== mainPort) {
255
+ return await (0, runtime_1.requireFreePortForWildcard)(assigned);
256
+ }
257
+ }
258
+ // The operator copies this address into a provider console, so it has to survive
259
+ // restarts instead of being a fresh OS-assigned port every time.
260
+ const stateFile = path_1.default.join(process.cwd(), '.xpod', 'runtime', 'ingress-port');
261
+ const stable = await (0, runtime_1.resolveStableLoopbackPort)(stateFile);
262
+ if (stable.changed) {
263
+ (0, global_logger_factory_1.getLoggerFor)('XpodStart').warn(`The ingress port changed to ${stable.port}; update the tunnel console if it still forwards to the previous port`);
264
+ }
265
+ return stable.port;
266
+ }
213
267
  function resolveCliOidcIssuer(env, provisionedIssuer, edition) {
214
268
  return (0, oidc_issuer_1.resolveExternalOidcIssuer)(env)
215
269
  ?? (0, oidc_issuer_1.resolveExternalOidcIssuer)({ SOLID_OIDC_ISSUER: provisionedIssuer })
216
270
  ?? (edition === 'local' ? oidc_issuer_1.DEFAULT_LOCAL_OIDC_ISSUER : undefined);
217
271
  }
218
- function resolveManagedEdgeAgentConfig(config, gatewayPort) {
272
+ function resolveManagedEdgeAgentConfig(config, gatewayPort, ingressPort, runtimeEnv = {}) {
219
273
  if (!config.cloudApiEndpoint || !config.nodeId || !config.nodeToken) {
220
274
  return undefined;
221
275
  }
276
+ const gatewayBaseUrl = `http://127.0.0.1:${gatewayPort}/`;
277
+ // The settings page owns these two decisions; the managed node identity only supplies
278
+ // the signal endpoint they run against.
279
+ const declaredSignalService = runtimeEnv.XPOD_P2P_SIGNAL_SERVICE?.trim();
280
+ const p2pDisabled = runtimeEnv.XPOD_P2P_ENABLED?.trim().toLowerCase() === 'false';
222
281
  return {
223
- signalEndpoint: new URL('/v1/signal', config.cloudApiEndpoint).toString(),
282
+ signalEndpoint: declaredSignalService
283
+ || new URL('/v1/signal', config.cloudApiEndpoint).toString(),
224
284
  nodeId: config.nodeId,
225
285
  nodeToken: config.nodeToken,
226
- targetBaseUrl: `http://127.0.0.1:${gatewayPort}/`,
286
+ // Forwarded peer traffic enters through the ingress listener, which never counts
287
+ // as local. LAN clients keep addressing the gateway listener, which they can reach.
288
+ targetBaseUrl: ingressPort === undefined ? gatewayBaseUrl : `http://127.0.0.1:${ingressPort}/`,
289
+ lanBaseUrl: gatewayBaseUrl,
290
+ // Peer-to-peer transport is off by default unless the deployment asked for it; an
291
+ // explicit false must actually stop it.
292
+ p2pEnabled: !p2pDisabled && runtimeEnv.XPOD_P2P_ENABLED?.trim().toLowerCase() === 'true',
227
293
  };
228
294
  }
229
295
  function resolveChildDatabaseUrl(value, childCwd) {
@@ -1967,6 +1967,15 @@
1967
1967
  "options_locations": {
1968
1968
  "@id": "undefineds:dist/edge/EdgeNodeHealthProbeService.jsonld#EdgeNodeHealthProbeService_options_locations"
1969
1969
  },
1970
+ "options_resolveAddresses": {
1971
+ "@id": "undefineds:dist/edge/EdgeNodeHealthProbeService.jsonld#EdgeNodeHealthProbeService_options_resolveAddresses"
1972
+ },
1973
+ "options_headRequest": {
1974
+ "@id": "undefineds:dist/edge/EdgeNodeHealthProbeService.jsonld#EdgeNodeHealthProbeService_options_headRequest"
1975
+ },
1976
+ "options_maxRedirects": {
1977
+ "@id": "undefineds:dist/edge/EdgeNodeHealthProbeService.jsonld#EdgeNodeHealthProbeService_options_maxRedirects"
1978
+ },
1970
1979
  "repository": {
1971
1980
  "@id": "undefineds:dist/edge/EdgeNodeHealthProbeService.jsonld#EdgeNodeHealthProbeService_options_repository"
1972
1981
  },
@@ -1981,6 +1990,15 @@
1981
1990
  },
1982
1991
  "locations": {
1983
1992
  "@id": "undefineds:dist/edge/EdgeNodeHealthProbeService.jsonld#EdgeNodeHealthProbeService_options_locations"
1993
+ },
1994
+ "resolveAddresses": {
1995
+ "@id": "undefineds:dist/edge/EdgeNodeHealthProbeService.jsonld#EdgeNodeHealthProbeService_options_resolveAddresses"
1996
+ },
1997
+ "headRequest": {
1998
+ "@id": "undefineds:dist/edge/EdgeNodeHealthProbeService.jsonld#EdgeNodeHealthProbeService_options_headRequest"
1999
+ },
2000
+ "maxRedirects": {
2001
+ "@id": "undefineds:dist/edge/EdgeNodeHealthProbeService.jsonld#EdgeNodeHealthProbeService_options_maxRedirects"
1984
2002
  }
1985
2003
  }
1986
2004
  },
@@ -2029,6 +2047,9 @@
2029
2047
  "options_p2pTargetBaseUrl": {
2030
2048
  "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pTargetBaseUrl"
2031
2049
  },
2050
+ "options_p2pLanBaseUrl": {
2051
+ "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pLanBaseUrl"
2052
+ },
2032
2053
  "options_p2pLabel": {
2033
2054
  "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pLabel"
2034
2055
  },
@@ -2118,6 +2139,9 @@
2118
2139
  "p2pTargetBaseUrl": {
2119
2140
  "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pTargetBaseUrl"
2120
2141
  },
2142
+ "p2pLanBaseUrl": {
2143
+ "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pLanBaseUrl"
2144
+ },
2121
2145
  "p2pLabel": {
2122
2146
  "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pLabel"
2123
2147
  },
@@ -2959,6 +2983,9 @@
2959
2983
  "options_cloudflaredPath": {
2960
2984
  "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider_options_cloudflaredPath"
2961
2985
  },
2986
+ "options_connectTimeoutMs": {
2987
+ "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider_options_connectTimeoutMs"
2988
+ },
2962
2989
  "tunnelToken": {
2963
2990
  "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider_options_tunnelToken"
2964
2991
  },
@@ -2967,6 +2994,9 @@
2967
2994
  },
2968
2995
  "cloudflaredPath": {
2969
2996
  "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider_options_cloudflaredPath"
2997
+ },
2998
+ "connectTimeoutMs": {
2999
+ "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider_options_connectTimeoutMs"
2970
3000
  }
2971
3001
  }
2972
3002
  },
@@ -47,6 +47,12 @@ export interface EdgeNodeAgentOptions {
47
47
  p2p?: {
48
48
  enabled?: boolean | string;
49
49
  targetBaseUrl: string | URL;
50
+ /**
51
+ * Address this node advertises as its LAN route. Defaults to `targetBaseUrl`,
52
+ * and must be set when the forwarding target is a loopback-only listener that
53
+ * other devices on the LAN cannot reach.
54
+ */
55
+ lanBaseUrl?: string | URL;
50
56
  label?: string;
51
57
  host?: string;
52
58
  address?: string;
@@ -244,7 +244,7 @@ class EdgeNodeAgent {
244
244
  if (!p2p || this.normalizeBoolean(p2p.enabled) === false) {
245
245
  return [];
246
246
  }
247
- const endpoint = this.resolveLanGatewayEndpoint(p2p.targetBaseUrl);
247
+ const endpoint = this.resolveLanGatewayEndpoint(p2p.lanBaseUrl ?? p2p.targetBaseUrl);
248
248
  if (!endpoint) {
249
249
  return [];
250
250
  }
@@ -16,6 +16,8 @@ export interface EdgeNodeAgentInitializerOptions {
16
16
  intervalMs?: number | string;
17
17
  p2pEnabled?: boolean | string;
18
18
  p2pTargetBaseUrl?: string;
19
+ /** LAN-facing address; defaults to `p2pTargetBaseUrl` inside the agent. */
20
+ p2pLanBaseUrl?: string;
19
21
  p2pLabel?: string;
20
22
  p2pAcceptIntervalMs?: number | string;
21
23
  p2pConnectTimeoutMs?: number | string;
@@ -86,6 +86,7 @@ class EdgeNodeAgentInitializer extends community_server_1.Initializer {
86
86
  p2p: {
87
87
  enabled: true,
88
88
  targetBaseUrl: options.p2pTargetBaseUrl,
89
+ ...(options.p2pLanBaseUrl ? { lanBaseUrl: options.p2pLanBaseUrl } : {}),
89
90
  label: options.p2pLabel,
90
91
  acceptIntervalMs: this.normalizePositiveInteger(options.p2pAcceptIntervalMs),
91
92
  connectTimeoutMs: this.normalizePositiveInteger(options.p2pConnectTimeoutMs),
@@ -185,6 +185,19 @@
185
185
  ]
186
186
  }
187
187
  },
188
+ {
189
+ "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pLanBaseUrl",
190
+ "range": {
191
+ "@type": "ParameterRangeUnion",
192
+ "parameterRangeElements": [
193
+ "xsd:string",
194
+ {
195
+ "@type": "ParameterRangeUndefined"
196
+ }
197
+ ]
198
+ },
199
+ "comment": "LAN-facing address; defaults to `p2pTargetBaseUrl` inside the agent."
200
+ },
188
201
  {
189
202
  "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pLabel",
190
203
  "range": {
@@ -555,6 +568,12 @@
555
568
  "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pTargetBaseUrl"
556
569
  }
557
570
  },
571
+ {
572
+ "keyRaw": "p2pLanBaseUrl",
573
+ "value": {
574
+ "@id": "undefineds:dist/edge/EdgeNodeAgentInitializer.jsonld#EdgeNodeAgentInitializer_options_p2pLanBaseUrl"
575
+ }
576
+ },
558
577
  {
559
578
  "keyRaw": "p2pLabel",
560
579
  "value": {
@@ -19,7 +19,17 @@ export declare class EdgeNodeDnsCoordinator {
19
19
  private readonly ttl?;
20
20
  private readonly enabled;
21
21
  constructor(options: EdgeNodeDnsCoordinatorOptions);
22
- synchronize(nodeId: string, metadata: Record<string, unknown>): Promise<void>;
22
+ /**
23
+ * Reconciles the DNS record owned by one node.
24
+ *
25
+ * `binding` is the control plane's subdomain assignment for that node. When it is
26
+ * supplied it is authoritative, including when it carries no subdomain: that means the
27
+ * node owns no record and nothing may be written or deleted. Node-reported metadata is
28
+ * still consulted for callers whose subdomain is local (`LocalNetworkManager`).
29
+ */
30
+ synchronize(nodeId: string, metadata: Record<string, unknown>, binding?: {
31
+ subdomain?: string;
32
+ }): Promise<void>;
23
33
  private extractDnsHints;
24
34
  private extractTunnelEntrypoint;
25
35
  private extractString;