@harperfast/harper 5.2.13 → 5.3.0-beta.1

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 (655) hide show
  1. package/agent/mcpTools.ts +1 -1
  2. package/agent/session.ts +25 -14
  3. package/bin/cliOperations.ts +58 -9
  4. package/bin/copyDb.ts +282 -59
  5. package/bin/deploySetup.ts +16 -5
  6. package/bin/harper.ts +1 -1
  7. package/bin/help.ts +4 -1
  8. package/bin/lite.ts +4 -1
  9. package/bin/restart.ts +120 -4
  10. package/bin/run.ts +6 -11
  11. package/bin/upgrade.js +7 -3
  12. package/bin/workloadIdentity.ts +119 -0
  13. package/components/Application.ts +3436 -242
  14. package/components/ApplicationScope.ts +8 -0
  15. package/components/EntryHandler.ts +59 -39
  16. package/components/OptionsWatcher.ts +440 -98
  17. package/components/RuntimeModuleTracker.ts +38 -7
  18. package/components/Scope.ts +56 -15
  19. package/components/awaitRestart.ts +84 -0
  20. package/components/componentLoader.ts +381 -32
  21. package/components/componentPreparationLock.ts +16 -5
  22. package/components/deploymentOperations.ts +4 -1
  23. package/components/deploymentRecorder.ts +9 -2
  24. package/components/mcp/adapters/harperHttp.ts +4 -0
  25. package/components/mcp/listChanged.ts +4 -0
  26. package/components/mcp/toolRegistry.ts +2 -0
  27. package/components/mcp/tools/operations.ts +9 -0
  28. package/components/mcp/tools/schemas/operationDescriptions.ts +2 -2
  29. package/components/operations.js +537 -113
  30. package/components/operationsValidation.js +98 -3
  31. package/components/packageComponent.ts +25 -1
  32. package/components/requestRestart.ts +11 -0
  33. package/components/status/ComponentStatusRegistry.ts +59 -0
  34. package/config/RootConfigWatcher.ts +240 -40
  35. package/config/configReadRetry.ts +62 -0
  36. package/config/configUtils.ts +357 -48
  37. package/config/harperConfigEnvVars.ts +170 -27
  38. package/config/parseConfigFile.ts +34 -0
  39. package/config/readConfigFileSync.ts +44 -0
  40. package/config/watcherArming.ts +59 -0
  41. package/config-root.schema.json +33 -0
  42. package/dataLayer/blobBackup.ts +160 -50
  43. package/dataLayer/delete.ts +6 -1
  44. package/dataLayer/harperBridge/ResourceBridge.ts +80 -10
  45. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  46. package/dataLayer/hdbInfoController.ts +34 -1
  47. package/dataLayer/insert.ts +44 -1
  48. package/dataLayer/rocksdbBackup.ts +53 -10
  49. package/dataLayer/schema.ts +11 -1
  50. package/dataLayer/schemaDescribe.ts +8 -1
  51. package/dist/agent/mcpTools.js +1 -1
  52. package/dist/agent/mcpTools.js.map +1 -1
  53. package/dist/agent/session.d.ts +22 -0
  54. package/dist/agent/session.js +26 -15
  55. package/dist/agent/session.js.map +1 -1
  56. package/dist/bin/cliOperations.js +61 -9
  57. package/dist/bin/cliOperations.js.map +1 -1
  58. package/dist/bin/copyDb.d.ts +12 -1
  59. package/dist/bin/copyDb.js +248 -60
  60. package/dist/bin/copyDb.js.map +1 -1
  61. package/dist/bin/deploySetup.d.ts +2 -0
  62. package/dist/bin/deploySetup.js +11 -3
  63. package/dist/bin/deploySetup.js.map +1 -1
  64. package/dist/bin/harper.js +1 -1
  65. package/dist/bin/harper.js.map +1 -1
  66. package/dist/bin/help.js +4 -1
  67. package/dist/bin/help.js.map +1 -1
  68. package/dist/bin/lite.js +4 -1
  69. package/dist/bin/lite.js.map +1 -1
  70. package/dist/bin/restart.js +91 -6
  71. package/dist/bin/restart.js.map +1 -1
  72. package/dist/bin/run.js +4 -10
  73. package/dist/bin/run.js.map +1 -1
  74. package/dist/bin/upgrade.js +4 -3
  75. package/dist/bin/upgrade.js.map +1 -1
  76. package/dist/bin/workloadIdentity.d.ts +18 -0
  77. package/dist/bin/workloadIdentity.js +100 -0
  78. package/dist/bin/workloadIdentity.js.map +1 -0
  79. package/dist/components/Application.d.ts +235 -17
  80. package/dist/components/Application.js +3038 -238
  81. package/dist/components/Application.js.map +1 -1
  82. package/dist/components/ApplicationScope.d.ts +8 -0
  83. package/dist/components/ApplicationScope.js +7 -0
  84. package/dist/components/ApplicationScope.js.map +1 -1
  85. package/dist/components/EntryHandler.js +26 -10
  86. package/dist/components/EntryHandler.js.map +1 -1
  87. package/dist/components/OptionsWatcher.d.ts +4 -0
  88. package/dist/components/OptionsWatcher.js +440 -99
  89. package/dist/components/OptionsWatcher.js.map +1 -1
  90. package/dist/components/RuntimeModuleTracker.js +40 -6
  91. package/dist/components/RuntimeModuleTracker.js.map +1 -1
  92. package/dist/components/Scope.js +52 -13
  93. package/dist/components/Scope.js.map +1 -1
  94. package/dist/components/awaitRestart.d.ts +33 -0
  95. package/dist/components/awaitRestart.js +61 -0
  96. package/dist/components/awaitRestart.js.map +1 -0
  97. package/dist/components/componentLoader.d.ts +38 -1
  98. package/dist/components/componentLoader.js +313 -24
  99. package/dist/components/componentLoader.js.map +1 -1
  100. package/dist/components/componentPreparationLock.d.ts +5 -0
  101. package/dist/components/componentPreparationLock.js +14 -6
  102. package/dist/components/componentPreparationLock.js.map +1 -1
  103. package/dist/components/deploymentOperations.js +4 -1
  104. package/dist/components/deploymentOperations.js.map +1 -1
  105. package/dist/components/deploymentRecorder.d.ts +4 -2
  106. package/dist/components/deploymentRecorder.js +1 -0
  107. package/dist/components/deploymentRecorder.js.map +1 -1
  108. package/dist/components/mcp/adapters/harperHttp.js +4 -0
  109. package/dist/components/mcp/adapters/harperHttp.js.map +1 -1
  110. package/dist/components/mcp/listChanged.js +5 -0
  111. package/dist/components/mcp/listChanged.js.map +1 -1
  112. package/dist/components/mcp/toolRegistry.d.ts +1 -0
  113. package/dist/components/mcp/toolRegistry.js.map +1 -1
  114. package/dist/components/mcp/tools/operations.d.ts +5 -0
  115. package/dist/components/mcp/tools/operations.js +9 -0
  116. package/dist/components/mcp/tools/operations.js.map +1 -1
  117. package/dist/components/mcp/tools/schemas/operationDescriptions.js +2 -2
  118. package/dist/components/mcp/tools/schemas/operationDescriptions.js.map +1 -1
  119. package/dist/components/operations.d.ts +28 -0
  120. package/dist/components/operations.js +476 -113
  121. package/dist/components/operations.js.map +1 -1
  122. package/dist/components/operationsValidation.js +97 -3
  123. package/dist/components/operationsValidation.js.map +1 -1
  124. package/dist/components/packageComponent.js +24 -0
  125. package/dist/components/packageComponent.js.map +1 -1
  126. package/dist/components/requestRestart.d.ts +1 -0
  127. package/dist/components/requestRestart.js +7 -0
  128. package/dist/components/requestRestart.js.map +1 -1
  129. package/dist/components/status/ComponentStatusRegistry.d.ts +0 -4
  130. package/dist/components/status/ComponentStatusRegistry.js +63 -0
  131. package/dist/components/status/ComponentStatusRegistry.js.map +1 -1
  132. package/dist/config/RootConfigWatcher.d.ts +9 -1
  133. package/dist/config/RootConfigWatcher.js +228 -37
  134. package/dist/config/RootConfigWatcher.js.map +1 -1
  135. package/dist/config/configReadRetry.d.ts +8 -0
  136. package/dist/config/configReadRetry.js +62 -0
  137. package/dist/config/configReadRetry.js.map +1 -0
  138. package/dist/config/configUtils.d.ts +11 -2
  139. package/dist/config/configUtils.js +304 -47
  140. package/dist/config/configUtils.js.map +1 -1
  141. package/dist/config/harperConfigEnvVars.d.ts +16 -0
  142. package/dist/config/harperConfigEnvVars.js +162 -25
  143. package/dist/config/harperConfigEnvVars.js.map +1 -1
  144. package/dist/config/parseConfigFile.d.ts +4 -0
  145. package/dist/config/parseConfigFile.js +35 -0
  146. package/dist/config/parseConfigFile.js.map +1 -0
  147. package/dist/config/readConfigFileSync.d.ts +1 -0
  148. package/dist/config/readConfigFileSync.js +47 -0
  149. package/dist/config/readConfigFileSync.js.map +1 -0
  150. package/dist/config/watcherArming.d.ts +15 -0
  151. package/dist/config/watcherArming.js +59 -0
  152. package/dist/config/watcherArming.js.map +1 -0
  153. package/dist/dataLayer/blobBackup.d.ts +49 -20
  154. package/dist/dataLayer/blobBackup.js +139 -50
  155. package/dist/dataLayer/blobBackup.js.map +1 -1
  156. package/dist/dataLayer/delete.js +1 -1
  157. package/dist/dataLayer/delete.js.map +1 -1
  158. package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +14 -1
  159. package/dist/dataLayer/harperBridge/ResourceBridge.js +72 -12
  160. package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
  161. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.d.ts +3 -1
  162. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  163. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js.map +1 -1
  164. package/dist/dataLayer/hdbInfoController.d.ts +10 -0
  165. package/dist/dataLayer/hdbInfoController.js +30 -1
  166. package/dist/dataLayer/hdbInfoController.js.map +1 -1
  167. package/dist/dataLayer/insert.d.ts +9 -1
  168. package/dist/dataLayer/insert.js +30 -0
  169. package/dist/dataLayer/insert.js.map +1 -1
  170. package/dist/dataLayer/rocksdbBackup.d.ts +2 -2
  171. package/dist/dataLayer/rocksdbBackup.js +45 -8
  172. package/dist/dataLayer/rocksdbBackup.js.map +1 -1
  173. package/dist/dataLayer/schema.js +8 -0
  174. package/dist/dataLayer/schema.js.map +1 -1
  175. package/dist/dataLayer/schemaDescribe.js +8 -1
  176. package/dist/dataLayer/schemaDescribe.js.map +1 -1
  177. package/dist/index.d.ts +2 -1
  178. package/dist/index.js +4 -1
  179. package/dist/index.js.map +1 -1
  180. package/dist/json/systemSchema.json +55 -0
  181. package/dist/resources/DatabaseTransaction.d.ts +77 -0
  182. package/dist/resources/DatabaseTransaction.js +586 -54
  183. package/dist/resources/DatabaseTransaction.js.map +1 -1
  184. package/dist/resources/LMDBTransaction.d.ts +2 -1
  185. package/dist/resources/LMDBTransaction.js +43 -6
  186. package/dist/resources/LMDBTransaction.js.map +1 -1
  187. package/dist/resources/PrimaryRocksDatabase.d.ts +1 -0
  188. package/dist/resources/PrimaryRocksDatabase.js +49 -5
  189. package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
  190. package/dist/resources/RecordEncoder.d.ts +20 -0
  191. package/dist/resources/RecordEncoder.js +110 -9
  192. package/dist/resources/RecordEncoder.js.map +1 -1
  193. package/dist/resources/RequestTarget.d.ts +2 -0
  194. package/dist/resources/RequestTarget.js.map +1 -1
  195. package/dist/resources/Resource.js +117 -24
  196. package/dist/resources/Resource.js.map +1 -1
  197. package/dist/resources/ResourceInterface.d.ts +28 -1
  198. package/dist/resources/ResourceInterface.js.map +1 -1
  199. package/dist/resources/RocksIndexStore.d.ts +6 -1
  200. package/dist/resources/RocksIndexStore.js +24 -9
  201. package/dist/resources/RocksIndexStore.js.map +1 -1
  202. package/dist/resources/RocksTransactionLogStore.d.ts +24 -1
  203. package/dist/resources/RocksTransactionLogStore.js +160 -49
  204. package/dist/resources/RocksTransactionLogStore.js.map +1 -1
  205. package/dist/resources/Table.d.ts +165 -10
  206. package/dist/resources/Table.js +1805 -303
  207. package/dist/resources/Table.js.map +1 -1
  208. package/dist/resources/analytics/write.js +10 -3
  209. package/dist/resources/analytics/write.js.map +1 -1
  210. package/dist/resources/auditStore.d.ts +181 -2
  211. package/dist/resources/auditStore.js +640 -29
  212. package/dist/resources/auditStore.js.map +1 -1
  213. package/dist/resources/blob.d.ts +129 -9
  214. package/dist/resources/blob.js +992 -114
  215. package/dist/resources/blob.js.map +1 -1
  216. package/dist/resources/branchDatabase.d.ts +48 -0
  217. package/dist/resources/branchDatabase.js +892 -0
  218. package/dist/resources/branchDatabase.js.map +1 -0
  219. package/dist/resources/crdt.js +50 -12
  220. package/dist/resources/crdt.js.map +1 -1
  221. package/dist/resources/dataLoader.js +3 -4
  222. package/dist/resources/dataLoader.js.map +1 -1
  223. package/dist/resources/databases.d.ts +157 -14
  224. package/dist/resources/databases.js +1462 -325
  225. package/dist/resources/databases.js.map +1 -1
  226. package/dist/resources/defineTable.d.ts +10 -2
  227. package/dist/resources/defineTable.js +9 -1
  228. package/dist/resources/defineTable.js.map +1 -1
  229. package/dist/resources/derivedIndexRegistry.d.ts +5 -0
  230. package/dist/resources/derivedIndexRegistry.js +68 -0
  231. package/dist/resources/derivedIndexRegistry.js.map +1 -0
  232. package/dist/resources/derivedIndexRuntime.d.ts +215 -0
  233. package/dist/resources/derivedIndexRuntime.js +2027 -0
  234. package/dist/resources/derivedIndexRuntime.js.map +1 -0
  235. package/dist/resources/graphql.d.ts +1 -1
  236. package/dist/resources/graphql.js +52 -16
  237. package/dist/resources/graphql.js.map +1 -1
  238. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +103 -9
  239. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +854 -41
  240. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
  241. package/dist/resources/indexes/hnswDerivedIndex.d.ts +67 -0
  242. package/dist/resources/indexes/hnswDerivedIndex.js +464 -0
  243. package/dist/resources/indexes/hnswDerivedIndex.js.map +1 -0
  244. package/dist/resources/indexes/hnswPlaneBinding.d.ts +65 -0
  245. package/dist/resources/indexes/hnswPlaneBinding.js +91 -0
  246. package/dist/resources/indexes/hnswPlaneBinding.js.map +1 -0
  247. package/dist/resources/longLivedTransactions.d.ts +71 -0
  248. package/dist/resources/longLivedTransactions.js +358 -0
  249. package/dist/resources/longLivedTransactions.js.map +1 -0
  250. package/dist/resources/models/backendRegistry.d.ts +26 -0
  251. package/dist/resources/models/backendRegistry.js +60 -2
  252. package/dist/resources/models/backendRegistry.js.map +1 -1
  253. package/dist/resources/models/bootstrap.d.ts +33 -1
  254. package/dist/resources/models/bootstrap.js +416 -31
  255. package/dist/resources/models/bootstrap.js.map +1 -1
  256. package/dist/resources/nodeIdMapping.d.ts +5 -0
  257. package/dist/resources/nodeIdMapping.js +49 -0
  258. package/dist/resources/nodeIdMapping.js.map +1 -1
  259. package/dist/resources/recordLock.d.ts +123 -0
  260. package/dist/resources/recordLock.js +315 -0
  261. package/dist/resources/recordLock.js.map +1 -0
  262. package/dist/resources/recordLockCoordinator.d.ts +557 -0
  263. package/dist/resources/recordLockCoordinator.js +2565 -0
  264. package/dist/resources/recordLockCoordinator.js.map +1 -0
  265. package/dist/resources/replayLogs.d.ts +14 -1
  266. package/dist/resources/replayLogs.js +157 -24
  267. package/dist/resources/replayLogs.js.map +1 -1
  268. package/dist/resources/replayLogsGuards.d.ts +94 -7
  269. package/dist/resources/replayLogsGuards.js +111 -7
  270. package/dist/resources/replayLogsGuards.js.map +1 -1
  271. package/dist/resources/replicatedApplyFailure.d.ts +16 -0
  272. package/dist/resources/replicatedApplyFailure.js +63 -0
  273. package/dist/resources/replicatedApplyFailure.js.map +1 -0
  274. package/dist/resources/scheduler/scheduler.js +3 -3
  275. package/dist/resources/scheduler/scheduler.js.map +1 -1
  276. package/dist/resources/search.d.ts +10 -4
  277. package/dist/resources/search.js +283 -37
  278. package/dist/resources/search.js.map +1 -1
  279. package/dist/resources/tracked.d.ts +5 -1
  280. package/dist/resources/tracked.js +74 -23
  281. package/dist/resources/tracked.js.map +1 -1
  282. package/dist/resources/transactionBroadcast.d.ts +1 -1
  283. package/dist/resources/transactionBroadcast.js +2 -2
  284. package/dist/resources/transactionBroadcast.js.map +1 -1
  285. package/dist/security/auth.js +61 -30
  286. package/dist/security/auth.js.map +1 -1
  287. package/dist/security/authn/oidc/claims.d.ts +22 -0
  288. package/dist/security/authn/oidc/claims.js +71 -0
  289. package/dist/security/authn/oidc/claims.js.map +1 -0
  290. package/dist/security/authn/oidc/identityToken.d.ts +27 -0
  291. package/dist/security/authn/oidc/identityToken.js +111 -0
  292. package/dist/security/authn/oidc/identityToken.js.map +1 -0
  293. package/dist/security/authn/oidc/jwks.d.ts +25 -0
  294. package/dist/security/authn/oidc/jwks.js +261 -0
  295. package/dist/security/authn/oidc/jwks.js.map +1 -0
  296. package/dist/security/authn/oidc/providers/generic.d.ts +13 -0
  297. package/dist/security/authn/oidc/providers/generic.js +34 -0
  298. package/dist/security/authn/oidc/providers/generic.js.map +1 -0
  299. package/dist/security/authn/oidc/providers/githubActions.d.ts +11 -0
  300. package/dist/security/authn/oidc/providers/githubActions.js +129 -0
  301. package/dist/security/authn/oidc/providers/githubActions.js.map +1 -0
  302. package/dist/security/authn/oidc/providers/index.d.ts +37 -0
  303. package/dist/security/authn/oidc/providers/index.js +24 -0
  304. package/dist/security/authn/oidc/providers/index.js.map +1 -0
  305. package/dist/security/authn/oidc/tokenExchange.d.ts +12 -0
  306. package/dist/security/authn/oidc/tokenExchange.js +306 -0
  307. package/dist/security/authn/oidc/tokenExchange.js.map +1 -0
  308. package/dist/security/authn/oidc/trustPolicyOperations.d.ts +49 -0
  309. package/dist/security/authn/oidc/trustPolicyOperations.js +358 -0
  310. package/dist/security/authn/oidc/trustPolicyOperations.js.map +1 -0
  311. package/dist/security/authn/oidc/types.d.ts +38 -0
  312. package/dist/security/authn/oidc/types.js +6 -0
  313. package/dist/security/authn/oidc/types.js.map +1 -0
  314. package/dist/security/certificateVerification/index.js +40 -11
  315. package/dist/security/certificateVerification/index.js.map +1 -1
  316. package/dist/security/certificateVerification/trustedIssuers.d.ts +24 -0
  317. package/dist/security/certificateVerification/trustedIssuers.js +79 -0
  318. package/dist/security/certificateVerification/trustedIssuers.js.map +1 -0
  319. package/dist/security/certificateVerification/types.d.ts +1 -0
  320. package/dist/security/credentialProvenance.d.ts +35 -0
  321. package/dist/security/credentialProvenance.js +51 -0
  322. package/dist/security/credentialProvenance.js.map +1 -0
  323. package/dist/security/credentialRejection.d.ts +4 -0
  324. package/dist/security/credentialRejection.js +24 -0
  325. package/dist/security/credentialRejection.js.map +1 -0
  326. package/dist/security/deferredAuthentication.d.ts +36 -0
  327. package/dist/security/deferredAuthentication.js +70 -0
  328. package/dist/security/deferredAuthentication.js.map +1 -0
  329. package/dist/security/impersonation.d.ts +21 -0
  330. package/dist/security/impersonation.js +108 -9
  331. package/dist/security/impersonation.js.map +1 -1
  332. package/dist/security/jsLoader.d.ts +6 -0
  333. package/dist/security/jsLoader.js +77 -15
  334. package/dist/security/jsLoader.js.map +1 -1
  335. package/dist/security/keys.js +301 -71
  336. package/dist/security/keys.js.map +1 -1
  337. package/dist/security/operationScope.d.ts +21 -0
  338. package/dist/security/operationScope.js +36 -0
  339. package/dist/security/operationScope.js.map +1 -0
  340. package/dist/security/permissionsTranslator.js +21 -0
  341. package/dist/security/permissionsTranslator.js.map +1 -1
  342. package/dist/security/tokenAuthentication.d.ts +19 -1
  343. package/dist/security/tokenAuthentication.js +191 -10
  344. package/dist/security/tokenAuthentication.js.map +1 -1
  345. package/dist/security/user.js +4 -3
  346. package/dist/security/user.js.map +1 -1
  347. package/dist/server/DurableSubscriptionsSession.d.ts +2 -2
  348. package/dist/server/DurableSubscriptionsSession.js +67 -10
  349. package/dist/server/DurableSubscriptionsSession.js.map +1 -1
  350. package/dist/server/REST.js +106 -2
  351. package/dist/server/REST.js.map +1 -1
  352. package/dist/server/graphqlQuerying.js +4 -0
  353. package/dist/server/graphqlQuerying.js.map +1 -1
  354. package/dist/server/http.d.ts +16 -1
  355. package/dist/server/http.js +122 -17
  356. package/dist/server/http.js.map +1 -1
  357. package/dist/server/itc/serverHandlers.js +8 -1
  358. package/dist/server/itc/serverHandlers.js.map +1 -1
  359. package/dist/server/jobs/jobProcess.js +6 -2
  360. package/dist/server/jobs/jobProcess.js.map +1 -1
  361. package/dist/server/jobs/jobs.js +4 -1
  362. package/dist/server/jobs/jobs.js.map +1 -1
  363. package/dist/server/liveSubscriptionAuth.d.ts +26 -4
  364. package/dist/server/liveSubscriptionAuth.js +105 -39
  365. package/dist/server/liveSubscriptionAuth.js.map +1 -1
  366. package/dist/server/loadRootComponents.js +49 -10
  367. package/dist/server/loadRootComponents.js.map +1 -1
  368. package/dist/server/mqtt.d.ts +2 -0
  369. package/dist/server/mqtt.js +165 -30
  370. package/dist/server/mqtt.js.map +1 -1
  371. package/dist/server/nodeName.d.ts +2 -0
  372. package/dist/server/nodeName.js +107 -23
  373. package/dist/server/nodeName.js.map +1 -1
  374. package/dist/server/serverHelpers/Headers.d.ts +27 -0
  375. package/dist/server/serverHelpers/Headers.js +145 -1
  376. package/dist/server/serverHelpers/Headers.js.map +1 -1
  377. package/dist/server/serverHelpers/NodeAdapterResponse.d.ts +48 -0
  378. package/dist/server/serverHelpers/NodeAdapterResponse.js +220 -0
  379. package/dist/server/serverHelpers/NodeAdapterResponse.js.map +1 -0
  380. package/dist/server/serverHelpers/Request.d.ts +5 -10
  381. package/dist/server/serverHelpers/Request.js +38 -136
  382. package/dist/server/serverHelpers/Request.js.map +1 -1
  383. package/dist/server/serverHelpers/contentTypes.d.ts +11 -0
  384. package/dist/server/serverHelpers/contentTypes.js +221 -40
  385. package/dist/server/serverHelpers/contentTypes.js.map +1 -1
  386. package/dist/server/serverHelpers/deployValidationState.d.ts +3 -0
  387. package/dist/server/serverHelpers/deployValidationState.js +9 -19
  388. package/dist/server/serverHelpers/deployValidationState.js.map +1 -1
  389. package/dist/server/serverHelpers/operationAuthorizationState.d.ts +12 -0
  390. package/dist/server/serverHelpers/operationAuthorizationState.js +24 -2
  391. package/dist/server/serverHelpers/operationAuthorizationState.js.map +1 -1
  392. package/dist/server/serverHelpers/registeredOperations.d.ts +5 -4
  393. package/dist/server/serverHelpers/registeredOperations.js +74 -21
  394. package/dist/server/serverHelpers/registeredOperations.js.map +1 -1
  395. package/dist/server/serverHelpers/requestSanitization.d.ts +11 -0
  396. package/dist/server/serverHelpers/requestSanitization.js +20 -0
  397. package/dist/server/serverHelpers/requestSanitization.js.map +1 -0
  398. package/dist/server/serverHelpers/serverHandlers.js +6 -3
  399. package/dist/server/serverHelpers/serverHandlers.js.map +1 -1
  400. package/dist/server/serverHelpers/serverUtilities.d.ts +18 -0
  401. package/dist/server/serverHelpers/serverUtilities.js +178 -29
  402. package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
  403. package/dist/server/serverHelpers/sharedMessageEncoding.d.ts +67 -0
  404. package/dist/server/serverHelpers/sharedMessageEncoding.js +280 -0
  405. package/dist/server/serverHelpers/sharedMessageEncoding.js.map +1 -0
  406. package/dist/server/serverHelpers/uwsServer.js +19 -1
  407. package/dist/server/serverHelpers/uwsServer.js.map +1 -1
  408. package/dist/server/static.js +24 -28
  409. package/dist/server/static.js.map +1 -1
  410. package/dist/server/storageReclamation.d.ts +5 -0
  411. package/dist/server/storageReclamation.js +17 -1
  412. package/dist/server/storageReclamation.js.map +1 -1
  413. package/dist/server/threads/isolatedApplications.d.ts +47 -0
  414. package/dist/server/threads/isolatedApplications.js +171 -0
  415. package/dist/server/threads/isolatedApplications.js.map +1 -0
  416. package/dist/server/threads/itc.d.ts +7 -2
  417. package/dist/server/threads/itc.js +5 -1
  418. package/dist/server/threads/itc.js.map +1 -1
  419. package/dist/server/threads/logRotationTransport.d.ts +1 -0
  420. package/dist/server/threads/logRotationTransport.js +33 -0
  421. package/dist/server/threads/logRotationTransport.js.map +1 -0
  422. package/dist/server/threads/manageThreads.d.ts +83 -3
  423. package/dist/server/threads/manageThreads.js +769 -75
  424. package/dist/server/threads/manageThreads.js.map +1 -1
  425. package/dist/server/threads/socketRouter.d.ts +1 -0
  426. package/dist/server/threads/socketRouter.js +277 -31
  427. package/dist/server/threads/socketRouter.js.map +1 -1
  428. package/dist/server/threads/threadHeapMemory.d.ts +2 -0
  429. package/dist/server/threads/threadHeapMemory.js +31 -0
  430. package/dist/server/threads/threadHeapMemory.js.map +1 -0
  431. package/dist/server/threads/threadServer.js +76 -22
  432. package/dist/server/threads/threadServer.js.map +1 -1
  433. package/dist/sqlEngine/config.d.ts +1 -3
  434. package/dist/sqlEngine/config.js +19 -16
  435. package/dist/sqlEngine/config.js.map +1 -1
  436. package/dist/sqlTranslator/index.d.ts +1 -1
  437. package/dist/sqlTranslator/index.js +30 -7
  438. package/dist/sqlTranslator/index.js.map +1 -1
  439. package/dist/upgrade/directives/5-3-0.d.ts +7 -0
  440. package/dist/upgrade/directives/5-3-0.js +148 -0
  441. package/dist/upgrade/directives/5-3-0.js.map +1 -0
  442. package/dist/upgrade/directives/directivesController.js +2 -1
  443. package/dist/upgrade/directives/directivesController.js.map +1 -1
  444. package/dist/utility/OperationFunctionCaller.js +2 -1
  445. package/dist/utility/OperationFunctionCaller.js.map +1 -1
  446. package/dist/utility/common_utils.d.ts +16 -0
  447. package/dist/utility/common_utils.js +32 -6
  448. package/dist/utility/common_utils.js.map +1 -1
  449. package/dist/utility/componentNames.d.ts +8 -0
  450. package/dist/utility/componentNames.js +12 -1
  451. package/dist/utility/componentNames.js.map +1 -1
  452. package/dist/utility/environment/environmentManager.js +3 -6
  453. package/dist/utility/environment/environmentManager.js.map +1 -1
  454. package/dist/utility/environment/systemInformation.d.ts +1 -0
  455. package/dist/utility/environment/systemInformation.js +1 -0
  456. package/dist/utility/environment/systemInformation.js.map +1 -1
  457. package/dist/utility/errors/commonErrors.d.ts +2 -0
  458. package/dist/utility/errors/commonErrors.js +2 -0
  459. package/dist/utility/errors/commonErrors.js.map +1 -1
  460. package/dist/utility/errors/hdbError.d.ts +33 -0
  461. package/dist/utility/errors/hdbError.js +58 -1
  462. package/dist/utility/errors/hdbError.js.map +1 -1
  463. package/dist/utility/globalSchema.d.ts +18 -0
  464. package/dist/utility/hdbTerms.d.ts +18 -0
  465. package/dist/utility/hdbTerms.js +20 -2
  466. package/dist/utility/hdbTerms.js.map +1 -1
  467. package/dist/utility/logging/harper_logger.d.ts +2 -0
  468. package/dist/utility/logging/harper_logger.js +286 -30
  469. package/dist/utility/logging/harper_logger.js.map +1 -1
  470. package/dist/utility/logging/logGenerationCoordinator.d.ts +35 -0
  471. package/dist/utility/logging/logGenerationCoordinator.js +184 -0
  472. package/dist/utility/logging/logGenerationCoordinator.js.map +1 -0
  473. package/dist/utility/logging/logRotation.d.ts +46 -0
  474. package/dist/utility/logging/logRotation.js +365 -0
  475. package/dist/utility/logging/logRotation.js.map +1 -0
  476. package/dist/utility/logging/logRotator.d.ts +1 -1
  477. package/dist/utility/logging/logRotator.js +192 -85
  478. package/dist/utility/logging/logRotator.js.map +1 -1
  479. package/dist/utility/nodeIdentity.d.ts +9 -0
  480. package/dist/utility/nodeIdentity.js +58 -0
  481. package/dist/utility/nodeIdentity.js.map +1 -0
  482. package/dist/utility/npmUtilities.js +11 -7
  483. package/dist/utility/npmUtilities.js.map +1 -1
  484. package/dist/utility/operationPermissions.d.ts +3 -1
  485. package/dist/utility/operationPermissions.js +16 -1
  486. package/dist/utility/operationPermissions.js.map +1 -1
  487. package/dist/utility/operation_authorization.d.ts +10 -7
  488. package/dist/utility/operation_authorization.js +212 -41
  489. package/dist/utility/operation_authorization.js.map +1 -1
  490. package/dist/utility/watchPath.d.ts +29 -0
  491. package/dist/utility/watchPath.js +68 -0
  492. package/dist/utility/watchPath.js.map +1 -0
  493. package/dist/utility/watcherFallback.d.ts +41 -0
  494. package/dist/utility/watcherFallback.js +153 -0
  495. package/dist/utility/watcherFallback.js.map +1 -1
  496. package/dist/validation/configValidator.d.ts +12 -0
  497. package/dist/validation/configValidator.js +205 -75
  498. package/dist/validation/configValidator.js.map +1 -1
  499. package/dist/validation/installValidator.js +12 -0
  500. package/dist/validation/installValidator.js.map +1 -1
  501. package/dist/validation/validationWrapper.d.ts +11 -0
  502. package/dist/validation/validationWrapper.js +16 -3
  503. package/dist/validation/validationWrapper.js.map +1 -1
  504. package/index.ts +8 -0
  505. package/json/systemSchema.json +55 -0
  506. package/npm-shrinkwrap.json +286 -194
  507. package/package.json +15 -7
  508. package/resources/DESIGN.md +219 -52
  509. package/resources/DatabaseTransaction.ts +657 -52
  510. package/resources/LMDBTransaction.ts +46 -6
  511. package/resources/PrimaryRocksDatabase.ts +46 -7
  512. package/resources/RecordEncoder.ts +124 -9
  513. package/resources/RequestTarget.ts +2 -0
  514. package/resources/Resource.ts +114 -22
  515. package/resources/ResourceInterface.ts +31 -0
  516. package/resources/RocksIndexStore.ts +30 -9
  517. package/resources/RocksTransactionLogStore.ts +188 -51
  518. package/resources/Table.ts +1960 -301
  519. package/resources/analytics/write.ts +10 -3
  520. package/resources/auditStore.ts +647 -32
  521. package/resources/blob.ts +1029 -110
  522. package/resources/branchDatabase.ts +941 -0
  523. package/resources/crdt.ts +76 -12
  524. package/resources/dataLoader.ts +3 -4
  525. package/resources/databases.ts +1584 -320
  526. package/resources/defineTable.ts +18 -2
  527. package/resources/derivedIndexRegistry.ts +56 -0
  528. package/resources/derivedIndexRuntime.ts +2292 -0
  529. package/resources/graphql.ts +72 -17
  530. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +911 -48
  531. package/resources/indexes/hnswDerivedIndex.ts +531 -0
  532. package/resources/indexes/hnswPlaneBinding.ts +174 -0
  533. package/resources/longLivedTransactions.ts +360 -0
  534. package/resources/models/backendRegistry.ts +84 -2
  535. package/resources/models/bootstrap.ts +473 -28
  536. package/resources/nodeIdMapping.ts +50 -0
  537. package/resources/recordLock.ts +419 -0
  538. package/resources/recordLockCoordinator.ts +3043 -0
  539. package/resources/replayLogs.ts +152 -26
  540. package/resources/replayLogsGuards.ts +171 -8
  541. package/resources/replicatedApplyFailure.ts +77 -0
  542. package/resources/scheduler/scheduler.ts +4 -4
  543. package/resources/search.ts +288 -46
  544. package/resources/tracked.ts +73 -22
  545. package/resources/transactionBroadcast.ts +3 -3
  546. package/security/auth.ts +68 -29
  547. package/security/authn/oidc/claims.ts +72 -0
  548. package/security/authn/oidc/identityToken.ts +129 -0
  549. package/security/authn/oidc/jwks.ts +260 -0
  550. package/security/authn/oidc/providers/generic.ts +40 -0
  551. package/security/authn/oidc/providers/githubActions.ts +137 -0
  552. package/security/authn/oidc/providers/index.ts +52 -0
  553. package/security/authn/oidc/tokenExchange.ts +300 -0
  554. package/security/authn/oidc/trustPolicyOperations.ts +343 -0
  555. package/security/authn/oidc/types.ts +41 -0
  556. package/security/certificateVerification/index.ts +54 -13
  557. package/security/certificateVerification/trustedIssuers.ts +76 -0
  558. package/security/certificateVerification/types.ts +1 -0
  559. package/security/credentialProvenance.ts +47 -0
  560. package/security/credentialRejection.ts +22 -0
  561. package/security/deferredAuthentication.ts +71 -0
  562. package/security/impersonation.ts +117 -12
  563. package/security/jsLoader.ts +83 -18
  564. package/security/keys.ts +298 -72
  565. package/security/operationScope.ts +33 -0
  566. package/security/permissionsTranslator.js +23 -0
  567. package/security/tokenAuthentication.ts +233 -12
  568. package/security/user.ts +4 -3
  569. package/server/DESIGN.md +194 -16
  570. package/server/DurableSubscriptionsSession.ts +71 -11
  571. package/server/REST.ts +115 -4
  572. package/server/graphqlQuerying.ts +4 -0
  573. package/server/http.ts +133 -20
  574. package/server/itc/serverHandlers.js +8 -1
  575. package/server/jobs/jobProcess.ts +8 -2
  576. package/server/jobs/jobs.ts +4 -1
  577. package/server/liveSubscriptionAuth.ts +129 -46
  578. package/server/loadRootComponents.js +50 -8
  579. package/server/mqtt.ts +179 -38
  580. package/server/nodeName.ts +103 -21
  581. package/server/serverHelpers/Headers.ts +135 -0
  582. package/server/serverHelpers/NodeAdapterResponse.ts +221 -0
  583. package/server/serverHelpers/Request.ts +33 -131
  584. package/server/serverHelpers/contentTypes.ts +217 -36
  585. package/server/serverHelpers/deployValidationState.ts +24 -13
  586. package/server/serverHelpers/operationAuthorizationState.ts +34 -3
  587. package/server/serverHelpers/registeredOperations.ts +79 -22
  588. package/server/serverHelpers/requestSanitization.ts +15 -0
  589. package/server/serverHelpers/serverHandlers.js +6 -3
  590. package/server/serverHelpers/serverUtilities.ts +232 -40
  591. package/server/serverHelpers/sharedMessageEncoding.ts +307 -0
  592. package/server/serverHelpers/uwsServer.ts +17 -2
  593. package/server/static.ts +23 -29
  594. package/server/storageReclamation.ts +15 -2
  595. package/server/threads/isolatedApplications.ts +157 -0
  596. package/server/threads/itc.js +11 -1
  597. package/server/threads/logRotationTransport.ts +40 -0
  598. package/server/threads/manageThreads.js +771 -66
  599. package/server/threads/socketRouter.ts +291 -30
  600. package/server/threads/threadHeapMemory.ts +26 -0
  601. package/server/threads/threadServer.js +73 -22
  602. package/sqlTranslator/index.ts +31 -8
  603. package/studio/web/assets/{Chat-4RrB5134.js → Chat-D3j-1yY1.js} +1 -1
  604. package/studio/web/assets/{FloatingChat-omlNMDcJ.js → FloatingChat-BxJGYcfB.js} +3 -3
  605. package/studio/web/assets/{apiToken-Bke3wvfZ.js → apiToken-CT55oWOe.js} +1 -1
  606. package/studio/web/assets/{applications-DvFDYJgK.js → applications-D9Ct9_vm.js} +1 -1
  607. package/studio/web/assets/{cssMode-C1vRa7zh.js → cssMode-DV8H7VwA.js} +1 -1
  608. package/studio/web/assets/{editor-3XRWEDWX.js → editor-uatc0unt.js} +1 -1
  609. package/studio/web/assets/{html-CTY5tdMr.js → html-Bm6D6paN.js} +1 -1
  610. package/studio/web/assets/{htmlMode-CG1vSD9t.js → htmlMode-CEn7tpLG.js} +1 -1
  611. package/studio/web/assets/{index-Dfpeofdu.js → index-BIXW6Pu4.js} +5 -5
  612. package/studio/web/assets/{index.lazy-B1VOIv-t.js → index.lazy-UI7L-Vrk.js} +1 -1
  613. package/studio/web/assets/{javascript-CJeJzGnI.js → javascript-CJ0G3AFZ.js} +1 -1
  614. package/studio/web/assets/{jsonMode-CYPBwM82.js → jsonMode-DQADAYEa.js} +1 -1
  615. package/studio/web/assets/{languageServices-IKH4GUHl.js → languageServices-CAQJXWcI.js} +1 -1
  616. package/studio/web/assets/{lspLanguageFeatures-BC8_gxKG.js → lspLanguageFeatures-CCQ8P5sY.js} +1 -1
  617. package/studio/web/assets/{notifications-BfKBpYcq.js → notifications-BbxTU6Aw.js} +1 -1
  618. package/studio/web/assets/{notifications-DFbArTfC.js → notifications-Cvb3P1lB.js} +1 -1
  619. package/studio/web/assets/{profile-Q4-T6c-S.js → profile-Yyb7gsvL.js} +1 -1
  620. package/studio/web/assets/{regions-CtkV0xje.js → regions-OgjGHlU5.js} +1 -1
  621. package/studio/web/assets/{register-1ZZuMsiA.js → register-6qwNEOY3.js} +2 -2
  622. package/studio/web/assets/{setComponentFile-ZWLcWv5X.js → setComponentFile-BilDMtgB.js} +1 -1
  623. package/studio/web/assets/{setup-DWprJyJy.js → setup-J6qJ7OIU.js} +2 -2
  624. package/studio/web/assets/{status--aNm8isn.js → status-0RWGcfyD.js} +1 -1
  625. package/studio/web/assets/{toggleHighContrast-Cq_lt3XD.js → toggleHighContrast-BIn-vErT.js} +1 -1
  626. package/studio/web/assets/{tsMode-pjgytARx.js → tsMode-DgUXku4d.js} +1 -1
  627. package/studio/web/assets/{typescript-Cdg0mqUh.js → typescript-C9orXcsM.js} +1 -1
  628. package/studio/web/assets/{useEntityRestURL-RZhaY8Rn.js → useEntityRestURL-BEoXXbUB.js} +1 -1
  629. package/studio/web/assets/{workers-BgoXIqQe.js → workers-JVzSDmgx.js} +1 -1
  630. package/studio/web/assets/{xml-BwSeDMiP.js → xml-Cq-S8S4X.js} +1 -1
  631. package/studio/web/assets/{yaml-DotCUG5l.js → yaml-sfoRdh1M.js} +1 -1
  632. package/studio/web/index.html +1 -1
  633. package/upgrade/directives/5-3-0.ts +132 -0
  634. package/upgrade/directives/directivesController.ts +2 -1
  635. package/utility/OperationFunctionCaller.ts +2 -1
  636. package/utility/common_utils.ts +30 -5
  637. package/utility/componentNames.ts +12 -0
  638. package/utility/environment/environmentManager.ts +3 -7
  639. package/utility/environment/systemInformation.ts +7 -0
  640. package/utility/errors/commonErrors.ts +4 -0
  641. package/utility/errors/hdbError.ts +57 -0
  642. package/utility/hdbTerms.ts +19 -0
  643. package/utility/logging/harper_logger.ts +278 -26
  644. package/utility/logging/logGenerationCoordinator.ts +196 -0
  645. package/utility/logging/logRotation.ts +367 -0
  646. package/utility/logging/logRotator.ts +213 -81
  647. package/utility/nodeIdentity.ts +45 -0
  648. package/utility/npmUtilities.ts +12 -8
  649. package/utility/operationPermissions.ts +18 -1
  650. package/utility/operation_authorization.ts +231 -42
  651. package/utility/watchPath.ts +63 -0
  652. package/utility/watcherFallback.ts +148 -0
  653. package/validation/configValidator.ts +215 -75
  654. package/validation/installValidator.ts +15 -0
  655. package/validation/validationWrapper.ts +18 -4
