@harperfast/harper 5.2.10 → 5.3.0-alpha.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 (554) hide show
  1. package/agent/mcpTools.ts +1 -1
  2. package/agent/session.ts +25 -14
  3. package/bin/cliOperations.ts +46 -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 +59 -3
  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 +2414 -242
  14. package/components/ApplicationScope.ts +8 -0
  15. package/components/EntryHandler.ts +59 -39
  16. package/components/OptionsWatcher.ts +150 -74
  17. package/components/RuntimeModuleTracker.ts +38 -7
  18. package/components/Scope.ts +37 -15
  19. package/components/awaitRestart.ts +84 -0
  20. package/components/componentLoader.ts +340 -30
  21. package/components/componentPreparationLock.ts +16 -5
  22. package/components/mcp/adapters/harperHttp.ts +4 -0
  23. package/components/mcp/listChanged.ts +4 -0
  24. package/components/mcp/toolRegistry.ts +2 -0
  25. package/components/mcp/tools/operations.ts +9 -0
  26. package/components/mcp/tools/schemas/operationDescriptions.ts +2 -2
  27. package/components/operations.js +270 -78
  28. package/components/operationsValidation.js +49 -1
  29. package/components/status/ComponentStatusRegistry.ts +59 -0
  30. package/config/RootConfigWatcher.ts +80 -34
  31. package/config/configUtils.ts +291 -34
  32. package/config/harperConfigEnvVars.ts +170 -27
  33. package/config-root.schema.json +29 -0
  34. package/dataLayer/blobBackup.ts +160 -50
  35. package/dataLayer/delete.ts +6 -1
  36. package/dataLayer/harperBridge/ResourceBridge.ts +52 -8
  37. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  38. package/dataLayer/hdbInfoController.ts +34 -1
  39. package/dataLayer/insert.ts +44 -1
  40. package/dataLayer/rocksdbBackup.ts +53 -10
  41. package/dataLayer/schema.ts +11 -1
  42. package/dataLayer/schemaDescribe.ts +8 -1
  43. package/dist/agent/mcpTools.js +1 -1
  44. package/dist/agent/mcpTools.js.map +1 -1
  45. package/dist/agent/session.d.ts +22 -0
  46. package/dist/agent/session.js +26 -15
  47. package/dist/agent/session.js.map +1 -1
  48. package/dist/bin/cliOperations.js +48 -9
  49. package/dist/bin/cliOperations.js.map +1 -1
  50. package/dist/bin/copyDb.d.ts +12 -1
  51. package/dist/bin/copyDb.js +248 -60
  52. package/dist/bin/copyDb.js.map +1 -1
  53. package/dist/bin/deploySetup.d.ts +2 -0
  54. package/dist/bin/deploySetup.js +11 -3
  55. package/dist/bin/deploySetup.js.map +1 -1
  56. package/dist/bin/harper.js +1 -1
  57. package/dist/bin/harper.js.map +1 -1
  58. package/dist/bin/help.js +4 -1
  59. package/dist/bin/help.js.map +1 -1
  60. package/dist/bin/lite.js +4 -1
  61. package/dist/bin/lite.js.map +1 -1
  62. package/dist/bin/restart.js +54 -5
  63. package/dist/bin/restart.js.map +1 -1
  64. package/dist/bin/run.js +4 -10
  65. package/dist/bin/run.js.map +1 -1
  66. package/dist/bin/upgrade.js +4 -3
  67. package/dist/bin/upgrade.js.map +1 -1
  68. package/dist/bin/workloadIdentity.d.ts +18 -0
  69. package/dist/bin/workloadIdentity.js +100 -0
  70. package/dist/bin/workloadIdentity.js.map +1 -0
  71. package/dist/components/Application.d.ts +139 -16
  72. package/dist/components/Application.js +2215 -267
  73. package/dist/components/Application.js.map +1 -1
  74. package/dist/components/ApplicationScope.d.ts +8 -0
  75. package/dist/components/ApplicationScope.js +7 -0
  76. package/dist/components/ApplicationScope.js.map +1 -1
  77. package/dist/components/EntryHandler.js +26 -10
  78. package/dist/components/EntryHandler.js.map +1 -1
  79. package/dist/components/OptionsWatcher.d.ts +1 -0
  80. package/dist/components/OptionsWatcher.js +141 -74
  81. package/dist/components/OptionsWatcher.js.map +1 -1
  82. package/dist/components/RuntimeModuleTracker.js +40 -6
  83. package/dist/components/RuntimeModuleTracker.js.map +1 -1
  84. package/dist/components/Scope.js +38 -13
  85. package/dist/components/Scope.js.map +1 -1
  86. package/dist/components/awaitRestart.d.ts +33 -0
  87. package/dist/components/awaitRestart.js +61 -0
  88. package/dist/components/awaitRestart.js.map +1 -0
  89. package/dist/components/componentLoader.d.ts +38 -1
  90. package/dist/components/componentLoader.js +279 -22
  91. package/dist/components/componentLoader.js.map +1 -1
  92. package/dist/components/componentPreparationLock.d.ts +5 -0
  93. package/dist/components/componentPreparationLock.js +14 -6
  94. package/dist/components/componentPreparationLock.js.map +1 -1
  95. package/dist/components/mcp/adapters/harperHttp.js +4 -0
  96. package/dist/components/mcp/adapters/harperHttp.js.map +1 -1
  97. package/dist/components/mcp/listChanged.js +5 -0
  98. package/dist/components/mcp/listChanged.js.map +1 -1
  99. package/dist/components/mcp/toolRegistry.d.ts +1 -0
  100. package/dist/components/mcp/toolRegistry.js.map +1 -1
  101. package/dist/components/mcp/tools/operations.d.ts +5 -0
  102. package/dist/components/mcp/tools/operations.js +9 -0
  103. package/dist/components/mcp/tools/operations.js.map +1 -1
  104. package/dist/components/mcp/tools/schemas/operationDescriptions.js +2 -2
  105. package/dist/components/mcp/tools/schemas/operationDescriptions.js.map +1 -1
  106. package/dist/components/operations.js +231 -77
  107. package/dist/components/operations.js.map +1 -1
  108. package/dist/components/operationsValidation.js +49 -1
  109. package/dist/components/operationsValidation.js.map +1 -1
  110. package/dist/components/status/ComponentStatusRegistry.d.ts +0 -4
  111. package/dist/components/status/ComponentStatusRegistry.js +63 -0
  112. package/dist/components/status/ComponentStatusRegistry.js.map +1 -1
  113. package/dist/config/RootConfigWatcher.d.ts +7 -1
  114. package/dist/config/RootConfigWatcher.js +64 -27
  115. package/dist/config/RootConfigWatcher.js.map +1 -1
  116. package/dist/config/configUtils.d.ts +9 -1
  117. package/dist/config/configUtils.js +254 -33
  118. package/dist/config/configUtils.js.map +1 -1
  119. package/dist/config/harperConfigEnvVars.d.ts +16 -0
  120. package/dist/config/harperConfigEnvVars.js +162 -25
  121. package/dist/config/harperConfigEnvVars.js.map +1 -1
  122. package/dist/dataLayer/blobBackup.d.ts +49 -20
  123. package/dist/dataLayer/blobBackup.js +139 -50
  124. package/dist/dataLayer/blobBackup.js.map +1 -1
  125. package/dist/dataLayer/delete.js +1 -1
  126. package/dist/dataLayer/delete.js.map +1 -1
  127. package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +14 -1
  128. package/dist/dataLayer/harperBridge/ResourceBridge.js +51 -10
  129. package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
  130. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.d.ts +3 -1
  131. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  132. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js.map +1 -1
  133. package/dist/dataLayer/hdbInfoController.d.ts +10 -0
  134. package/dist/dataLayer/hdbInfoController.js +30 -1
  135. package/dist/dataLayer/hdbInfoController.js.map +1 -1
  136. package/dist/dataLayer/insert.d.ts +9 -1
  137. package/dist/dataLayer/insert.js +30 -0
  138. package/dist/dataLayer/insert.js.map +1 -1
  139. package/dist/dataLayer/rocksdbBackup.d.ts +2 -2
  140. package/dist/dataLayer/rocksdbBackup.js +45 -8
  141. package/dist/dataLayer/rocksdbBackup.js.map +1 -1
  142. package/dist/dataLayer/schema.js +8 -0
  143. package/dist/dataLayer/schema.js.map +1 -1
  144. package/dist/dataLayer/schemaDescribe.js +8 -1
  145. package/dist/dataLayer/schemaDescribe.js.map +1 -1
  146. package/dist/index.d.ts +1 -1
  147. package/dist/index.js.map +1 -1
  148. package/dist/json/systemSchema.json +52 -0
  149. package/dist/resources/DatabaseTransaction.d.ts +55 -3
  150. package/dist/resources/DatabaseTransaction.js +460 -134
  151. package/dist/resources/DatabaseTransaction.js.map +1 -1
  152. package/dist/resources/LMDBTransaction.js +22 -4
  153. package/dist/resources/LMDBTransaction.js.map +1 -1
  154. package/dist/resources/PrimaryRocksDatabase.d.ts +1 -0
  155. package/dist/resources/PrimaryRocksDatabase.js +30 -2
  156. package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
  157. package/dist/resources/RecordEncoder.d.ts +20 -0
  158. package/dist/resources/RecordEncoder.js +94 -9
  159. package/dist/resources/RecordEncoder.js.map +1 -1
  160. package/dist/resources/RequestTarget.d.ts +2 -0
  161. package/dist/resources/RequestTarget.js.map +1 -1
  162. package/dist/resources/Resource.js +20 -11
  163. package/dist/resources/Resource.js.map +1 -1
  164. package/dist/resources/ResourceInterface.d.ts +20 -1
  165. package/dist/resources/ResourceInterface.js.map +1 -1
  166. package/dist/resources/RocksIndexStore.d.ts +6 -1
  167. package/dist/resources/RocksIndexStore.js +24 -10
  168. package/dist/resources/RocksIndexStore.js.map +1 -1
  169. package/dist/resources/RocksTransactionLogStore.d.ts +14 -1
  170. package/dist/resources/RocksTransactionLogStore.js +57 -17
  171. package/dist/resources/RocksTransactionLogStore.js.map +1 -1
  172. package/dist/resources/Table.d.ts +112 -8
  173. package/dist/resources/Table.js +1071 -197
  174. package/dist/resources/Table.js.map +1 -1
  175. package/dist/resources/auditStore.d.ts +11 -2
  176. package/dist/resources/auditStore.js +183 -18
  177. package/dist/resources/auditStore.js.map +1 -1
  178. package/dist/resources/blob.d.ts +129 -9
  179. package/dist/resources/blob.js +992 -114
  180. package/dist/resources/blob.js.map +1 -1
  181. package/dist/resources/branchDatabase.d.ts +48 -0
  182. package/dist/resources/branchDatabase.js +892 -0
  183. package/dist/resources/branchDatabase.js.map +1 -0
  184. package/dist/resources/crdt.js +50 -12
  185. package/dist/resources/crdt.js.map +1 -1
  186. package/dist/resources/databases.d.ts +150 -9
  187. package/dist/resources/databases.js +1247 -525
  188. package/dist/resources/databases.js.map +1 -1
  189. package/dist/resources/defineTable.d.ts +10 -2
  190. package/dist/resources/defineTable.js +9 -1
  191. package/dist/resources/defineTable.js.map +1 -1
  192. package/dist/resources/graphql.d.ts +1 -1
  193. package/dist/resources/graphql.js +50 -15
  194. package/dist/resources/graphql.js.map +1 -1
  195. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +1 -0
  196. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +6 -2
  197. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
  198. package/dist/resources/longLivedTransactions.d.ts +71 -0
  199. package/dist/resources/longLivedTransactions.js +358 -0
  200. package/dist/resources/longLivedTransactions.js.map +1 -0
  201. package/dist/resources/models/backendRegistry.d.ts +26 -0
  202. package/dist/resources/models/backendRegistry.js +60 -2
  203. package/dist/resources/models/backendRegistry.js.map +1 -1
  204. package/dist/resources/models/bootstrap.d.ts +33 -1
  205. package/dist/resources/models/bootstrap.js +416 -31
  206. package/dist/resources/models/bootstrap.js.map +1 -1
  207. package/dist/resources/recordLock.d.ts +80 -0
  208. package/dist/resources/recordLock.js +184 -0
  209. package/dist/resources/recordLock.js.map +1 -0
  210. package/dist/resources/replayLogs.d.ts +14 -1
  211. package/dist/resources/replayLogs.js +152 -24
  212. package/dist/resources/replayLogs.js.map +1 -1
  213. package/dist/resources/replayLogsGuards.d.ts +94 -7
  214. package/dist/resources/replayLogsGuards.js +111 -7
  215. package/dist/resources/replayLogsGuards.js.map +1 -1
  216. package/dist/resources/search.js +158 -32
  217. package/dist/resources/search.js.map +1 -1
  218. package/dist/resources/transactionBroadcast.d.ts +1 -1
  219. package/dist/resources/transactionBroadcast.js +2 -2
  220. package/dist/resources/transactionBroadcast.js.map +1 -1
  221. package/dist/security/auth.js +61 -30
  222. package/dist/security/auth.js.map +1 -1
  223. package/dist/security/authn/oidc/claims.d.ts +22 -0
  224. package/dist/security/authn/oidc/claims.js +71 -0
  225. package/dist/security/authn/oidc/claims.js.map +1 -0
  226. package/dist/security/authn/oidc/identityToken.d.ts +27 -0
  227. package/dist/security/authn/oidc/identityToken.js +111 -0
  228. package/dist/security/authn/oidc/identityToken.js.map +1 -0
  229. package/dist/security/authn/oidc/jwks.d.ts +25 -0
  230. package/dist/security/authn/oidc/jwks.js +261 -0
  231. package/dist/security/authn/oidc/jwks.js.map +1 -0
  232. package/dist/security/authn/oidc/providers/generic.d.ts +13 -0
  233. package/dist/security/authn/oidc/providers/generic.js +34 -0
  234. package/dist/security/authn/oidc/providers/generic.js.map +1 -0
  235. package/dist/security/authn/oidc/providers/githubActions.d.ts +11 -0
  236. package/dist/security/authn/oidc/providers/githubActions.js +129 -0
  237. package/dist/security/authn/oidc/providers/githubActions.js.map +1 -0
  238. package/dist/security/authn/oidc/providers/index.d.ts +37 -0
  239. package/dist/security/authn/oidc/providers/index.js +24 -0
  240. package/dist/security/authn/oidc/providers/index.js.map +1 -0
  241. package/dist/security/authn/oidc/tokenExchange.d.ts +12 -0
  242. package/dist/security/authn/oidc/tokenExchange.js +306 -0
  243. package/dist/security/authn/oidc/tokenExchange.js.map +1 -0
  244. package/dist/security/authn/oidc/trustPolicyOperations.d.ts +49 -0
  245. package/dist/security/authn/oidc/trustPolicyOperations.js +358 -0
  246. package/dist/security/authn/oidc/trustPolicyOperations.js.map +1 -0
  247. package/dist/security/authn/oidc/types.d.ts +38 -0
  248. package/dist/security/authn/oidc/types.js +6 -0
  249. package/dist/security/authn/oidc/types.js.map +1 -0
  250. package/dist/security/certificateVerification/index.js +40 -11
  251. package/dist/security/certificateVerification/index.js.map +1 -1
  252. package/dist/security/certificateVerification/trustedIssuers.d.ts +24 -0
  253. package/dist/security/certificateVerification/trustedIssuers.js +79 -0
  254. package/dist/security/certificateVerification/trustedIssuers.js.map +1 -0
  255. package/dist/security/certificateVerification/types.d.ts +1 -0
  256. package/dist/security/credentialProvenance.d.ts +35 -0
  257. package/dist/security/credentialProvenance.js +51 -0
  258. package/dist/security/credentialProvenance.js.map +1 -0
  259. package/dist/security/credentialRejection.d.ts +4 -0
  260. package/dist/security/credentialRejection.js +24 -0
  261. package/dist/security/credentialRejection.js.map +1 -0
  262. package/dist/security/deferredAuthentication.d.ts +36 -0
  263. package/dist/security/deferredAuthentication.js +70 -0
  264. package/dist/security/deferredAuthentication.js.map +1 -0
  265. package/dist/security/impersonation.d.ts +21 -0
  266. package/dist/security/impersonation.js +108 -9
  267. package/dist/security/impersonation.js.map +1 -1
  268. package/dist/security/jsLoader.d.ts +6 -0
  269. package/dist/security/jsLoader.js +75 -15
  270. package/dist/security/jsLoader.js.map +1 -1
  271. package/dist/security/keys.js +301 -71
  272. package/dist/security/keys.js.map +1 -1
  273. package/dist/security/operationScope.d.ts +21 -0
  274. package/dist/security/operationScope.js +36 -0
  275. package/dist/security/operationScope.js.map +1 -0
  276. package/dist/security/permissionsTranslator.js +21 -0
  277. package/dist/security/permissionsTranslator.js.map +1 -1
  278. package/dist/security/tokenAuthentication.d.ts +19 -1
  279. package/dist/security/tokenAuthentication.js +191 -10
  280. package/dist/security/tokenAuthentication.js.map +1 -1
  281. package/dist/security/user.js +4 -3
  282. package/dist/security/user.js.map +1 -1
  283. package/dist/server/DurableSubscriptionsSession.d.ts +2 -2
  284. package/dist/server/DurableSubscriptionsSession.js +67 -10
  285. package/dist/server/DurableSubscriptionsSession.js.map +1 -1
  286. package/dist/server/REST.js +73 -0
  287. package/dist/server/REST.js.map +1 -1
  288. package/dist/server/graphqlQuerying.js +4 -0
  289. package/dist/server/graphqlQuerying.js.map +1 -1
  290. package/dist/server/http.d.ts +11 -0
  291. package/dist/server/http.js +88 -15
  292. package/dist/server/http.js.map +1 -1
  293. package/dist/server/itc/serverHandlers.js +8 -1
  294. package/dist/server/itc/serverHandlers.js.map +1 -1
  295. package/dist/server/jobs/jobProcess.js +6 -2
  296. package/dist/server/jobs/jobProcess.js.map +1 -1
  297. package/dist/server/jobs/jobs.js +4 -1
  298. package/dist/server/jobs/jobs.js.map +1 -1
  299. package/dist/server/liveSubscriptionAuth.d.ts +26 -4
  300. package/dist/server/liveSubscriptionAuth.js +105 -39
  301. package/dist/server/liveSubscriptionAuth.js.map +1 -1
  302. package/dist/server/loadRootComponents.js +49 -10
  303. package/dist/server/loadRootComponents.js.map +1 -1
  304. package/dist/server/mqtt.d.ts +2 -0
  305. package/dist/server/mqtt.js +165 -30
  306. package/dist/server/mqtt.js.map +1 -1
  307. package/dist/server/nodeName.d.ts +2 -0
  308. package/dist/server/nodeName.js +107 -23
  309. package/dist/server/nodeName.js.map +1 -1
  310. package/dist/server/serverHelpers/Headers.d.ts +25 -0
  311. package/dist/server/serverHelpers/Headers.js +139 -1
  312. package/dist/server/serverHelpers/Headers.js.map +1 -1
  313. package/dist/server/serverHelpers/contentTypes.d.ts +9 -0
  314. package/dist/server/serverHelpers/contentTypes.js +32 -25
  315. package/dist/server/serverHelpers/contentTypes.js.map +1 -1
  316. package/dist/server/serverHelpers/deployValidationState.d.ts +3 -0
  317. package/dist/server/serverHelpers/deployValidationState.js +9 -19
  318. package/dist/server/serverHelpers/deployValidationState.js.map +1 -1
  319. package/dist/server/serverHelpers/operationAuthorizationState.d.ts +12 -0
  320. package/dist/server/serverHelpers/operationAuthorizationState.js +24 -2
  321. package/dist/server/serverHelpers/operationAuthorizationState.js.map +1 -1
  322. package/dist/server/serverHelpers/registeredOperations.d.ts +5 -4
  323. package/dist/server/serverHelpers/registeredOperations.js +74 -21
  324. package/dist/server/serverHelpers/registeredOperations.js.map +1 -1
  325. package/dist/server/serverHelpers/requestSanitization.d.ts +11 -0
  326. package/dist/server/serverHelpers/requestSanitization.js +20 -0
  327. package/dist/server/serverHelpers/requestSanitization.js.map +1 -0
  328. package/dist/server/serverHelpers/serverHandlers.js +6 -3
  329. package/dist/server/serverHelpers/serverHandlers.js.map +1 -1
  330. package/dist/server/serverHelpers/serverUtilities.d.ts +18 -0
  331. package/dist/server/serverHelpers/serverUtilities.js +90 -20
  332. package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
  333. package/dist/server/serverHelpers/sharedMessageEncoding.d.ts +67 -0
  334. package/dist/server/serverHelpers/sharedMessageEncoding.js +280 -0
  335. package/dist/server/serverHelpers/sharedMessageEncoding.js.map +1 -0
  336. package/dist/server/serverHelpers/uwsServer.js +19 -1
  337. package/dist/server/serverHelpers/uwsServer.js.map +1 -1
  338. package/dist/server/static.js +24 -28
  339. package/dist/server/static.js.map +1 -1
  340. package/dist/server/storageReclamation.d.ts +5 -0
  341. package/dist/server/storageReclamation.js +16 -0
  342. package/dist/server/storageReclamation.js.map +1 -1
  343. package/dist/server/threads/itc.d.ts +7 -2
  344. package/dist/server/threads/itc.js +5 -1
  345. package/dist/server/threads/itc.js.map +1 -1
  346. package/dist/server/threads/manageThreads.d.ts +26 -4
  347. package/dist/server/threads/manageThreads.js +517 -72
  348. package/dist/server/threads/manageThreads.js.map +1 -1
  349. package/dist/server/threads/socketRouter.js +89 -26
  350. package/dist/server/threads/socketRouter.js.map +1 -1
  351. package/dist/server/threads/threadHeapMemory.d.ts +2 -0
  352. package/dist/server/threads/threadHeapMemory.js +31 -0
  353. package/dist/server/threads/threadHeapMemory.js.map +1 -0
  354. package/dist/server/threads/threadServer.js +46 -15
  355. package/dist/server/threads/threadServer.js.map +1 -1
  356. package/dist/sqlEngine/config.d.ts +1 -3
  357. package/dist/sqlEngine/config.js +19 -16
  358. package/dist/sqlEngine/config.js.map +1 -1
  359. package/dist/sqlTranslator/index.d.ts +1 -1
  360. package/dist/sqlTranslator/index.js +30 -7
  361. package/dist/sqlTranslator/index.js.map +1 -1
  362. package/dist/upgrade/directives/5-3-0.d.ts +7 -0
  363. package/dist/upgrade/directives/5-3-0.js +148 -0
  364. package/dist/upgrade/directives/5-3-0.js.map +1 -0
  365. package/dist/upgrade/directives/directivesController.js +2 -1
  366. package/dist/upgrade/directives/directivesController.js.map +1 -1
  367. package/dist/utility/OperationFunctionCaller.js +2 -1
  368. package/dist/utility/OperationFunctionCaller.js.map +1 -1
  369. package/dist/utility/common_utils.d.ts +16 -0
  370. package/dist/utility/common_utils.js +32 -6
  371. package/dist/utility/common_utils.js.map +1 -1
  372. package/dist/utility/componentNames.d.ts +8 -0
  373. package/dist/utility/componentNames.js +12 -1
  374. package/dist/utility/componentNames.js.map +1 -1
  375. package/dist/utility/environment/environmentManager.js +3 -6
  376. package/dist/utility/environment/environmentManager.js.map +1 -1
  377. package/dist/utility/environment/systemInformation.d.ts +1 -0
  378. package/dist/utility/environment/systemInformation.js +1 -0
  379. package/dist/utility/environment/systemInformation.js.map +1 -1
  380. package/dist/utility/errors/commonErrors.d.ts +2 -0
  381. package/dist/utility/errors/commonErrors.js +2 -0
  382. package/dist/utility/errors/commonErrors.js.map +1 -1
  383. package/dist/utility/errors/hdbError.d.ts +17 -0
  384. package/dist/utility/errors/hdbError.js +30 -1
  385. package/dist/utility/errors/hdbError.js.map +1 -1
  386. package/dist/utility/globalSchema.d.ts +18 -0
  387. package/dist/utility/hdbTerms.d.ts +16 -0
  388. package/dist/utility/hdbTerms.js +18 -2
  389. package/dist/utility/hdbTerms.js.map +1 -1
  390. package/dist/utility/logging/harper_logger.d.ts +2 -0
  391. package/dist/utility/logging/harper_logger.js +91 -14
  392. package/dist/utility/logging/harper_logger.js.map +1 -1
  393. package/dist/utility/logging/logRotator.js +76 -49
  394. package/dist/utility/logging/logRotator.js.map +1 -1
  395. package/dist/utility/nodeIdentity.d.ts +9 -0
  396. package/dist/utility/nodeIdentity.js +58 -0
  397. package/dist/utility/nodeIdentity.js.map +1 -0
  398. package/dist/utility/npmUtilities.js +9 -7
  399. package/dist/utility/npmUtilities.js.map +1 -1
  400. package/dist/utility/operationPermissions.d.ts +3 -1
  401. package/dist/utility/operationPermissions.js +16 -1
  402. package/dist/utility/operationPermissions.js.map +1 -1
  403. package/dist/utility/operation_authorization.d.ts +10 -7
  404. package/dist/utility/operation_authorization.js +212 -41
  405. package/dist/utility/operation_authorization.js.map +1 -1
  406. package/dist/utility/watchPath.d.ts +29 -0
  407. package/dist/utility/watchPath.js +68 -0
  408. package/dist/utility/watchPath.js.map +1 -0
  409. package/dist/utility/watcherFallback.d.ts +86 -0
  410. package/dist/utility/watcherFallback.js +278 -1
  411. package/dist/utility/watcherFallback.js.map +1 -1
  412. package/dist/validation/configValidator.d.ts +12 -0
  413. package/dist/validation/configValidator.js +199 -72
  414. package/dist/validation/configValidator.js.map +1 -1
  415. package/dist/validation/installValidator.js +12 -0
  416. package/dist/validation/installValidator.js.map +1 -1
  417. package/dist/validation/validationWrapper.d.ts +11 -0
  418. package/dist/validation/validationWrapper.js +16 -3
  419. package/dist/validation/validationWrapper.js.map +1 -1
  420. package/index.ts +2 -0
  421. package/json/systemSchema.json +52 -0
  422. package/npm-shrinkwrap.json +235 -233
  423. package/package.json +8 -7
  424. package/resources/DESIGN.md +114 -52
  425. package/resources/DatabaseTransaction.ts +522 -130
  426. package/resources/LMDBTransaction.ts +26 -4
  427. package/resources/PrimaryRocksDatabase.ts +29 -3
  428. package/resources/RecordEncoder.ts +103 -8
  429. package/resources/RequestTarget.ts +2 -0
  430. package/resources/Resource.ts +17 -9
  431. package/resources/ResourceInterface.ts +23 -0
  432. package/resources/RocksIndexStore.ts +30 -10
  433. package/resources/RocksTransactionLogStore.ts +78 -21
  434. package/resources/Table.ts +1107 -164
  435. package/resources/auditStore.ts +187 -21
  436. package/resources/blob.ts +1029 -110
  437. package/resources/branchDatabase.ts +941 -0
  438. package/resources/crdt.ts +76 -12
  439. package/resources/databases.ts +1354 -522
  440. package/resources/defineTable.ts +18 -2
  441. package/resources/graphql.ts +70 -16
  442. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +6 -2
  443. package/resources/longLivedTransactions.ts +360 -0
  444. package/resources/models/backendRegistry.ts +84 -2
  445. package/resources/models/bootstrap.ts +473 -28
  446. package/resources/recordLock.ts +253 -0
  447. package/resources/replayLogs.ts +147 -26
  448. package/resources/replayLogsGuards.ts +171 -8
  449. package/resources/search.ts +154 -32
  450. package/resources/transactionBroadcast.ts +3 -3
  451. package/security/auth.ts +68 -29
  452. package/security/authn/oidc/claims.ts +72 -0
  453. package/security/authn/oidc/identityToken.ts +129 -0
  454. package/security/authn/oidc/jwks.ts +260 -0
  455. package/security/authn/oidc/providers/generic.ts +40 -0
  456. package/security/authn/oidc/providers/githubActions.ts +137 -0
  457. package/security/authn/oidc/providers/index.ts +52 -0
  458. package/security/authn/oidc/tokenExchange.ts +300 -0
  459. package/security/authn/oidc/trustPolicyOperations.ts +343 -0
  460. package/security/authn/oidc/types.ts +41 -0
  461. package/security/certificateVerification/index.ts +54 -13
  462. package/security/certificateVerification/trustedIssuers.ts +76 -0
  463. package/security/certificateVerification/types.ts +1 -0
  464. package/security/credentialProvenance.ts +47 -0
  465. package/security/credentialRejection.ts +22 -0
  466. package/security/deferredAuthentication.ts +71 -0
  467. package/security/impersonation.ts +117 -12
  468. package/security/jsLoader.ts +81 -18
  469. package/security/keys.ts +298 -72
  470. package/security/operationScope.ts +33 -0
  471. package/security/permissionsTranslator.js +23 -0
  472. package/security/tokenAuthentication.ts +233 -12
  473. package/security/user.ts +4 -3
  474. package/server/DESIGN.md +183 -16
  475. package/server/DurableSubscriptionsSession.ts +71 -11
  476. package/server/REST.ts +79 -1
  477. package/server/graphqlQuerying.ts +4 -0
  478. package/server/http.ts +99 -18
  479. package/server/itc/serverHandlers.js +8 -1
  480. package/server/jobs/jobProcess.ts +8 -2
  481. package/server/jobs/jobs.ts +4 -1
  482. package/server/liveSubscriptionAuth.ts +129 -46
  483. package/server/loadRootComponents.js +50 -8
  484. package/server/mqtt.ts +179 -38
  485. package/server/nodeName.ts +103 -21
  486. package/server/serverHelpers/Headers.ts +131 -0
  487. package/server/serverHelpers/contentTypes.ts +29 -21
  488. package/server/serverHelpers/deployValidationState.ts +24 -13
  489. package/server/serverHelpers/operationAuthorizationState.ts +34 -3
  490. package/server/serverHelpers/registeredOperations.ts +79 -22
  491. package/server/serverHelpers/requestSanitization.ts +15 -0
  492. package/server/serverHelpers/serverHandlers.js +6 -3
  493. package/server/serverHelpers/serverUtilities.ts +104 -31
  494. package/server/serverHelpers/sharedMessageEncoding.ts +307 -0
  495. package/server/serverHelpers/uwsServer.ts +17 -2
  496. package/server/static.ts +23 -29
  497. package/server/storageReclamation.ts +13 -0
  498. package/server/threads/itc.js +11 -1
  499. package/server/threads/manageThreads.js +526 -63
  500. package/server/threads/socketRouter.ts +81 -26
  501. package/server/threads/threadHeapMemory.ts +26 -0
  502. package/server/threads/threadServer.js +43 -15
  503. package/sqlTranslator/index.ts +31 -8
  504. package/studio/web/assets/{Chat-Br06zdMA.js → Chat-BnCBegQz.js} +1 -1
  505. package/studio/web/assets/{FloatingChat-BWImX5fA.js → FloatingChat-CoDW1ySS.js} +3 -3
  506. package/studio/web/assets/{apiToken-DN0nmDsq.js → apiToken-Bwk5BLXW.js} +1 -1
  507. package/studio/web/assets/{applications-kSxVoyeU.js → applications-DHxGi7JH.js} +1 -1
  508. package/studio/web/assets/{cssMode-C1JeufH5.js → cssMode-s0cWI-_M.js} +1 -1
  509. package/studio/web/assets/{editor-qoo9CrGO.js → editor-DNcRHK54.js} +1 -1
  510. package/studio/web/assets/{html-Dt4IIy04.js → html-Bdssedlg.js} +1 -1
  511. package/studio/web/assets/{htmlMode-DXgKKr4C.js → htmlMode-CoDlJ3fw.js} +1 -1
  512. package/studio/web/assets/{index-6onkYFOG.js → index-D6sxmFLR.js} +5 -5
  513. package/studio/web/assets/{index.lazy-BrCFnpNJ.js → index.lazy-tmU5BS8s.js} +1 -1
  514. package/studio/web/assets/{javascript-DNCQGUBc.js → javascript-B8meVSTH.js} +1 -1
  515. package/studio/web/assets/{jsonMode-CR6HWruP.js → jsonMode-DpIPd35T.js} +1 -1
  516. package/studio/web/assets/{languageServices-BM4fI4rS.js → languageServices-C_5FMJzQ.js} +1 -1
  517. package/studio/web/assets/{lspLanguageFeatures-DSa1ttcD.js → lspLanguageFeatures-BIzNBzPK.js} +1 -1
  518. package/studio/web/assets/{notifications-BHXLnh6x.js → notifications-CQf18QKb.js} +1 -1
  519. package/studio/web/assets/{notifications-CUmtIA6z.js → notifications-CvZivSbh.js} +1 -1
  520. package/studio/web/assets/{profile-8BeFSF3j.js → profile-DdOwtntb.js} +1 -1
  521. package/studio/web/assets/{regions-C8qR0HhD.js → regions-n69fwagr.js} +1 -1
  522. package/studio/web/assets/{register-B4n5i0SD.js → register-PfWTCXWB.js} +2 -2
  523. package/studio/web/assets/{setComponentFile-g0_B0lgX.js → setComponentFile-Bg6O7X0S.js} +1 -1
  524. package/studio/web/assets/{setup-B0CTj_Q5.js → setup-CUx_aUDl.js} +2 -2
  525. package/studio/web/assets/{status-C6Yib7-K.js → status-D7BVKqX9.js} +1 -1
  526. package/studio/web/assets/{toggleHighContrast-Dgta7bVi.js → toggleHighContrast-DBSyXzMr.js} +1 -1
  527. package/studio/web/assets/{tsMode-CH_jHvU-.js → tsMode-BByKCjBS.js} +1 -1
  528. package/studio/web/assets/{typescript-Co9LCXd5.js → typescript-DDLnLpw9.js} +1 -1
  529. package/studio/web/assets/{useEntityRestURL-wKC8NsC_.js → useEntityRestURL-31CHGaHk.js} +1 -1
  530. package/studio/web/assets/{workers-CWeLxCXA.js → workers-pR3jRY9D.js} +1 -1
  531. package/studio/web/assets/{xml-BadC-0Rk.js → xml-2iRnMhQO.js} +1 -1
  532. package/studio/web/assets/{yaml-BiUfxPbC.js → yaml-Bf92gJpd.js} +1 -1
  533. package/studio/web/index.html +1 -1
  534. package/upgrade/directives/5-3-0.ts +132 -0
  535. package/upgrade/directives/directivesController.ts +2 -1
  536. package/utility/OperationFunctionCaller.ts +2 -1
  537. package/utility/common_utils.ts +30 -5
  538. package/utility/componentNames.ts +12 -0
  539. package/utility/environment/environmentManager.ts +3 -7
  540. package/utility/environment/systemInformation.ts +7 -0
  541. package/utility/errors/commonErrors.ts +4 -0
  542. package/utility/errors/hdbError.ts +29 -0
  543. package/utility/hdbTerms.ts +17 -0
  544. package/utility/logging/harper_logger.ts +87 -14
  545. package/utility/logging/logRotator.ts +72 -45
  546. package/utility/nodeIdentity.ts +45 -0
  547. package/utility/npmUtilities.ts +10 -8
  548. package/utility/operationPermissions.ts +18 -1
  549. package/utility/operation_authorization.ts +231 -42
  550. package/utility/watchPath.ts +63 -0
  551. package/utility/watcherFallback.ts +270 -0
  552. package/validation/configValidator.ts +209 -72
  553. package/validation/installValidator.ts +15 -0
  554. package/validation/validationWrapper.ts +18 -4
@@ -100,25 +100,48 @@ let hdbProperties;
100
100
 
101
101
  let rootConfig;
102
102
 
103
- function updateLogger(logger: any, logOptions: any, name?: string) {
104
- logger.rotation = logOptions.rotation;
103
+ // `mainLoggerRef` defaults to the module's private `mainLogger` singleton (the real production
104
+ // behavior) but can be overridden by callers (currently just tests) so the inheritance decision
105
+ // below can be exercised against a throwaway logger without reaching into module-private state.
106
+ export function updateLogger(logger: any, logOptions: any, name?: string, mainLoggerRef: any = mainLogger) {
107
+ // Fall back to the main logger's rotation (like level/path below) so an external/component
108
+ // logger with no rotation block of its own inherits maxSize/interval/etc rather than losing
109
+ // rotation entirely (#1877). Excluded when `logger` IS mainLoggerRef: the fallback would just
110
+ // reassign mainLogger.rotation to itself, making it impossible to ever clear main's rotation.
111
+ const inheritedRotation = logOptions.rotation ?? (logger === mainLoggerRef ? undefined : mainLoggerRef?.rotation);
112
+ if (inheritedRotation && inheritedRotation === mainLoggerRef?.rotation) {
113
+ // This logger has no rotation block of its own and is inheriting main's wholesale — but
114
+ // inheriting `rotation.path` too would point this logger's archives at wherever main
115
+ // archives to. If this logger's file lives on a different filesystem/volume than that
116
+ // directory, the rotator's fs.rename() there fails with EXDEV and the tick error leaks
117
+ // (contained in logRotator.ts) without ever rotating this log. Strip the inherited path so
118
+ // rotation instead defaults beside this logger's own path (logRotator's own <log dir>/rotated
119
+ // fallback); an explicit `rotation.path` in this logger's own config still wins, since that
120
+ // goes through `logOptions.rotation` above, not this fallback. Clone rather than mutate:
121
+ // `inheritedRotation` is the literal object shared by mainLogger.rotation and every other
122
+ // component that inherited it.
123
+ const { path: _inheritedPath, ...rotationWithoutPath } = inheritedRotation;
124
+ logger.rotation = rotationWithoutPath;
125
+ } else {
126
+ logger.rotation = inheritedRotation;
127
+ }
105
128
  let path = logOptions.path;
106
129
  if (path) {
107
130
  if (!logOptions.root) logOptions.root = pathModule.dirname(path);
108
131
  } else if (logOptions.root) {
109
132
  path = join(logOptions.root, logName);
110
133
  } else {
111
- path = mainLogger.path;
134
+ path = mainLoggerRef.path;
112
135
  if (!logOptions.root) logOptions.root = pathModule.dirname(path);
113
136
  }
114
137
  if (path) logger.path = path;
115
138
  else console.error('No path for logger', logOptions);
116
- logger.level = LOG_LEVEL_HIERARCHY[logOptions.level] ?? mainLogger?.level ?? LOG_LEVEL_HIERARCHY.info;
139
+ logger.level = LOG_LEVEL_HIERARCHY[logOptions.level] ?? mainLoggerRef?.level ?? LOG_LEVEL_HIERARCHY.info;
117
140
  updateConditional(logger);
118
141
  logger.logToStdstreams = logOptions.stdStreams ?? false;
119
142
  // if there is a configured tag or if a component is logging to default/main log path, use the component name as the tag
120
143
  // to differentiate it
121
- logger.tag = logOptions.tag ?? ((mainLogger.path === logger.path || externalLogger.path === logger.path) && name);
144
+ logger.tag = logOptions.tag ?? ((mainLoggerRef.path === logger.path || externalLogger.path === logger.path) && name);
122
145
  }
123
146
  // creates a logger where the methods are only defined if they are within the log level.
124
147
  // Using this conditional logger means that every method call must be optional like log.trace?.('message),
@@ -145,7 +168,7 @@ function resolveLogPath(configPath: string, rootPath: string) {
145
168
  async function updateLogSettings() {
146
169
  if (!rootConfig) {
147
170
  // set up the initial watcher
148
- rootConfig = new RootConfigWatcher();
171
+ rootConfig = getSharedRootConfigWatcher();
149
172
  // wait for it to be ready
150
173
  await rootConfig.ready;
151
174
  // TODO: Any way to differentiate changes that we can and can't handle?
@@ -383,8 +406,20 @@ module.exports = {
383
406
  disableStdio,
384
407
  isStdioBrokenError,
385
408
  externalLogger,
409
+ updateLogger,
386
410
  };
387
411
 
412
+ // Writes past the stdio guard installed by installStdioGuard, which would otherwise route the
413
+ // text back into the file logger this is the fallback for, and swallows a broken pipe - there is
414
+ // nowhere left to report it.
415
+ function writeToStdioDirectly(stream, text) {
416
+ try {
417
+ nativeStdWrite.call(stream, text);
418
+ } catch {
419
+ // stdio is gone too
420
+ }
421
+ }
422
+
388
423
  // A bare no-op would read as permanent backpressure to a pipe()'d source; this drains and
389
424
  // discards instead.
390
425
  function noopWrite(_chunk?: any, encoding?: any, callback?: any) {
@@ -510,10 +545,17 @@ export function initLogSettings(forceInit = false) {
510
545
 
511
546
  logLevel = logLevel === undefined ? defaultLevel : logLevel;
512
547
 
513
- mainLogger = createLogger({ level: logLevel });
548
+ // createLogger shadows the module-level `logToStdstreams` with this option, so omitting it
549
+ // drops every log written before a config exists rather than routing it to the streams.
550
+ mainLogger = createLogger({ level: logLevel, stdStreams: logToStdstreams });
514
551
  // setup the external logger
515
552
  externalLogger = mainLogger.forComponent('external');
516
553
  externalLogger.tag = null; // don't tag by default
554
+ // The streams are this branch's only sink, so it needs the same EPIPE/EIO listeners the
555
+ // configured path installs below: `harper install | head -1` closes the reader, and the
556
+ // async error would otherwise land on a stream with none and take the install down. The
557
+ // guard's write override is inert here, because `log_to_file` is false.
558
+ stdioLogging();
517
559
  return;
518
560
  }
519
561
 
@@ -727,6 +769,8 @@ export function createLogger(options: any = {} as any) {
727
769
  return logger;
728
770
  }
729
771
  const LOG_TIME_USAGE_THRESHOLD = 100;
772
+ // How long to write straight to stdio after the log file refuses an append.
773
+ const APPEND_RETRY_COOLDOWN = 5000;
730
774
  /**
731
775
  * Get the file logger for the given path. If it doesn't exist, create it.
732
776
  * @param path
@@ -735,7 +779,7 @@ const LOG_TIME_USAGE_THRESHOLD = 100;
735
779
  */
736
780
  function getFileLogger(path, rotation, isExternalInstance) {
737
781
  let logger = fileLoggers.get(path);
738
- let logFD, loggedFDError, logTimer;
782
+ let logFD, loggedFDError, loggedAppendError, logTimer, retryAppendAfter;
739
783
  let logBuffer;
740
784
  let logTimeUsage = 0;
741
785
  if (!logger) {
@@ -788,14 +832,37 @@ function getFileLogger(path, rotation, isExternalInstance) {
788
832
  // this is called on a timer, and will write the log buffer to the file
789
833
  function logQueuedData(entry?: any) {
790
834
  openLogFile(undefined);
791
- if (logFD) {
835
+ const payload = logBuffer ? logBuffer.join('') : entry;
836
+ // A file that just refused a write will refuse the next one too, and every attempt costs a
837
+ // failed syscall plus a thrown error on whatever path is logging - which, on a full volume,
838
+ // is the request path at full rate. Go straight to stdio until the cooldown expires.
839
+ if (logFD && !(retryAppendAfter > performance.now())) {
792
840
  let startTime = performance.now();
793
- fs.appendFileSync(logFD, logBuffer ? logBuffer.join('') : entry);
841
+ try {
842
+ fs.appendFileSync(logFD, payload);
843
+ // Both cleared, so a volume that fills again months later reports itself again
844
+ retryAppendAfter = undefined;
845
+ loggedAppendError = false;
846
+ } catch (error) {
847
+ retryAppendAfter = performance.now() + APPEND_RETRY_COOLDOWN;
848
+ // A log write must never take the process down: on an exhausted volume this throws from
849
+ // both inline and timer call sites, making every log statement a crash point (#847).
850
+ // The fallback goes through nativeStdWrite rather than console because
851
+ // installStdioGuard routes console output back into this same file logger when
852
+ // logging.file and logging.console are both on, which would recurse until the stack blew.
853
+ if (!loggedAppendError) {
854
+ loggedAppendError = true;
855
+ writeToStdioDirectly(process.stderr, `Harper cannot write to its log file: ${error}\n`);
856
+ }
857
+ writeToStdioDirectly(process.stdout, payload);
858
+ logBuffer = null;
859
+ return;
860
+ }
794
861
  let endTime = performance.now();
795
862
  // determine if we are using more than about two percent of processing time for log writes recently, and if so, we
796
863
  // will start buffering
797
864
  logTimeUsage = Math.max(endTime, logTimeUsage) + (endTime - startTime) * 50;
798
- } else if (!loggedFDError) console.log(logBuffer ? logBuffer.join('') : entry);
865
+ } else writeToStdioDirectly(process.stdout, payload);
799
866
  if (logBuffer) logBuffer = null;
800
867
  }
801
868
 
@@ -815,8 +882,13 @@ function getFileLogger(path, rotation, isExternalInstance) {
815
882
  } catch (error) {
816
883
  if (error.code === 'ENOENT' && !isRetry) {
817
884
  // if the directory doesn't exist, create it
818
- fs.mkdirpSync(pathModule.dirname(path));
819
- return openLogFile(true);
885
+ try {
886
+ fs.mkdirpSync(pathModule.dirname(path));
887
+ return openLogFile(true);
888
+ } catch (mkdirError) {
889
+ // creating the log directory can fail for the same reason the log write can
890
+ error = mkdirError;
891
+ }
820
892
  }
821
893
  if (!loggedFDError) {
822
894
  loggedFDError = true;
@@ -1811,7 +1883,7 @@ export function AuthAuditLog(
1811
1883
  this.path = path;
1812
1884
  }
1813
1885
  // we have to load this at the end to avoid circular dependencies problems
1814
- import { RootConfigWatcher } from '../../config/RootConfigWatcher.ts';
1886
+ import { getSharedRootConfigWatcher } from '../../config/RootConfigWatcher.ts';
1815
1887
 
1816
1888
  export const getLogFilePath = () => logFilePath;
1817
1889
  export const forComponent = (name: string, isExternal?: boolean) => mainLogger.forComponent(name, isExternal);
@@ -1846,4 +1918,5 @@ export default {
1846
1918
  errorForLog,
1847
1919
  inspectForLog,
1848
1920
  isErrorLike,
1921
+ updateLogger,
1849
1922
  };
@@ -6,6 +6,7 @@ import { promisify } from 'util';
6
6
  import { pipeline } from 'stream';
7
7
  const pipe = promisify(pipeline);
8
8
  import * as path from 'path';
9
+ import { createHash } from 'crypto';
9
10
  import * as envMgr from '../environment/environmentManager.ts';
10
11
  envMgr.initSync();
11
12
  import hdbLogger from './harper_logger.ts';
@@ -67,62 +68,71 @@ function logRotator({ logger, maxSize, interval, retention, enabled, path: rotat
67
68
  let lastRotationTime = Date.now();
68
69
  hdbLogger.trace('Log rotate enabled, maxSize:', maxSize, 'interval:', interval);
69
70
  const setIntervalId = setInterval(async () => {
70
- // A missing/relocated active log file only invalidates the rotation checks below — retention cleanup
71
- // must still run. So skip the individual check on ENOENT rather than returning from the whole tick.
72
- if (maxBytes) {
73
- let fileStats;
74
- try {
75
- fileStats = await fsProm.stat(logger.path);
76
- } catch (err) {
77
- // If the log file doesn't exist, skip the size-based rotation check
78
- if (err.code !== 'ENOENT') throw err;
79
- }
80
-
81
- if (fileStats && fileStats.size >= maxBytes) {
71
+ // The tick is async but setInterval doesn't await it, so any error that escapes this callback
72
+ // becomes an unhandled rejection rather than surfacing anywhere useful — and since it isn't
73
+ // caught, it also skips the retention cleanup below. Contain everything here and report via
74
+ // the logger instead, so one bad tick (e.g. an unexpected fs error) never kills rotation for
75
+ // the rest of the process's life.
76
+ try {
77
+ // A missing/relocated active log file only invalidates the rotation checks below — retention cleanup
78
+ // must still run. So skip the individual check on ENOENT rather than returning from the whole tick.
79
+ if (maxBytes) {
80
+ let fileStats;
82
81
  try {
83
- lastRotatedLogPath = await moveLogFile(logger.path, rotatedLogDir, logger);
82
+ fileStats = await fsProm.stat(logger.path);
84
83
  } catch (err) {
85
- // If the log file doesn't exist, skip rotation
84
+ // If the log file doesn't exist, skip the size-based rotation check
86
85
  if (err.code !== 'ENOENT') throw err;
87
86
  }
88
- }
89
- }
90
87
 
91
- if (maxInterval) {
92
- const minSinceLastRotate = Date.now() - lastRotationTime;
93
- if (minSinceLastRotate >= maxInterval) {
94
- try {
95
- lastRotatedLogPath = await moveLogFile(logger.path, rotatedLogDir, logger);
96
- lastRotationTime = Date.now();
97
- } catch (err) {
98
- // If the log file doesn't exist, skip rotation
99
- if (err.code !== 'ENOENT') throw err;
88
+ if (fileStats && fileStats.size >= maxBytes) {
89
+ try {
90
+ lastRotatedLogPath = await moveLogFile(logger.path, rotatedLogDir, logger);
91
+ } catch (err) {
92
+ // If the log file doesn't exist, skip rotation
93
+ if (err.code !== 'ENOENT') throw err;
94
+ }
100
95
  }
101
96
  }
102
- }
103
- if (retention || reclamationPriority) {
104
- // remove old logs after retention time
105
- // adjust retention time if there is a reclamation priority in place
106
- const retentionMs = convertToMS(retention ?? '1M') / (1 + reclamationPriority);
107
- reclamationPriority = 0; // reset it after use
108
- let files;
109
- try {
110
- files = await fsProm.readdir(rotatedLogDir);
111
- } catch (err) {
112
- // The rotated log dir may not exist yet (nothing rotated so far); nothing to clean up
113
- if (err.code !== 'ENOENT') hdbLogger.error('Error reading rotated log directory', rotatedLogDir, err);
114
- files = [];
97
+
98
+ if (maxInterval) {
99
+ const minSinceLastRotate = Date.now() - lastRotationTime;
100
+ if (minSinceLastRotate >= maxInterval) {
101
+ try {
102
+ lastRotatedLogPath = await moveLogFile(logger.path, rotatedLogDir, logger);
103
+ lastRotationTime = Date.now();
104
+ } catch (err) {
105
+ // If the log file doesn't exist, skip rotation
106
+ if (err.code !== 'ENOENT') throw err;
107
+ }
108
+ }
115
109
  }
116
- for (const file of files) {
110
+ if (retention || reclamationPriority) {
111
+ // remove old logs after retention time
112
+ // adjust retention time if there is a reclamation priority in place
113
+ const retentionMs = convertToMS(retention ?? '1M') / (1 + reclamationPriority);
114
+ reclamationPriority = 0; // reset it after use
115
+ let files;
117
116
  try {
118
- const fileStats = await fsProm.stat(path.join(rotatedLogDir, file));
119
- if (Date.now() - fileStats.mtimeMs > retentionMs) {
120
- await fsProm.unlink(path.join(rotatedLogDir, file));
121
- }
117
+ files = await fsProm.readdir(rotatedLogDir);
122
118
  } catch (err) {
123
- hdbLogger.error('Error trying to remove log', file, err);
119
+ // The rotated log dir may not exist yet (nothing rotated so far); nothing to clean up
120
+ if (err.code !== 'ENOENT') hdbLogger.error('Error reading rotated log directory', rotatedLogDir, err);
121
+ files = [];
122
+ }
123
+ for (const file of files) {
124
+ try {
125
+ const fileStats = await fsProm.stat(path.join(rotatedLogDir, file));
126
+ if (Date.now() - fileStats.mtimeMs > retentionMs) {
127
+ await fsProm.unlink(path.join(rotatedLogDir, file));
128
+ }
129
+ } catch (err) {
130
+ hdbLogger.error('Error trying to remove log', file, err);
131
+ }
124
132
  }
125
133
  }
134
+ } catch (err) {
135
+ hdbLogger.error('Error during log rotation audit tick for', logger.path, err);
126
136
  }
127
137
  }, auditInterval ?? LOG_AUDIT_INTERVAL).unref();
128
138
  return {
@@ -135,11 +145,28 @@ function logRotator({ logger, maxSize, interval, retention, enabled, path: rotat
135
145
  };
136
146
  }
137
147
 
148
+ // Monotonically increasing across every rotation in this process, regardless of which logger/source
149
+ // triggered it — combined with the pid, this guarantees two archive names can never collide even if
150
+ // two rotations for two different sources race concurrently within the same audit-interval tick.
151
+ let rotationSequence = 0;
152
+
138
153
  async function moveLogFile(logPath: string, rotatedLogPath: string, logger?: any) {
139
154
  const compress = envMgr.get(CONFIG_PARAMS.LOGGING_ROTATION_COMPRESS);
155
+ // Name the archive after its source log (hdb, external, a component name, ...), not a fixed
156
+ // "HDB" literal — external/component loggers can now inherit rotation from the main logger
157
+ // (#1877) and default to the same rotated directory as it, so distinct sources rotating in
158
+ // the same audit tick must not collide on the same timestamp-only filename. A basename alone
159
+ // is not enough either: two distinct source paths can share a basename (e.g. `/logs/a/hdb.log`
160
+ // and `/logs/b/hdb.log`), so a hash of the full resolved source path plus a pid+sequence suffix
161
+ // give every archive a name POSIX rename() can never clobber, even under a same-millisecond race.
162
+ const sourceName = path.basename(logPath, path.extname(logPath)) || 'HDB';
163
+ // sha256, not sha1: this only needs a stable identifier, not cryptographic strength, but a FIPS-mode
164
+ // OpenSSL provider disables sha1 and throws synchronously, which would crash every rotation tick.
165
+ const sourceId = createHash('sha256').update(path.resolve(logPath)).digest('hex').slice(0, 8);
166
+ const uniqueSuffix = `${process.pid}-${rotationSequence++}`;
140
167
  let fullRotateLogPath = path.join(
141
168
  rotatedLogPath,
142
- `HDB-${new Date(Date.now()).toISOString().replaceAll(':', '-')}.log`
169
+ `${sourceName}-${sourceId}-${new Date(Date.now()).toISOString().replaceAll(':', '-')}-${uniqueSuffix}.log`
143
170
  );
144
171
  // Move log file to rotated log path first (if we crash
145
172
  // during compression, we don't want to restart the compression with a new file)
@@ -0,0 +1,45 @@
1
+ import { isIP } from 'node:net';
2
+
3
+ /**
4
+ * A node's identity — node.hostname, and the replication.hostname / certificate it falls back to —
5
+ * must be a bare hostname or IP literal, not a URL: it becomes the certificate common name and the
6
+ * host replication advertises and dials, so a scheme/port/path/non-string corrupts both (harper#2218,
7
+ * where "ws://http://host:9926:9925" resolves to host "http"). Returns a reason clause when `value`
8
+ * is not a bare host, else undefined. An empty string is "unset" (a caller's cue to fall back), not a
9
+ * violation.
10
+ */
11
+ export function bareHostViolation(value: unknown): string | undefined {
12
+ if (typeof value !== 'string') return `must be a string, but is a ${value === null ? 'null' : typeof value}`;
13
+ if (value === '') return undefined;
14
+ // The identity is stored unbracketed (bracketing belongs to URL construction). Reject a bracketed
15
+ // form so it is never cached — otherwise net.isIP fails on it and the certificate SAN is mistyped
16
+ // as DNS rather than IP, and the same node's identity string would differ by source.
17
+ if (value.includes('[') || value.includes(']'))
18
+ return 'must be an unbracketed IPv6 literal (e.g. "::1", not "[::1]")';
19
+ // A zone id ("fe80::1%eth0") passes net.isIP but has no valid URL authority, so exclude it here.
20
+ if (isIP(value) && !value.includes('%')) return undefined; // a bare IPv4/IPv6 literal is a valid identity
21
+ if (value.includes('://')) return 'must not include a URL scheme';
22
+ let url;
23
+ try {
24
+ // Parse under a special scheme so the host grammar matches the ws:// replication URLs that
25
+ // consume this value — a host this accepts is one the consumer accepts (a non-special scheme is
26
+ // more lenient and would pass e.g. "node%20" or "0x7f.1"). A port or path makes url.hostname
27
+ // differ from the input and is caught by the round-trip check below.
28
+ url = new URL(`https://${value}`);
29
+ } catch {
30
+ return 'is not a valid hostname';
31
+ }
32
+ // Report the port before the round-trip check: the parser strips a default port for the scheme it
33
+ // was given (":443" under https), which would otherwise surface as a vaguer "is not a bare hostname".
34
+ if (url.port || (url.hostname && value.slice(url.hostname.length).startsWith(':'))) {
35
+ return 'must not include a port';
36
+ }
37
+ if (url.username || url.password) return 'must not include credentials';
38
+ if (url.search) return 'must not include a query string';
39
+ if (url.hash) return 'must not include a fragment';
40
+ if (url.pathname && url.pathname !== '/') return 'must not include a path';
41
+ // The host must survive parsing unchanged (compared case-insensitively, since URL lowercases it);
42
+ // anything that does not round-trip carried extra syntax and is not a bare host.
43
+ if (url.hostname.toLowerCase() !== value.toLowerCase()) return 'is not a bare hostname';
44
+ return undefined;
45
+ }
@@ -12,7 +12,7 @@ import harperLogger from './logging/harper_logger.ts';
12
12
 
13
13
  import { CONFIG_PARAMS } from './hdbTerms.ts';
14
14
  import { getConfigPath } from '../config/configUtils.ts';
15
- import { nonInteractiveSpawn } from '../components/Application.ts';
15
+ import { nonInteractiveSpawn, packageManagerInstallArguments } from '../components/Application.ts';
16
16
  import { withComponentPreparationLock } from '../components/componentPreparationLock.ts';
17
17
  import { isThreadRunning } from '../server/threads/manageThreads.js';
18
18
 
@@ -26,18 +26,19 @@ export async function installModules(req: any) {
26
26
  'install_node_modules is deprecated. Dependencies are automatically installed on' +
27
27
  ' deploy, and install_node_modules can lead to inconsistent behavior';
28
28
  harperLogger.warn(deprecationWarning, req.projects);
29
- const validation = modulesValidator(req);
29
+ const { error: validation, value: validatedRequest } = modulesValidator(req);
30
30
  if (validation) {
31
31
  throw handleHDBError(validation, validation.message, HTTP_STATUS_CODES.BAD_REQUEST);
32
32
  }
33
33
 
34
- let { projects, dryRun } = req;
34
+ const { projects, dry_run: dryRun } = validatedRequest;
35
35
 
36
36
  const componentsRootDirPath = getConfigPath(CONFIG_PARAMS.COMPONENTSROOT);
37
37
 
38
38
  const responseObject: any = {};
39
39
 
40
- const args = ['install', '--force', '--omit=dev', '--json'];
40
+ // `allowInstallScripts` is true because this operation has always run a project's install lifecycle
41
+ const args = [...packageManagerInstallArguments('npm', true, true), '--json'];
41
42
  if (dryRun) args.push('--dry-run');
42
43
 
43
44
  for (const project of projects) {
@@ -91,15 +92,16 @@ function parseNPMStdErr(stderr: string) {
91
92
  }
92
93
 
93
94
  /**
94
- * Validator for both installModules & auditModules
95
+ * Validator for installModules
95
96
  * @param {Object} req
96
- * @returns {*}
97
97
  */
98
98
  function modulesValidator(req: any) {
99
+ // `dryRun` was the only spelling that worked before dry_run was honored; keep it accepted, but
100
+ // reject a request that carries both rather than picking a winner
99
101
  const funcSchema = Joi.object({
100
102
  projects: Joi.array().min(1).items(Joi.string()).required(),
101
103
  dry_run: Joi.boolean().default(false),
102
- });
104
+ }).rename('dryRun', 'dry_run', { ignoreUndefined: true });
103
105
 
104
- return validator.validateBySchema(req, funcSchema);
106
+ return validator.validateAndConvertBySchema(req, funcSchema);
105
107
  }
@@ -69,6 +69,7 @@ export const OPERATION_PERMISSION_GROUPS = {
69
69
  OPERATIONS_ENUM.INSERT,
70
70
  OPERATIONS_ENUM.UPDATE,
71
71
  OPERATIONS_ENUM.UPSERT,
72
+ OPERATIONS_ENUM.PUT,
72
73
  OPERATIONS_ENUM.DELETE,
73
74
  // Bulk load
74
75
  OPERATIONS_ENUM.CSV_DATA_LOAD,
@@ -97,6 +98,11 @@ const validGroups: Set<string> = new Set(Object.keys(OPERATION_PERMISSION_GROUPS
97
98
  // permission) whose names may fall outside OPERATIONS_ENUM. Tracked so they're grantable in a
98
99
  // role's `operations` allowlist (add_role/alter_role/impersonation validate against this set too).
99
100
  const dynamicallyRegisteredOps: Set<string> = new Set();
101
+ // The same, for ops registered on a WORKER and mirrored here by the OPERATION_REGISTERED bridge.
102
+ // Deliberately a separate set: the two threads can register the same name independently (a hot
103
+ // deploy can add a `startOnMainThread` component while the worker offering that name is retiring),
104
+ // so worker-lifecycle cleanup must not be able to revoke a mark this thread made itself.
105
+ const workerRegisteredOps: Set<string> = new Set();
100
106
 
101
107
  /**
102
108
  * Mark a dynamically-registered operation name as a valid target for role `operations` grants.
@@ -115,13 +121,24 @@ export function unregisterGrantableOperation(name: string): void {
115
121
  dynamicallyRegisteredOps.delete(name);
116
122
  }
117
123
 
124
+ export function registerWorkerGrantableOperation(name: string): void {
125
+ workerRegisteredOps.add(name);
126
+ }
127
+
128
+ export function unregisterWorkerGrantableOperation(name: string): void {
129
+ workerRegisteredOps.delete(name);
130
+ }
131
+
118
132
  /**
119
133
  * Validates that every entry in an operations array is a known operation name or group name.
120
134
  * Returns the first invalid entry, or null if all entries are valid.
121
135
  */
122
136
  export function validateOperations(operations: readonly unknown[]): string | null {
123
137
  for (const op of operations) {
124
- if (typeof op !== 'string' || (!validOps.has(op) && !validGroups.has(op) && !dynamicallyRegisteredOps.has(op))) {
138
+ if (
139
+ typeof op !== 'string' ||
140
+ (!validOps.has(op) && !validGroups.has(op) && !dynamicallyRegisteredOps.has(op) && !workerRegisteredOps.has(op))
141
+ ) {
125
142
  return String(op);
126
143
  }
127
144
  }