@@ -0,0 +1,307 @@
1
+ import { serializeMessage, getMessageSerializer } from './contentTypes.ts';
2
+ import { logger } from '../../utility/logging/logger.ts';
3
+
4
+ /**
5
+ * The encoding work that every subscriber of a topic would otherwise redo for the same message.
6
+ * `payload` is the serialized message body; `frames` holds fully encoded protocol frames that are
7
+ * byte-identical across subscribers (MQTT QoS 0 PUBLISH packets), keyed by whatever the frame
8
+ * still varies on. `next` chains the encodings for any further content types the same message was
9
+ * delivered in — a chain rather than a map because a topic's subscribers realistically negotiate
10
+ * one or two content types, and this keeps the single-content-type case to one allocation.
11
+ *
12
+ * `hits` counts the subscribers after the first, so a caller can skip caching anything derived
13
+ * from the payload until a fan-out is known to exist. `failed` is a distinct state from an
14
+ * undefined `payload`, which a serializer can legitimately return (JSON of `undefined`).
15
+ * `bytes` is everything this entry holds — payload plus frames — and `epoch` records which
16
+ * generation those bytes are charged to, so work that lands after a rotation (a serialization that
17
+ * resolves late) is not charged to a budget it does not belong to, and a promotion re-charges the
18
+ * entry exactly once. That is what makes the budget an actual accounting rather than an estimate.
19
+ */
20
+ export interface SharedMessageEncoding {
21
+ serializer: Function;
22
+ version: number | undefined;
23
+ payload: Buffer | string | Promise<Buffer | string> | undefined;
24
+ failed: boolean;
25
+ hits: number;
26
+ bytes: number;
27
+ epoch: number;
28
+ frames: Map<number, Map<string, Buffer>> | undefined;
29
+ next: SharedMessageEncoding | undefined;
30
+ }
31
+
32
+ // A message that carries its own content type is passed through verbatim and never negotiated, so
33
+ // every subscriber shares one entry no matter what it negotiated. This sentinel stands in for the
34
+ // serializer that was deliberately not consulted.
35
+ const PASS_THROUGH = function passThrough() {};
36
+
37
+ // THE IDENTITY CONTRACT. A fan-out has a single shared origin: the same message object instance is
38
+ // dispatched to every subscription of a key (resources/transactionBroadcast.ts), so identity is
39
+ // what lets the first subscriber to encode do the work for all of them. This is only sound because
40
+ // every internal producer yields a *fresh object per version* — transactionBroadcast hands one
41
+ // auditRecord to every subscription, auditStore's getValue memoizes the decode in its closure, and
42
+ // primaryStore.getEntry is guarded by a version check — so identity implies equal content, and a
43
+ // miss (a primitive message, or a store cache eviction between subscribers) only costs the
44
+ // redundant encode we have today rather than yielding stale bytes.
45
+ //
46
+ // A custom Resource is not bound by that, so identity alone is not trusted: the event's record
47
+ // version is part of the key (see getSharedMessageEncoding), which makes reusing one envelope
48
+ // across publishes correct as long as the version advances, and refuses to share at all when there
49
+ // is no version to tell one publish from the next.
50
+ //
51
+ // Retention is bounded by rotating generations rather than by the message object's lifetime: for
52
+ // record events the message IS the store's cached record, so hanging encodings off it alone would
53
+ // keep serialized copies and whole PUBLISH buffers resident for as long as the record stays cached,
54
+ // while sharing is only ever needed for the duration of one fan-out. Two generations are kept so a
55
+ // fan-out spanning a rotation still hits; dropping a generation releases all of it at once.
56
+ const ROTATE_INTERVAL_MS = 10_000;
57
+ // Time alone bounds how LONG an entry is retained, not how MUCH: at high throughput on
58
+ // single-subscriber topics the interval's worth of payloads would all be live at once, for no
59
+ // benefit. The byte budget puts a ceiling on that, at the cost of a fan-out that spans an early
60
+ // rotation falling back to re-encoding — slower, never wrong. Note this is the ceiling for ONE
61
+ // generation; the previous generation can hold as much again, so steady-state retention is up to
62
+ // twice this per worker thread.
63
+ export const MAX_RETAINED_BYTES = 4_000_000;
64
+ let currentGeneration = new WeakMap<object, SharedMessageEncoding>();
65
+ let previousGeneration = new WeakMap<object, SharedMessageEncoding>();
66
+ // Rotation runs on a timer, not on a delivery counter: the bound has to hold when traffic stops,
67
+ // which is exactly when a delivery-gated check would never fire again. Insert counts only decide
68
+ // when the timer can stop — a WeakMap can not be asked whether it is empty.
69
+ let rotationTimer: ReturnType<typeof setInterval> | undefined;
70
+ let currentInserts = 0;
71
+ let currentBytes = 0;
72
+ // Identifies the generation an entry's bytes are charged to. Work can land after a rotation — a
73
+ // serialization that resolves late, a frame generated by a subscriber that arrived slowly — and
74
+ // charging that to the current budget would bill a generation the bytes do not belong to, then bill
75
+ // them again when a promotion re-charges the entry.
76
+ const UNRETAINED = -1;
77
+ // starts at 1 so UNRETAINED can never collide with `currentEpoch - 1`, which would make charge()
78
+ // treat a never-retained entry as one still live in the previous generation
79
+ let currentEpoch = 1;
80
+
81
+ /** Retire the older generation. Exported for the rotation timer and for tests. */
82
+ export function rotateSharedEncodings() {
83
+ previousGeneration = currentGeneration;
84
+ currentGeneration = new WeakMap();
85
+ currentEpoch++;
86
+ const rotatedInserts = currentInserts;
87
+ currentInserts = 0;
88
+ currentBytes = 0;
89
+ if (rotatedInserts === 0 && rotationTimer !== undefined) {
90
+ // nothing is retained in either generation, so stop ticking until the next insert
91
+ clearInterval(rotationTimer);
92
+ rotationTimer = undefined;
93
+ }
94
+ }
95
+
96
+ /** Whether the rotation timer is currently armed. Introspection for tests. */
97
+ export function isRotationScheduled(): boolean {
98
+ return rotationTimer !== undefined;
99
+ }
100
+
101
+ /** Bytes charged to the live generation. Introspection so tests can pin the accounting exactly. */
102
+ export function getRetainedBytes(): number {
103
+ return currentBytes;
104
+ }
105
+
106
+ function retainedSize(payload: SharedMessageEncoding['payload']): number {
107
+ // a pending promise is accounted for when it resolves
108
+ if (typeof payload === 'string') return Buffer.byteLength(payload);
109
+ return (payload as Buffer)?.byteLength ?? 0;
110
+ }
111
+
112
+ /** Add to an entry's footprint, and to the budget if the entry is live. */
113
+ function charge(encoding: SharedMessageEncoding, bytes: number) {
114
+ encoding.bytes += bytes;
115
+ if (encoding.epoch === currentEpoch) currentBytes += bytes;
116
+ else if (encoding.epoch === currentEpoch - 1) {
117
+ // Bytes can land after a rotation — a serialization resolving late, or a frame generated by a
118
+ // subscriber whose await spanned one. The entry is still live in the previous generation, so
119
+ // fold its whole footprint into the live budget; charging only the new bytes would leave the
120
+ // rest counted by no generation at all, and charging nothing would under-report the ceiling.
121
+ encoding.epoch = currentEpoch;
122
+ currentBytes += encoding.bytes;
123
+ }
124
+ }
125
+
126
+ /** Give back everything a chain holds, for an entry that is being discarded rather than refilled. */
127
+ function release(encoding: SharedMessageEncoding) {
128
+ for (let node = encoding; node !== undefined; node = node.next) {
129
+ if (node.epoch === currentEpoch) currentBytes -= node.bytes;
130
+ node.epoch = UNRETAINED;
131
+ }
132
+ }
133
+
134
+ function retain(message: object, encoding: SharedMessageEncoding) {
135
+ if (currentBytes >= MAX_RETAINED_BYTES) rotateSharedEncodings();
136
+ currentGeneration.set(message, encoding);
137
+ currentInserts++;
138
+ // charges the whole chain: on a promotion this re-charges everything the entry holds, since
139
+ // rotation zeroed the counter but the bytes are still live
140
+ for (let node = encoding; node !== undefined; node = node.next) {
141
+ if (node.epoch !== currentEpoch) {
142
+ node.epoch = currentEpoch;
143
+ currentBytes += node.bytes;
144
+ }
145
+ }
146
+ if (rotationTimer === undefined) {
147
+ rotationTimer = setInterval(rotateSharedEncodings, ROTATE_INTERVAL_MS);
148
+ rotationTimer.unref?.();
149
+ }
150
+ }
151
+
152
+ function fill(encoding: SharedMessageEncoding, message: any, request: any) {
153
+ // whatever this entry was holding is being replaced, so give the bytes back before re-charging
154
+ if (encoding.epoch === currentEpoch) currentBytes -= encoding.bytes;
155
+ encoding.bytes = 0;
156
+ encoding.frames = undefined;
157
+ // Pessimistic: an entry is only valid once a payload is actually in hand. Set optimistically,
158
+ // a synchronous throw here would leave an already-retained entry claiming success with no
159
+ // payload, and every later subscriber would send an empty PUBLISH instead of erroring.
160
+ encoding.failed = true;
161
+ encoding.payload = undefined;
162
+ const payload = serializeMessage(message, request);
163
+ encoding.payload = payload;
164
+ encoding.failed = false;
165
+ // A pass-through payload IS the message's own data, already reachable from the WeakMap key, so
166
+ // caching it retains nothing extra and must not be billed against the budget.
167
+ if (encoding.serializer === PASS_THROUGH) return;
168
+ if (typeof (payload as any)?.then === 'function')
169
+ // collapse an async serialization in place so later subscribers, and frame sharing, see the
170
+ // finished buffer rather than re-entering the async path
171
+ encoding.payload = (payload as Promise<Buffer | string>).then(
172
+ (resolved) => {
173
+ charge(encoding, retainedSize(resolved));
174
+ return (encoding.payload = resolved);
175
+ },
176
+ (error) => {
177
+ // mark for retry rather than memoize the failure: a shared rejected promise would turn
178
+ // one transient serialization error into a permanent one for every later subscriber
179
+ encoding.failed = true;
180
+ encoding.payload = undefined;
181
+ throw error;
182
+ }
183
+ );
184
+ else charge(encoding, retainedSize(payload));
185
+ }
186
+
187
+ function encode(message: any, request: any, serializer: Function, version?: number): SharedMessageEncoding {
188
+ const encoding: SharedMessageEncoding = {
189
+ serializer,
190
+ version,
191
+ payload: undefined,
192
+ failed: false,
193
+ hits: 0,
194
+ bytes: 0,
195
+ epoch: UNRETAINED,
196
+ frames: undefined,
197
+ next: undefined,
198
+ };
199
+ fill(encoding, message, request);
200
+ return encoding;
201
+ }
202
+
203
+ function reuse(encoding: SharedMessageEncoding, message: any, request: any): SharedMessageEncoding {
204
+ encoding.hits++;
205
+ if (encoding.failed) fill(encoding, message, request);
206
+ return encoding;
207
+ }
208
+
209
+ /**
210
+ * Get the encoding shared by every subscriber that negotiated the same content type. Keyed on the
211
+ * message object's identity, the serializer function (which is what `serializeMessage` output
212
+ * varies on), and the event's record `version`.
213
+ *
214
+ * The version is part of the key, not a permission to share. Identity alone would be unsafe for a
215
+ * producer that reuses one mutable envelope across publishes — an app Resource wrapping a table
216
+ * subscription to enrich events can easily do that, and copies the version straight through with a
217
+ * spread — so a cached entry whose version does not match is treated as a miss and re-encoded.
218
+ * That leaves only same-object-and-same-version mutation, which is indistinguishable from "the same
219
+ * message". An event with no version at all is not shared: nothing then distinguishes one publish
220
+ * from the next.
221
+ */
222
+ export function getSharedMessageEncoding(message: any, request?: any, version?: number): SharedMessageEncoding {
223
+ // Negotiation must not run for a pass-through message: an Accept header naming only unsupported
224
+ // types throws 406, which would kill a delivery that used to succeed by returning message.data.
225
+ const serializer =
226
+ message?.contentType != null && message.data != null ? PASS_THROUGH : getMessageSerializer(request);
227
+ // primitives can not key a WeakMap, and are cheap to encode anyway; these stay per-subscriber
228
+ if (message === null || typeof message !== 'object' || typeof version !== 'number')
229
+ return encode(message, request, serializer);
230
+ let encoding = currentGeneration.get(message);
231
+ if (encoding === undefined) {
232
+ encoding = previousGeneration.get(message);
233
+ // promote a surviving entry so it lives through the next rotation
234
+ if (encoding !== undefined && encoding.version === version) retain(message, encoding);
235
+ }
236
+ if (encoding !== undefined && encoding.version !== version) {
237
+ // the same object carrying a new version: every content type on the chain is stale, so give
238
+ // back what the whole chain held and start over rather than serving the earlier message
239
+ release(encoding);
240
+ encoding = undefined;
241
+ }
242
+ if (encoding === undefined) {
243
+ retain(message, (encoding = encode(message, request, serializer, version)));
244
+ return encoding;
245
+ }
246
+ let last: SharedMessageEncoding;
247
+ do {
248
+ if (encoding.serializer === serializer) return reuse(encoding, message, request);
249
+ last = encoding;
250
+ encoding = encoding.next;
251
+ } while (encoding !== undefined);
252
+ // a second content type on an already-retained message is retained with it, so it is charged too
253
+ const chained = encode(message, request, serializer, version);
254
+ chained.epoch = last.epoch;
255
+ if (chained.epoch === currentEpoch) currentBytes += chained.bytes;
256
+ return (last.next = chained);
257
+ }
258
+
259
+ /**
260
+ * Resolve a still-pending shared serialization, retrying once through a fresh lookup if it failed.
261
+ * Every subscriber currently in the fan-out awaits the same promise, so without this one transient
262
+ * failure would disconnect all of them, where before the encoding was shared each subscriber
263
+ * serialized — and so retried — on its own.
264
+ */
265
+ export async function resolveSharedPayload(
266
+ encoding: SharedMessageEncoding,
267
+ message: any,
268
+ request: any,
269
+ version?: number
270
+ ): Promise<Buffer | string> {
271
+ try {
272
+ return await (encoding.payload as Promise<Buffer | string>);
273
+ } catch (error) {
274
+ // otherwise a failure that the retry recovers from leaves no trace at all
275
+ logger.debug?.('Shared message serialization failed, retrying for this subscriber', error);
276
+ // The entry is marked for retry, or a peer in this same wave has already refilled it — either
277
+ // way, ask again. The first subscriber here re-encodes and the rest share that attempt; if it
278
+ // fails too, that rejection propagates and the caller handles it as it did before sharing.
279
+ return await getSharedMessageEncoding(message, request, version).payload;
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Look up a fully encoded frame shared across subscribers, or undefined if it has not been
285
+ * generated yet. Split from `setSharedFrame` so a cache hit — the whole point on a fan-out —
286
+ * allocates nothing, not even a generator closure.
287
+ */
288
+ export function getSharedFrame(encoding: SharedMessageEncoding, version: number, topic: string): Buffer | undefined {
289
+ return encoding.frames?.get(version)?.get(topic);
290
+ }
291
+
292
+ /**
293
+ * Store a generated frame for reuse by the remaining subscribers, and return it. Call only when
294
+ * `encoding.hits > 0`: a frame stored for a fan-out of one is never read, and would keep a whole
295
+ * PUBLISH buffer reachable from the message object for the rest of its retention window.
296
+ */
297
+ export function setSharedFrame(encoding: SharedMessageEncoding, version: number, topic: string, frame: Buffer): Buffer {
298
+ let frames = encoding.frames;
299
+ if (frames === undefined) encoding.frames = frames = new Map();
300
+ let byTopic = frames.get(version);
301
+ if (byTopic === undefined) frames.set(version, (byTopic = new Map()));
302
+ // concurrent subscribers can each generate before any of them stores; only the retained buffer
303
+ // is charged, or the budget would bill every duplicate that is immediately garbage
304
+ if (!byTopic.has(topic)) charge(encoding, frame.byteLength);
305
+ byTopic.set(topic, frame);
306
+ return frame;
307
+ }
@@ -225,8 +225,23 @@ export async function createUwsServer(options: UwsServerOptions): Promise<{ app:
225
225
  app.any('/*', withBody);
226
226
 
227
227
  await new Promise<void>((resolve, reject) => {
228
- const onListen = (listenSocket: unknown) =>
229
- listenSocket ? resolve() : reject(new Error(`uWS failed to bind ${host ?? ''}:${port ?? socketPath}`));
228
+ let settled = false;
229
+ // Backstop against the native listen callback never firing at all — without it, a stuck
230
+ // bind is indistinguishable from a slow one, and nothing here ever rejects.
231
+ const bindTimeout = setTimeout(() => {
232
+ if (settled) return;
233
+ settled = true;
234
+ reject(
235
+ new Error(`uWS timed out waiting to bind ${host ?? ''}:${port ?? socketPath} (listen callback never fired)`)
236
+ );
237
+ }, 30_000);
238
+ const onListen = (listenSocket: unknown) => {
239
+ if (settled) return;
240
+ settled = true;
241
+ clearTimeout(bindTimeout);
242
+ if (listenSocket) resolve();
243
+ else reject(new Error(`uWS failed to bind ${host ?? ''}:${port ?? socketPath}`));
244
+ };
230
245
  // uWS shares the port across workers (SO_REUSEPORT) by default, matching the Node reusePort path.
231
246
  if (port != null) {
232
247
  if (host) app.listen(host, port, onListen);
package/server/static.ts CHANGED
@@ -5,6 +5,7 @@ import { resolveBaseURLPath } from '../components/resolveBaseURLPath.ts';
5
5
  import { convertToMS } from '../utility/common_utils.ts';
6
6
  import { isMatch } from 'micromatch';
7
7
  import send from 'send';
8
+ import { settleDeferredCredentialRejection } from '../security/deferredAuthentication.ts';
8
9
 
9
10
  /**
10
11
  * The static plugin handles serving static files from the respective application directory.
@@ -337,40 +338,30 @@ export function handleApplication(scope: Scope) {
337
338
  // Retrieve index entry
338
339
  staticFile = indexEntries.get(req.pathname);
339
340
 
340
- // The router strips both '/assets' and '/assets/' down to '/', so the mount root
341
- // must be disambiguated via the unstripped pathname (exposed by stripPrefix):
342
- // redirect the no-slash form so relative links on the index page resolve under
343
- // the mount (#1583). Query string is preserved across both redirects; compute it
344
- // lazily inside each branch so the common (non-redirect) index serve stays allocation-free.
345
- // Gated on the EXTERNAL base path, not the plugin-local one: a root-level static
346
- // plugin (baseURLPath === '/') still needs this redirect when the application
347
- // itself carries a host/urlPath mount, since the client-visible mount root is then
348
- // externalBaseURLPath, not '/' (review finding).
349
- if (staticFile && req.pathname === '/' && externalBaseURLPath !== '/') {
350
- const originalPathname: string | undefined = (req as any).originalPathname;
351
- if (originalPathname && !originalPathname.endsWith('/')) {
352
- const queryIndex = (req.url as string).indexOf('?');
353
- const query = queryIndex === -1 ? '' : (req.url as string).slice(queryIndex);
354
- return {
355
- status: 301,
356
- headers: {
357
- Location: externalBaseURLPath + query,
358
- },
359
- };
360
- }
361
- }
341
+ // Prefix stripping makes `originalPathname` necessary to distinguish mounted roots (#1583).
342
+ const originalPathname: string | undefined = (req as any).originalPathname;
343
+ const redirectsMountRoot = !!(
344
+ staticFile &&
345
+ req.pathname === '/' &&
346
+ externalBaseURLPath !== '/' &&
347
+ originalPathname &&
348
+ !originalPathname.endsWith('/')
349
+ );
362
350
 
363
- // If `null`, redirect to trailing slash. req.pathname arrives with the mount
364
- // prefix stripped, so rebuild the external path for the Location header (#1583)
365
- if (staticFile === null) {
366
- const externalPath =
367
- externalBaseURLPath === '/' ? req.pathname : externalBaseURLPath.slice(0, -1) + req.pathname;
351
+ if (redirectsMountRoot || staticFile === null) {
352
+ const settledCredentialRejection = settleDeferredCredentialRejection(req);
353
+ if (settledCredentialRejection) return settledCredentialRejection;
368
354
  const queryIndex = (req.url as string).indexOf('?');
369
355
  const query = queryIndex === -1 ? '' : (req.url as string).slice(queryIndex);
356
+ const location = redirectsMountRoot
357
+ ? externalBaseURLPath + query
358
+ : (externalBaseURLPath === '/' ? req.pathname : externalBaseURLPath.slice(0, -1) + req.pathname) +
359
+ '/' +
360
+ query;
370
361
  return {
371
362
  status: 301,
372
363
  headers: {
373
- Location: externalPath + '/' + query,
364
+ Location: location,
374
365
  },
375
366
  };
376
367
  }
@@ -393,6 +384,8 @@ export function handleApplication(scope: Scope) {
393
384
 
394
385
  // If an entry matched, serve it
395
386
  if (staticFile) {
387
+ const settledCredentialRejection = settleDeferredCredentialRejection(req);
388
+ if (settledCredentialRejection) return settledCredentialRejection;
396
389
  // The benefit to using `send` is that it handles a lot of edge cases and headers for us.
397
390
  return {
398
391
  handlesHeaders: true,
@@ -405,7 +398,8 @@ export function handleApplication(scope: Scope) {
405
398
  return next(req);
406
399
  }
407
400
 
408
- // Otherwise, handle not found
401
+ const settledCredentialRejection = settleDeferredCredentialRejection(req);
402
+ if (settledCredentialRejection) return settledCredentialRejection;
409
403
 
410
404
  const notFound = scope.options.get(['notFound']);
411
405
 
@@ -1,7 +1,7 @@
1
1
  import { readFile, realpath } from 'node:fs/promises';
2
2
  import { statfs } from 'node:fs/promises';
3
3
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
4
- import { getWorkerIndex, getWorkerCount } from '../server/threads/manageThreads.js';
4
+ import { ownsStoreMaintenance } from '../server/threads/manageThreads.js';
5
5
  import { logger } from '../utility/logging/logger.ts';
6
6
  import { CONFIG_PARAMS } from '../utility/hdbTerms.ts';
7
7
  import * as envMgr from '../utility/environment/environmentManager.ts';
@@ -106,7 +106,7 @@ export function onStorageReclamation(
106
106
  handler: (priority: number) => Promise<void> | void,
107
107
  skipThreadCheck?: boolean
108
108
  ) {
109
- if (skipThreadCheck || getWorkerIndex() === getWorkerCount() - 1) {
109
+ if (skipThreadCheck || ownsStoreMaintenance(path)) {
110
110
  // only run on one thread (last one)
111
111
  if (!path) {
112
112
  throw new Error('Storage reclamation path cannot be empty');
@@ -128,6 +128,19 @@ export function onStorageReclamation(
128
128
  export function removeStorageReclamation(path: string): boolean {
129
129
  return reclamationHandlers.delete(path);
130
130
  }
131
+
132
+ /**
133
+ * Drop one handler; a RocksDB column family shares its path with every other family in the database.
134
+ * The list is replaced rather than spliced so a run iterating it across awaits skips nothing.
135
+ */
136
+ export function removeStorageReclamationHandler(path: string, handler: (priority: number) => unknown): boolean {
137
+ const handlers = reclamationHandlers.get(path);
138
+ const remaining = handlers?.filter((entry) => entry.handler !== handler);
139
+ if (!remaining || remaining.length === handlers.length) return false;
140
+ if (remaining.length === 0) reclamationHandlers.delete(path);
141
+ else reclamationHandlers.set(path, remaining);
142
+ return true;
143
+ }
131
144
  let reclamationTimer: NodeJS.Timeout;
132
145
 
133
146
  export type StorageSpaceStats = {
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Isolated applications: an application whose root-config entry carries `isolated: true` runs in a
3
+ * worker thread of its own that loads no other application (harper#642, tier 2).
4
+ *
5
+ * The invariant every helper here serves: an isolated application is loaded by exactly one thread,
6
+ * and that thread loads nothing else. The dedicated worker is an ordinary `http` worker by type --
7
+ * so restarts, overlap rules and shutdown treat it as one -- distinguished only by
8
+ * `workerData.isolatedApplication`. It binds none of the public ports (the kernel would hand it
9
+ * connections for every other application) and is reachable only through its own UDS mirror, whose
10
+ * metadata names the application and its hosts for the fronting proxy to route by.
11
+ */
12
+ import { isMainThread, workerData } from 'node:worker_threads';
13
+ import { getWorkerIndex } from './manageThreads.js';
14
+ import { getConfigObj, getConfigPath } from '../../config/configUtils.ts';
15
+ import * as env from '../../utility/environment/environmentManager.ts';
16
+ import { CONFIG_PARAMS } from '../../utility/hdbTerms.ts';
17
+ import { isDomainSocketPathTooLong } from '../../utility/domainSocket.ts';
18
+ import { existsSync } from 'node:fs';
19
+ import { basename, join } from 'node:path';
20
+
21
+ export const DEFAULT_MAX_ISOLATED_APPLICATIONS = 8;
22
+
23
+ /** The application this thread is dedicated to, if it is a dedicated worker. */
24
+ export function thisThreadsIsolatedApplication(): string | undefined {
25
+ return (workerData as any)?.isolatedApplication;
26
+ }
27
+
28
+ export function thisThreadOwnsApplication(
29
+ appName: string | undefined,
30
+ owner: string | undefined = thisThreadsIsolatedApplication()
31
+ ): boolean {
32
+ return owner !== undefined && appName === owner;
33
+ }
34
+
35
+ export function isIsolatedApplication(
36
+ appName: string,
37
+ config: Record<string, any> | undefined = getConfigObj()
38
+ ): boolean {
39
+ const entry = config?.[appName];
40
+ return typeof entry === 'object' && entry !== null && entry.isolated === true;
41
+ }
42
+
43
+ /** Every application the root config marks isolated, in config order. */
44
+ export function isolatedApplicationNames(config: Record<string, any> | undefined = getConfigObj()): string[] {
45
+ if (!config) return [];
46
+ return Object.keys(config).filter((name) => isIsolatedApplication(name, config));
47
+ }
48
+
49
+ export function presentIsolatedApplicationNames(
50
+ config: Record<string, any> | undefined = getConfigObj(),
51
+ componentsRoot: string = getConfigPath(CONFIG_PARAMS.COMPONENTSROOT) as string,
52
+ installedRoot: string = join(env.get(CONFIG_PARAMS.ROOTPATH), 'components'),
53
+ runApplicationPath: string | undefined = process.env.RUN_HDB_APP
54
+ ): string[] {
55
+ return isolatedApplicationNames(config).filter(
56
+ (application) =>
57
+ existsSync(join(componentsRoot, application)) ||
58
+ existsSync(join(installedRoot, application)) ||
59
+ (runApplicationPath && basename(runApplicationPath) === application)
60
+ );
61
+ }
62
+
63
+ export function maxIsolatedApplications(): number {
64
+ const configured = Number(env.get(CONFIG_PARAMS.THREADS_MAXISOLATED));
65
+ return Number.isInteger(configured) && configured >= 0 ? configured : DEFAULT_MAX_ISOLATED_APPLICATIONS;
66
+ }
67
+
68
+ /** Why `appName` cannot claim a place in the dedicated-worker budget, if the budget is full. */
69
+ export function isolatedApplicationCapacityRefusal(
70
+ appName: string,
71
+ runningApplications: Iterable<string>,
72
+ max = maxIsolatedApplications()
73
+ ): string | undefined {
74
+ const running = new Set(runningApplications);
75
+ if (running.has(appName) || running.size < max) return undefined;
76
+ return `the instance already runs ${max} isolated application(s) (threads.maxIsolated)`;
77
+ }
78
+
79
+ /**
80
+ * Whether the calling thread is the one that loads the application `appName` (an application: a
81
+ * directory under componentsRoot, or a root-config entry with `package`). A dedicated worker loads
82
+ * only its own application; every other thread -- pool workers and the main thread alike -- loads only
83
+ * the applications that are not isolated. Decided before any of the application's modules are
84
+ * imported, so a skipped application has no side effects on the thread that skipped it.
85
+ */
86
+ export function shouldLoadApplicationHere(
87
+ appName: string,
88
+ owner: string | undefined = thisThreadsIsolatedApplication(),
89
+ config: Record<string, any> | undefined = getConfigObj()
90
+ ): boolean {
91
+ if (owner !== undefined) return appName === owner;
92
+ return !isIsolatedApplication(appName, config);
93
+ }
94
+
95
+ /**
96
+ * Whether this thread starts the uWS listener for one `uwsServeConfigs` entry (see listenOnPorts()).
97
+ * A dedicated worker starts only its own per-application UDS mirrors -- the entries that carry a
98
+ * `socketPath` -- and never a global port listener, which the kernel would hand connections for every
99
+ * other application.
100
+ */
101
+ export function shouldStartUwsListenerHere(
102
+ serveConfig: { socketPath?: string },
103
+ owner: string | undefined = thisThreadsIsolatedApplication()
104
+ ): boolean {
105
+ return owner === undefined || Boolean(serveConfig.socketPath);
106
+ }
107
+
108
+ /**
109
+ * Whether a dedicated worker can be reached at all: it binds only UDS mirrors of the secure port, so
110
+ * without `tls.unixDomainSockets` and a secure port an isolated application would load and answer
111
+ * nothing, silently. Refused at admission instead. Returns the reason, or undefined when reachable.
112
+ */
113
+ export function isolatedApplicationsUnreachableReason(platform = process.platform): string | undefined {
114
+ if (platform === 'win32') return 'Windows does not support per-application UDS mirrors';
115
+ // the main thread standing in as the only worker (threads.count: 0) has no thread to give
116
+ if (isMainThread && getWorkerIndex() === 0) return 'threads.count is 0, so there is no worker thread to dedicate';
117
+ if (!env.get(CONFIG_PARAMS.HTTP_SECUREPORT)) return 'no http.securePort is configured';
118
+ if (!env.get(CONFIG_PARAMS.TLS_UNIXDOMAINSOCKETS)) return 'tls.unixDomainSockets is not enabled';
119
+ return undefined;
120
+ }
121
+
122
+ /** Why `appName` cannot get a dedicated worker on this instance, or undefined when it can. */
123
+ export function isolatedApplicationRefusal(appName: string): string | undefined {
124
+ const unreachable = isolatedApplicationsUnreachableReason();
125
+ if (unreachable) return `its worker would be unreachable: ${unreachable}`;
126
+ const socketPath = join(
127
+ env.getHdbBasePath(),
128
+ 'sockets',
129
+ `${applicationSocketName(appName, env.get(CONFIG_PARAMS.HTTP_SECUREPORT))}.sock`
130
+ );
131
+ if (isDomainSocketPathTooLong(socketPath)) return `its UDS mirror path ${socketPath} exceeds the platform limit`;
132
+ return undefined;
133
+ }
134
+
135
+ /**
136
+ * The filesystem name of an isolated worker's UDS mirror for `port`: every UTF-8 byte outside
137
+ * `[A-Za-z0-9._]` becomes a fixed-width `%XX`, which is injective (two application names never share
138
+ * a socket), and the `app-` prefix keeps it apart from the pool's `<workerIndex>-<port>` names.
139
+ */
140
+ export function applicationSocketName(appName: string, port: number | string): string {
141
+ let encoded = '';
142
+ for (const byte of Buffer.from(appName, 'utf8')) {
143
+ const c = String.fromCharCode(byte);
144
+ encoded += byte < 0x80 && /[A-Za-z0-9._]/.test(c) ? c : `%${byte.toString(16).toUpperCase().padStart(2, '0')}`;
145
+ }
146
+ return `app-${encoded}-${port}`;
147
+ }
148
+
149
+ /** What a dedicated worker publishes in its mirror metadata for the proxy to route by. */
150
+ export function isolatedApplicationRoute(
151
+ appName: string | undefined = thisThreadsIsolatedApplication(),
152
+ config: Record<string, any> | undefined = getConfigObj()
153
+ ): { application: string; hosts: string[] } | undefined {
154
+ if (!appName) return undefined;
155
+ const host = config?.[appName]?.host; // a string, as the mount parser requires
156
+ return { application: appName, hosts: typeof host === 'string' && host ? [host] : [] };
157
+ }
@@ -72,14 +72,24 @@ function validateEvent(event) {
72
72
  * @param schema
73
73
  * @param table
74
74
  * @param attribute
75
+ * @param branchPath the branch directory when the change is to a scope-private branch of `schema`
76
+ * rather than to the database itself (resources/databases.ts `reloadBranchAt`)
75
77
  * @constructor
76
78
  */
77
- function SchemaEventMsg(originator, operation, schema, table = undefined, attribute = undefined) {
79
+ function SchemaEventMsg(
80
+ originator,
81
+ operation,
82
+ schema,
83
+ table = undefined,
84
+ attribute = undefined,
85
+ branchPath = undefined
86
+ ) {
78
87
  this.originator = originator;
79
88
  this.operation = operation;
80
89
  this.schema = schema;
81
90
  this.table = table;
82
91
  this.attribute = attribute;
92
+ if (branchPath) this.branchPath = branchPath;
83
93
  }
84
94
 
85
95
  /**