@harperfast/harper 5.2.9 → 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 (668) 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 -0
  150. package/dist/resources/DatabaseTransaction.js +459 -45
  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 +29 -0
  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 -9
  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 +1073 -191
  174. package/dist/resources/Table.js.map +1 -1
  175. package/dist/resources/auditStore.d.ts +11 -2
  176. package/dist/resources/auditStore.js +325 -71
  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 -0
  187. package/dist/resources/databases.js +1200 -239
  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 -6
  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 +12 -0
  341. package/dist/server/storageReclamation.js +26 -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 -3
  347. package/dist/server/threads/manageThreads.js +517 -65
  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 +196 -194
  423. package/package.json +7 -6
  424. package/resources/DESIGN.md +114 -52
  425. package/resources/DatabaseTransaction.ts +521 -43
  426. package/resources/LMDBTransaction.ts +26 -4
  427. package/resources/PrimaryRocksDatabase.ts +28 -1
  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 -9
  433. package/resources/RocksTransactionLogStore.ts +78 -21
  434. package/resources/Table.ts +1110 -159
  435. package/resources/auditStore.ts +331 -73
  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 +1310 -252
  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 -7
  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 +23 -0
  498. package/server/threads/itc.js +11 -1
  499. package/server/threads/manageThreads.js +526 -56
  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-BnCBegQz.js +2267 -0
  505. package/studio/web/assets/FloatingChat-CoDW1ySS.js +23 -0
  506. package/studio/web/assets/{abnfDiagram-VCTEODGH-C0_BAZyO.js → abnfDiagram-VCTEODGH-B0BebmD2.js} +1 -1
  507. package/studio/web/assets/{alertDialog-DIHt7Z0r.js → alertDialog-CQyAJJhl.js} +1 -1
  508. package/studio/web/assets/{apiToken-c3Rd-w6g.js → apiToken-Bwk5BLXW.js} +1 -1
  509. package/studio/web/assets/applications-DHxGi7JH.js +296 -0
  510. package/studio/web/assets/architecture-7GRP2DOG-LB-MLAAb.js +1 -0
  511. package/studio/web/assets/{architectureDiagram-5GKGNRK7-BWzrASgm.js → architectureDiagram-5GKGNRK7-7SW3GD-K.js} +1 -1
  512. package/studio/web/assets/authStore-C3Nfubqr.js +3 -0
  513. package/studio/web/assets/{blockDiagram-NRAW4CY4-BdJX9Khj.js → blockDiagram-I7D4REHJ-BqguiadH.js} +2 -2
  514. package/studio/web/assets/{button-DhiX-njv.js → button-BIsUKRZq.js} +2 -2
  515. package/studio/web/assets/{c4Diagram-UCG6FXSJ-CI6MzGmQ.js → c4Diagram-7LVT6UL2-LBNf8t_X.js} +1 -1
  516. package/studio/web/assets/channel-yictG-U-.js +1 -0
  517. package/studio/web/assets/{chevron-up-Df2c8uoU.js → chevron-up-DtKGqDn3.js} +1 -1
  518. package/studio/web/assets/{chunk-TEH6E4GO-P87k5mNi.js → chunk-4HAMMTFA-DWtTut21.js} +1 -1
  519. package/studio/web/assets/{chunk-75Z2AOVW-BT8tVmks.js → chunk-75Z2AOVW-QGQD6th2.js} +1 -1
  520. package/studio/web/assets/{chunk-DU6HZSFF-9kAOOmI6.js → chunk-DU6HZSFF-Chq20Ba5.js} +1 -1
  521. package/studio/web/assets/{chunk-F27PBJKO-BW7ao8AY.js → chunk-F27PBJKO-BVA5EPhV.js} +1 -1
  522. package/studio/web/assets/{chunk-GMAD6QVW-BNyXpoQO.js → chunk-GMAD6QVW-BeS7S07A.js} +1 -1
  523. package/studio/web/assets/{chunk-OBVCFTLP-D4wWOqDQ.js → chunk-GVQU2GXP-sbwVIQ8i.js} +1 -1
  524. package/studio/web/assets/{chunk-G27WJ6UU-COyLMcgK.js → chunk-IMKFNOWR-Bnh3tAVd.js} +1 -1
  525. package/studio/web/assets/{chunk-JQ64N6SF-Cyz1IeLf.js → chunk-L3NEJ4N5-COfUyKII.js} +1 -1
  526. package/studio/web/assets/chunk-OSK3NFVY-ByciRftO.js +10 -0
  527. package/studio/web/assets/{chunk-P2QGCYS3-DmIFY4d7.js → chunk-P2QGCYS3-CP1VhG_c.js} +1 -1
  528. package/studio/web/assets/{chunk-POPQ4Y6H-BPrvMyKz.js → chunk-POPQ4Y6H-ClWhhkwW.js} +1 -1
  529. package/studio/web/assets/{chunk-PWAF6VOD-2zB6IW9i.js → chunk-PWAF6VOD-1z1THyS5.js} +1 -1
  530. package/studio/web/assets/{chunk-RHFEMEQ7-2FgyI8YU.js → chunk-SHT3W25Y-LpQkMsah.js} +2 -2
  531. package/studio/web/assets/{chunk-SVP7TREG-FwtbH2QC.js → chunk-SVP7TREG-jtdAHw0S.js} +1 -1
  532. package/studio/web/assets/{chunk-LCL6LL3I-HOzK_ppE.js → chunk-TICWLB2K-VOwzetX-.js} +1 -1
  533. package/studio/web/assets/classDiagram-ZZMXUADV-VaEwSy_g.js +1 -0
  534. package/studio/web/assets/classDiagram-v2-VYDZK3BY-VaEwSy_g.js +1 -0
  535. package/studio/web/assets/{createLucideIcon-BKGPfjm2.js → createLucideIcon-CzW9508A.js} +1 -1
  536. package/studio/web/assets/{cssMode-CEN2mzSA.js → cssMode-s0cWI-_M.js} +1 -1
  537. package/studio/web/assets/{cynefin-OW5HDTMX-BRkpLFQV.js → cynefin-OW5HDTMX-BbdbCvub.js} +1 -1
  538. package/studio/web/assets/{cynefinDiagram-5FMLGOSQ-CHT1DaX6.js → cynefinDiagram-5FMLGOSQ-TP-aIqbt.js} +1 -1
  539. package/studio/web/assets/{dagre-3AP2YEHR-DpUXBh63.js → dagre-GXQ25YYZ-DShnGpGo.js} +1 -1
  540. package/studio/web/assets/{diagram-S7CK7UJ4-BuymVFZT.js → diagram-S7CK7UJ4-aoCVTtcy.js} +1 -1
  541. package/studio/web/assets/{diagram-UQ7AKVKN-CyP148RM.js → diagram-UQ7AKVKN-DglXtQ6x.js} +1 -1
  542. package/studio/web/assets/{diagram-VSXAHHWV-CoCAg3M9.js → diagram-VSXAHHWV-fhEdmkwM.js} +1 -1
  543. package/studio/web/assets/{diagram-VX7I27RA-BpOqCFca.js → diagram-VX7I27RA-DccVJet6.js} +1 -1
  544. package/studio/web/assets/{diagram-Z3DM3KII-Bfpw7Vbj.js → diagram-Z3DM3KII-D-RyJJb7.js} +1 -1
  545. package/studio/web/assets/{dialog-CBf0Mr1d.js → dialog-Cn2uWgD4.js} +1 -1
  546. package/studio/web/assets/{dist-lkA3O3eM.js → dist-DP8UjMB_.js} +1 -1
  547. package/studio/web/assets/{download-BtTOBem-.js → download-B5T5r7ss.js} +1 -1
  548. package/studio/web/assets/{ebnfDiagram-PWID7BFC-DS_6aWqL.js → ebnfDiagram-PWID7BFC-DJGpIpz_.js} +1 -1
  549. package/studio/web/assets/{editor-D8oDeCTL.js → editor-DNcRHK54.js} +1 -1
  550. package/studio/web/assets/{erDiagram-SSCWMZ5O-DJNk6Fgw.js → erDiagram-RLTQ6QDP-CIfNlgkC.js} +1 -1
  551. package/studio/web/assets/eventmodeling-NTZA5JFV-CLxnp2CR.js +1 -0
  552. package/studio/web/assets/flowDiagram-HODETNUW-BIbhmz9f.js +1 -0
  553. package/studio/web/assets/{ganttDiagram-EL5Y4UJY-2pOExxMY.js → ganttDiagram-EL5Y4UJY-BxToTzzD.js} +1 -1
  554. package/studio/web/assets/{getAnalytics-D4LKGeVy.js → getAnalytics-GHK8ORfM.js} +1 -1
  555. package/studio/web/assets/{gitGraph-4MIJSDKK-CH5ZxwzF.js → gitGraph-4MIJSDKK-D2s2w8lE.js} +1 -1
  556. package/studio/web/assets/{gitGraphDiagram-WWUBYQGX-DVIsIhbO.js → gitGraphDiagram-WWUBYQGX-Dwntd4-x.js} +1 -1
  557. package/studio/web/assets/{html-u3vOg7LJ.js → html-Bdssedlg.js} +1 -1
  558. package/studio/web/assets/{htmlMode-DyO31v-P.js → htmlMode-CoDlJ3fw.js} +1 -1
  559. package/studio/web/assets/{index-Cxj2_wsl.css → index-7RMEgVG1.css} +1 -1
  560. package/studio/web/assets/index-D6sxmFLR.js +824 -0
  561. package/studio/web/assets/index.lazy-tmU5BS8s.js +2 -0
  562. package/studio/web/assets/{info-A6RAGUB7-CPQfTnaG.js → info-A6RAGUB7-DYjkvb0C.js} +1 -1
  563. package/studio/web/assets/{infoDiagram-RXCK75RN-DlwLYlwm.js → infoDiagram-27XIBGKW-Bnp1FJE5.js} +1 -1
  564. package/studio/web/assets/{ishikawaDiagram-5VMMS53U-BRXRp29U.js → ishikawaDiagram-5VMMS53U-D9Xh2r6X.js} +1 -1
  565. package/studio/web/assets/{javascript-CUvxOyTC.js → javascript-B8meVSTH.js} +1 -1
  566. package/studio/web/assets/{journeyDiagram-EYS64GPL-B0ou8k0n.js → journeyDiagram-3NMN7TZE-CokIi6ll.js} +2 -2
  567. package/studio/web/assets/{jsonMode-f_IwbF3D.js → jsonMode-DpIPd35T.js} +1 -1
  568. package/studio/web/assets/{kanban-definition-3QL26DDD-uYg7iYzp.js → kanban-definition-UXKFOSKX-CukSFJfX.js} +1 -1
  569. package/studio/web/assets/{languageServices-DXtZ6rEF.js → languageServices-C_5FMJzQ.js} +1 -1
  570. package/studio/web/assets/{lspLanguageFeatures-B4pCF1zO.js → lspLanguageFeatures-BIzNBzPK.js} +1 -1
  571. package/studio/web/assets/{mermaid-parser.core-Ck-fC8b7.js → mermaid-parser.core-BlEsOWNO.js} +3 -3
  572. package/studio/web/assets/{mermaid.core-CP8aNNYm.js → mermaid.core-BlkGaMIH.js} +5 -5
  573. package/studio/web/assets/{mindmap-definition-FBJOCRG2-CgTZ-rit.js → mindmap-definition-YA3MSWOX-IprMc_0j.js} +1 -1
  574. package/studio/web/assets/{notifications-D3tIQ4sg.js → notifications-CQf18QKb.js} +1 -1
  575. package/studio/web/assets/notifications-CvZivSbh.js +1 -0
  576. package/studio/web/assets/{packet-AYTQ26CC-DEyoPtPb.js → packet-AYTQ26CC-Bi3V04Zi.js} +1 -1
  577. package/studio/web/assets/{pegDiagram-XKGWAZYB-DrD-7sD9.js → pegDiagram-XKGWAZYB-BNuPDLZY.js} +1 -1
  578. package/studio/web/assets/{pie-WAS4IAKB-wjj-EI1d.js → pie-WAS4IAKB-_6DoDbng.js} +1 -1
  579. package/studio/web/assets/{pieDiagram-E7YTZNPT-GntqDCzv.js → pieDiagram-E7YTZNPT-DqNb6Ht2.js} +1 -1
  580. package/studio/web/assets/{profile-DZWU7MgT.js → profile-DdOwtntb.js} +1 -1
  581. package/studio/web/assets/{quadrantDiagram-AXDQQJYC-0UeqXQGd.js → quadrantDiagram-AXDQQJYC-BGH9E2YR.js} +1 -1
  582. package/studio/web/assets/{radar-RG4KPBEZ-DFSA5h7k.js → radar-RG4KPBEZ-DDdVczcL.js} +1 -1
  583. package/studio/web/assets/{railroad-74A4TZTK-CaOUG9wR.js → railroad-74A4TZTK-BJUP4Jds.js} +1 -1
  584. package/studio/web/assets/railroad-abnf-HS5TGJTU-Bm3L1L0h.js +1 -0
  585. package/studio/web/assets/railroad-ebnf-LZEXJU2U-CKzLGlkw.js +1 -0
  586. package/studio/web/assets/railroad-peg-WCYAUIDC-S8xLjslx.js +1 -0
  587. package/studio/web/assets/{railroadDiagram-O6MQD6OU-yHUELZaV.js → railroadDiagram-O6MQD6OU-DGTPh2KZ.js} +1 -1
  588. package/studio/web/assets/{regions-CkyurXzE.js → regions-n69fwagr.js} +1 -1
  589. package/studio/web/assets/{register-BUyhWjBO.js → register-PfWTCXWB.js} +3 -3
  590. package/studio/web/assets/{requirementDiagram-EFPCY7ZU-DNEGFjuW.js → requirementDiagram-BXWQKSXE-BJnO6uLz.js} +1 -1
  591. package/studio/web/assets/{sankeyDiagram-P5KCCOFB-DpyAmSVR.js → sankeyDiagram-P5KCCOFB-0vSOdymH.js} +1 -1
  592. package/studio/web/assets/{sequenceDiagram-WJ2MYXX4-TyaT7xNk.js → sequenceDiagram-WJ2MYXX4-hETizDWE.js} +1 -1
  593. package/studio/web/assets/{setComponentFile-CeyKSZAa.js → setComponentFile-Bg6O7X0S.js} +1 -1
  594. package/studio/web/assets/{setup-D2kn7cAA.js → setup-CUx_aUDl.js} +2 -2
  595. package/studio/web/assets/{stateDiagram-HBIQ2CUA-CeEdTArZ.js → stateDiagram-D77RDMKH-CdYQ_KtC.js} +1 -1
  596. package/studio/web/assets/stateDiagram-v2-MP3YSRHH-CdKuzQMT.js +1 -0
  597. package/studio/web/assets/status-D7BVKqX9.js +61 -0
  598. package/studio/web/assets/{swimlanes-XN3QIQJK-B54FmF46.js → swimlanes-42K2YHIH-B8cHIpU4.js} +1 -1
  599. package/studio/web/assets/swimlanesDiagram-VR7AAH4N-DmOSJwaH.js +8 -0
  600. package/studio/web/assets/{tabs-B_G5zscN.js → tabs-BrHu7gJi.js} +1 -1
  601. package/studio/web/assets/{timeline-definition-24CTP7MA-D-a9ujbo.js → timeline-definition-24CTP7MA-BJWYSXqF.js} +1 -1
  602. package/studio/web/assets/{toggleHighContrast-C0UW6rI2.js → toggleHighContrast-DBSyXzMr.js} +1 -1
  603. package/studio/web/assets/{treeView-Q6P3EWNA-CrW_6JnS.js → treeView-Q6P3EWNA-qxe_v6CQ.js} +1 -1
  604. package/studio/web/assets/{treemap-WGGIJYW6-BxyYLdP_.js → treemap-WGGIJYW6-dDo97XXF.js} +1 -1
  605. package/studio/web/assets/{tsMode-DBC0zmDx.js → tsMode-BByKCjBS.js} +1 -1
  606. package/studio/web/assets/{typescript-DApRQir3.js → typescript-DDLnLpw9.js} +1 -1
  607. package/studio/web/assets/{useEntityRestURL-DB6JStU1.js → useEntityRestURL-31CHGaHk.js} +1 -1
  608. package/studio/web/assets/{useLocalStorage-Dtj1QS8_.js → useLocalStorage-BqMR3D8_.js} +1 -1
  609. package/studio/web/assets/vendor-core-c2JRRJpV.js +58 -0
  610. package/studio/web/assets/vendor-datadog-CLUcJXOo.js +6 -0
  611. package/studio/web/assets/{vendor-react-Dyj4O3HE.js → vendor-react-CJV_K1u4.js} +1 -1
  612. package/studio/web/assets/vendor-tanstack-DxzraizX.js +1 -0
  613. package/studio/web/assets/{vendor-ui-vhu-UHhF.js → vendor-ui-BUjK0h8a.js} +2 -2
  614. package/studio/web/assets/{vennDiagram-4TSXK5OY-Cy7s7Mpy.js → vennDiagram-4TSXK5OY-A3i-lCdl.js} +1 -1
  615. package/studio/web/assets/{wardley-WFR3VGLG-BeBL35g2.js → wardley-WFR3VGLG-B0ik-_6g.js} +1 -1
  616. package/studio/web/assets/{wardleyDiagram-VM6X3IG4-BylmIGSg.js → wardleyDiagram-VM6X3IG4-CjrkKWUR.js} +1 -1
  617. package/studio/web/assets/{workers-C0bFIedw.js → workers-pR3jRY9D.js} +1 -1
  618. package/studio/web/assets/x-DIzaLEdK.js +1 -0
  619. package/studio/web/assets/{xml-HWd01lU-.js → xml-2iRnMhQO.js} +1 -1
  620. package/studio/web/assets/{xychartDiagram-S5SC5T6Z-CoKALMXr.js → xychartDiagram-S5SC5T6Z-Biok4GYV.js} +1 -1
  621. package/studio/web/assets/{yaml-CIH0Nt-h.js → yaml-Bf92gJpd.js} +1 -1
  622. package/studio/web/index.html +14 -14
  623. package/upgrade/directives/5-3-0.ts +132 -0
  624. package/upgrade/directives/directivesController.ts +2 -1
  625. package/utility/OperationFunctionCaller.ts +2 -1
  626. package/utility/common_utils.ts +30 -5
  627. package/utility/componentNames.ts +12 -0
  628. package/utility/environment/environmentManager.ts +3 -7
  629. package/utility/environment/systemInformation.ts +7 -0
  630. package/utility/errors/commonErrors.ts +4 -0
  631. package/utility/errors/hdbError.ts +29 -0
  632. package/utility/hdbTerms.ts +17 -0
  633. package/utility/logging/harper_logger.ts +87 -14
  634. package/utility/logging/logRotator.ts +72 -45
  635. package/utility/nodeIdentity.ts +45 -0
  636. package/utility/npmUtilities.ts +10 -8
  637. package/utility/operationPermissions.ts +18 -1
  638. package/utility/operation_authorization.ts +231 -42
  639. package/utility/watchPath.ts +63 -0
  640. package/utility/watcherFallback.ts +270 -0
  641. package/validation/configValidator.ts +209 -72
  642. package/validation/installValidator.ts +15 -0
  643. package/validation/validationWrapper.ts +18 -4
  644. package/studio/web/assets/Chat-JpO8EtUu.js +0 -2067
  645. package/studio/web/assets/FloatingChat-Bcj3xSZu.js +0 -23
  646. package/studio/web/assets/applications-ByqLRKyZ.js +0 -296
  647. package/studio/web/assets/architecture-7GRP2DOG-DNdx5tEU.js +0 -1
  648. package/studio/web/assets/authStore-qKmCZcaf.js +0 -3
  649. package/studio/web/assets/channel-DtCV8PTL.js +0 -1
  650. package/studio/web/assets/chunk-R7TYR2AO-Irip67yr.js +0 -10
  651. package/studio/web/assets/classDiagram-DTDB5LWJ-DbO_dCNE.js +0 -1
  652. package/studio/web/assets/classDiagram-v2-JRS7N3AN-DbO_dCNE.js +0 -1
  653. package/studio/web/assets/eventmodeling-NTZA5JFV-5jbe4A5P.js +0 -1
  654. package/studio/web/assets/flowDiagram-A5DVABFB-Dp9Ezlow.js +0 -1
  655. package/studio/web/assets/index-aSt5tY-L.js +0 -824
  656. package/studio/web/assets/index.lazy-B9jiPwT8.js +0 -2
  657. package/studio/web/assets/notifications-CUoYgU98.js +0 -1
  658. package/studio/web/assets/railroad-abnf-HS5TGJTU-Bc0Qi0WH.js +0 -1
  659. package/studio/web/assets/railroad-ebnf-LZEXJU2U-G8rVVZ2C.js +0 -1
  660. package/studio/web/assets/railroad-peg-WCYAUIDC-CrehKBhC.js +0 -1
  661. package/studio/web/assets/stateDiagram-v2-4QOOHH4V-D4tuw9Su.js +0 -1
  662. package/studio/web/assets/status-D7Xn5ePA.js +0 -61
  663. package/studio/web/assets/swimlanesDiagram-VK2B7HYN-XOhmNEvq.js +0 -8
  664. package/studio/web/assets/vendor-core-RCcadM3e.js +0 -73
  665. package/studio/web/assets/vendor-datadog-BRv-mOv1.js +0 -6
  666. package/studio/web/assets/vendor-tanstack-BiFWSB3W.js +0 -1
  667. package/studio/web/assets/x-B9o9hsep.js +0 -1
  668. /package/studio/web/assets/{sizeCapture-X5ZJPWSS-B0uUizjq.js → sizeCapture-INFHLROL-B0uUizjq.js} +0 -0
package/agent/mcpTools.ts CHANGED
@@ -57,7 +57,7 @@ const AGENT_MCP_TOOLS: Record<string, AgentMcpToolMeta> = {
57
57
  readOnly: true,
58
58
  },
59
59
  list_agent_sessions: {
60
- description: 'List built-in-agent sessions, most recent first.',
60
+ description: 'List built-in-agent sessions, most recently updated first.',
61
61
  inputSchema: {
62
62
  type: 'object',
63
63
  properties: { limit: { type: 'integer', minimum: 1, description: 'Max sessions to return (default 100).' } },
package/agent/session.ts CHANGED
@@ -16,6 +16,20 @@ import type { AgentMessage, AgentRunStatus, AgentSessionRow, ApprovalRequest } f
16
16
 
17
17
  let cachedTable: any;
18
18
 
19
+ /** `listSessions` sorts on `updatedAt`, which Table.search serves only from an index. */
20
+ export const AGENT_SESSION_ATTRIBUTES = [
21
+ { name: 'session_id', isPrimaryKey: true },
22
+ { name: 'user', type: 'string', indexed: true },
23
+ { name: 'status', type: 'string', indexed: true },
24
+ { name: 'messages' },
25
+ { name: 'pendingApprovals' },
26
+ { name: 'model', type: 'string' },
27
+ { name: 'provider', type: 'string' },
28
+ { name: 'createdAt', type: 'number', indexed: true },
29
+ { name: 'updatedAt', type: 'number', indexed: true },
30
+ { name: 'lastError', type: 'string' },
31
+ ];
32
+
19
33
  export function getAgentSessionTable(): any {
20
34
  if (cachedTable) return cachedTable;
21
35
  cachedTable = table({
@@ -23,18 +37,7 @@ export function getAgentSessionTable(): any {
23
37
  database: SYSTEM_SCHEMA_NAME,
24
38
  audit: true,
25
39
  trackDeletes: false,
26
- attributes: [
27
- { name: 'session_id', isPrimaryKey: true },
28
- { name: 'user', type: 'string', indexed: true },
29
- { name: 'status', type: 'string', indexed: true },
30
- { name: 'messages' },
31
- { name: 'pendingApprovals' },
32
- { name: 'model', type: 'string' },
33
- { name: 'provider', type: 'string' },
34
- { name: 'createdAt', type: 'number', indexed: true },
35
- { name: 'updatedAt', type: 'number', indexed: true },
36
- { name: 'lastError', type: 'string' },
37
- ],
40
+ attributes: AGENT_SESSION_ATTRIBUTES,
38
41
  });
39
42
  return cachedTable;
40
43
  }
@@ -77,8 +80,16 @@ export async function getSession(sessionId: string): Promise<AgentSessionRow | u
77
80
  export async function listSessions(opts: { limit?: number } = {}): Promise<AgentSessionRow[]> {
78
81
  const limit = opts.limit ?? 100;
79
82
  const out: AgentSessionRow[] = [];
80
- for (const entry of getAgentSessionTable().primaryStore.getRange({ reverse: true, limit })) {
81
- if (entry.value) out.push(entry.value as AgentSessionRow);
83
+ // Sort with no conditions on purpose: Table.search pushes an order-aligned pseudo-condition when
84
+ // the sort attribute is indexed, and throws 404 when it is not. Adding a `updatedAt > 0` sentinel
85
+ // to force the index would make conditions non-empty, so losing `indexed` on the attribute would
86
+ // silently degrade to decoding every session (full transcripts) and sorting in memory instead of
87
+ // failing. The sentinel would also drop rows whose updatedAt is absent or 0.
88
+ for await (const row of getAgentSessionTable().search({
89
+ sort: { attribute: 'updatedAt', descending: true },
90
+ limit,
91
+ })) {
92
+ if (row != null) out.push(row as AgentSessionRow);
82
93
  }
83
94
  return out;
84
95
  }
@@ -6,6 +6,7 @@ import * as envMgr from '../utility/environment/environmentManager.ts';
6
6
  envMgr.initSync();
7
7
  import * as terms from '../utility/hdbTerms.ts';
8
8
  import { httpRequest } from '../utility/common_utils.ts';
9
+ import { workloadIdentityAvailable, exchangeWorkloadIdentityForToken } from './workloadIdentity.ts';
9
10
  import * as fs from 'fs-extra';
10
11
  import * as YAML from 'yaml';
11
12
  import { Readable } from 'node:stream';
@@ -55,11 +56,11 @@ const TRANSPORT_ONLY_FIELDS = new Set([
55
56
  'by_ref',
56
57
  'ref',
57
58
  'credential',
58
- // `deploy setup=true`'s token, read off the parsed request by deploySetup and sealed locally. No
59
- // operation takes a *top-level* `token`, so keeping it out of every body costs nothing and means a
60
- // mistyped `setup` — which parses as a bare word and falls through to a real deploy — can't carry a
61
- // PAT to the server. Distinct from `credentials[].token`, which is nested inside a field that IS
62
- // sent (ingestCredentials seals it server-side) and is only kept out of the operations log.
59
+ // `deploy setup=true`'s token, read off the parsed request by deploySetup and sealed locally.
60
+ // Stripping it means a mistyped `setup` — which parses as a bare word and falls through to a real
61
+ // deploy — can't carry a PAT to the server. Distinct from `credentials[].token`, which is nested
62
+ // inside a field that IS sent (ingestCredentials seals it server-side) and is only kept out of the
63
+ // operations log. See OPERATIONS_TAKING_A_TOKEN for the one operation this must not apply to.
63
64
  'token',
64
65
  ]);
65
66
 
@@ -179,10 +180,24 @@ async function* wrapPackagingStream(stream: Readable, projectPath: string): Asyn
179
180
  // Build the JSON operation-field set from `req`, dropping the CLI's internal (`_`-prefixed)
180
181
  // and transport-only fields so neither the CLI internals nor credentials leak into the
181
182
  // request body. Shared by the multipart and legacy-JSON deploy body builders.
183
+ /**
184
+ * Operations whose own request body has a top-level `token`, which must therefore survive the
185
+ * transport-only stripping above.
186
+ *
187
+ * `exchange_oidc_token` (#2171) is one: the identity token IS the request. The blanket strip was
188
+ * written when no operation took a top-level `token`, and left this one reaching the server without
189
+ * the field it requires — so the issuer-agnostic path was unusable through the generic CLI even
190
+ * though direct HTTP worked. Keyed on the operation rather than dropping the strip, because the
191
+ * mistyped-`setup` case it guards against is real.
192
+ */
193
+ const OPERATIONS_TAKING_A_TOKEN = new Set(['exchange_oidc_token']);
194
+
182
195
  function operationFields(req: any): any {
196
+ const keepsToken = OPERATIONS_TAKING_A_TOKEN.has(req?.operation);
183
197
  const fields: any = {};
184
198
  for (const [key, value] of Object.entries(req)) {
185
- if (key.startsWith('_') || TRANSPORT_ONLY_FIELDS.has(key)) continue;
199
+ if (key.startsWith('_')) continue;
200
+ if (TRANSPORT_ONLY_FIELDS.has(key) && !(key === 'token' && keepsToken)) continue;
186
201
  fields[key] = value;
187
202
  }
188
203
  return fields;
@@ -764,7 +779,8 @@ export async function resolveRequestOptions(req: any): Promise<{ options: any; t
764
779
  options.timeout = SSE_OPERATIONS.has(req.operation) ? SSE_OPERATION_TIMEOUT_MS : CLI_OPERATION_TIMEOUT_MS;
765
780
  // Authentication precedence: explicitly configured credentials (dedicated args, URL
766
781
  // userinfo, env vars) beat everything, then env-var tokens, then the saved `harper login`
767
- // token, and only then the legacy `username=`/`password=` payload fallback below. The
782
+ // token, then a CI identity token exchanged via OIDC (#2171 — ambient, so it ranks below
783
+ // everything configured), and only then the legacy `username=`/`password=` fallback. The
768
784
  // tokens must outrank that fallback: for add_user/alter_user those args are the credentials
769
785
  // of the user being created/altered, so treating them as auth would authenticate as a user
770
786
  // who doesn't exist yet (or as the wrong identity) instead of using the admin's session.
@@ -799,9 +815,12 @@ export async function resolveRequestOptions(req: any): Promise<{ options: any; t
799
815
  const envRefreshToken = tokenPrefix ? process.env[`${tokenPrefix}_REFRESH_TOKEN`]?.trim() : undefined;
800
816
  // A namespace that is set but blank is a broken CI secret, not a request to fall back to
801
817
  // whatever the developer last logged in as — say so rather than switching identity silently.
802
- if (tokenPrefix && !envOperationToken && !envRefreshToken) {
818
+ const tokenNamespaceBlank = !!tokenPrefix && !envOperationToken && !envRefreshToken;
819
+ if (tokenNamespaceBlank) {
803
820
  console.error(
804
- `Ignoring empty ${tokenPrefix}_OPERATION_TOKEN/${tokenPrefix}_REFRESH_TOKEN; falling back to saved login credentials.`
821
+ `Ignoring empty ${tokenPrefix}_OPERATION_TOKEN/${tokenPrefix}_REFRESH_TOKEN; falling back to saved ` +
822
+ `login credentials. Workload identity is deliberately NOT used here: a blank token namespace is a ` +
823
+ `failed secret, and deploying as a different identity would hide that.`
805
824
  );
806
825
  }
807
826
 
@@ -819,6 +838,24 @@ export async function resolveRequestOptions(req: any): Promise<{ options: any; t
819
838
  if (tokens.operation_token) {
820
839
  options.headers.Authorization = `Bearer ${tokens.operation_token}`;
821
840
  }
841
+ } else if (workloadIdentityAvailable() && !tokenNamespaceBlank) {
842
+ // Last credential source: no configured token, but this runner can prove its identity to
843
+ // the cluster directly (#2171). Deliberately below the env-var and saved tokens — an
844
+ // explicitly configured credential should keep working exactly as it did when someone adds
845
+ // `id-token: write` to a workflow, rather than silently switching which identity deploys.
846
+ //
847
+ // `!tokenNamespaceBlank` extends that invariant to the half-configured case. A CI secret
848
+ // that failed to populate leaves the namespace set but empty; without this, such a run
849
+ // would quietly deploy as the OIDC policy's user instead of failing, which is the same
850
+ // silent identity switch in a shape that is harder to notice.
851
+ // Standard operation timeout, not the caller's — by this point `options.timeout` may carry
852
+ // the 10-minute SSE timeout for a streaming deploy_component, and the exchange is a small
853
+ // fast request. Without the override a stalled exchange hangs the deploy for ten minutes,
854
+ // on the very operation this feature exists to serve. Same reasoning, same fix as
855
+ // refreshExpiredOperationToken above.
856
+ const exchangeOptions = { ...options, timeout: CLI_OPERATION_TIMEOUT_MS };
857
+ const operationToken = await exchangeWorkloadIdentityForToken(exchangeOptions, target.resolvedTarget);
858
+ if (operationToken) options.headers.Authorization = `Bearer ${operationToken}`;
822
859
  }
823
860
  }
824
861
  // Legacy fallback for operations where `username=`/`password=` genuinely ARE the caller's
package/bin/copyDb.ts CHANGED
@@ -6,16 +6,17 @@ import {
6
6
  toRocksCompression,
7
7
  } from '../resources/databases.ts';
8
8
  import { open, asBinary } from 'lmdb';
9
- import { join } from 'path';
9
+ import { isAbsolute, join, relative, sep } from 'node:path';
10
10
  import { move, remove } from 'fs-extra';
11
11
  import { existsSync, mkdirSync } from 'node:fs';
12
- import { rename } from 'node:fs/promises';
12
+ import { rename, writeFile } from 'node:fs/promises';
13
13
  import { get } from '../utility/environment/environmentManager.ts';
14
14
  import OpenEnvironmentObject from '../utility/lmdb/OpenEnvironmentObject.ts';
15
15
  import { OpenDBIObject } from '../utility/lmdb/OpenDBIObject.ts';
16
16
  import { INTERNAL_DBIS_NAME, AUDIT_STORE_NAME } from '../utility/lmdb/terms.ts';
17
17
  import { CONFIG_PARAMS, DATABASES_DIR_NAME, MIGRATING_DIR_SUFFIX } from '../utility/hdbTerms.ts';
18
- import { AUDIT_STORE_OPTIONS } from '../resources/auditStore.ts';
18
+ import { AUDIT_STORE_OPTIONS, auditRetention } from '../resources/auditStore.ts';
19
+ import { blobsReadmeContent, copyBlobRootsByIndex } from '../dataLayer/blobBackup.ts';
19
20
  import { describeSchema } from '../dataLayer/schemaDescribe.ts';
20
21
  import { updateConfigValue } from '../config/configUtils.ts';
21
22
  import * as hdbLogger from '../utility/logging/harper_logger.ts';
@@ -26,6 +27,7 @@ import {
26
27
  beginPendingMigrationBlobSaves,
27
28
  encodeBlobsWithFilePath,
28
29
  endPendingMigrationBlobSaves,
30
+ getBlobPathsForDatabaseName,
29
31
  } from '../resources/blob.ts';
30
32
  import {
31
33
  RecordEncoder,
@@ -50,18 +52,35 @@ export async function compactOnStart() {
50
52
  for (const databaseName in databases) {
51
53
  if (databaseName === 'system') continue;
52
54
  if (databaseName.endsWith('-copy')) continue; // don't copy the copy
53
- let dbPath;
54
- for (const tableName in databases[databaseName]) {
55
- dbPath = databases[databaseName][tableName].primaryStore.path;
56
- break;
57
- }
58
- if (!dbPath) {
55
+ const rootStores = getRootStores(databases[databaseName]);
56
+ if (rootStores.size === 0) {
59
57
  console.log("Couldn't find any tables in database", databaseName);
60
58
  continue;
61
59
  }
60
+ if ([...rootStores].some((rootStore) => rootStore instanceof RocksDatabase)) {
61
+ console.log('Database', databaseName, 'is RocksDB, which compacts itself, skipping');
62
+ continue;
63
+ }
64
+ // Compaction replaces one environment file, and leaves the blob roots alone because the
65
+ // compacted copy goes back to this exact path under this database name. Tables in separate
66
+ // environments have no single file to replace, so compacting them would relocate tables and
67
+ // strand their blobs.
68
+ if (rootStores.size > 1) {
69
+ const message = `Skipping compaction of database ${databaseName}: its tables span ${rootStores.size} storage environments (table-specific paths), which compaction cannot replace as one file`;
70
+ hdbLogger.warn(message);
71
+ console.warn(message);
72
+ continue;
73
+ }
74
+ const dbPath = [...rootStores][0].path;
62
75
 
63
76
  const backupDest = join(rootPath, 'backup', databaseName + '.mdb');
64
77
  const copyDest = join(rootPath, DATABASES_DIR_NAME, databaseName + '-copy.mdb');
78
+ if (existsSync(copyDest)) {
79
+ const message = `Skipping compaction of database ${databaseName}: ${copyDest} already exists; inspect and rename or remove it, then re-enable '${CONFIG_PARAMS.STORAGE_COMPACTONSTART}' before retrying (this run already disabled it)`;
80
+ hdbLogger.warn(message);
81
+ console.warn(message);
82
+ continue;
83
+ }
65
84
  let recordCount = 0;
66
85
  try {
67
86
  recordCount = await getTotalDBRecordCount(databaseName);
@@ -70,21 +89,24 @@ export async function compactOnStart() {
70
89
  hdbLogger.error('Error getting record count for database', databaseName, error);
71
90
  console.error('Error getting record count for database', databaseName, error);
72
91
  }
73
- compactedDb.set(databaseName, {
92
+ const compactionState = {
74
93
  dbPath,
75
94
  copyDest,
76
95
  backupDest,
77
96
  recordCount,
78
- });
97
+ backedUp: false,
98
+ };
99
+ compactedDb.set(databaseName, compactionState);
79
100
 
80
- await copyDb(databaseName, copyDest);
101
+ await remove(copyDest + '-lock');
81
102
 
103
+ await copyDb(databaseName, copyDest, { blobs: 'preserve-source-roots' });
104
+
105
+ // The backup is the only rollback for the overwrite below, so a failed backup fails the
106
+ // compaction (leaving the source in place) instead of overwriting the only copy.
82
107
  console.log('Backing up', databaseName, 'to', backupDest);
83
- try {
84
- await move(dbPath, backupDest, { overwrite: true });
85
- } catch (error) {
86
- console.log('Error moving database', dbPath, 'to', backupDest, error);
87
- }
108
+ await move(dbPath, backupDest, { overwrite: true });
109
+ compactionState.backedUp = true;
88
110
  // Move compacted DB to back to original DB path
89
111
  console.log('Moving copy compacted', databaseName, 'to', dbPath);
90
112
  await move(copyDest, dbPath, { overwrite: true });
@@ -110,7 +132,12 @@ export async function compactOnStart() {
110
132
 
111
133
  updateConfigValue(CONFIG_PARAMS.STORAGE_COMPACTONSTART, false);
112
134
 
113
- for (const [_db, { dbPath, backupDest }] of compactedDb) {
135
+ for (const [_db, { dbPath, backupDest, backedUp }] of compactedDb) {
136
+ // Only a backup this run created is this run's source to restore. `backupDest` is a fixed
137
+ // path per database, so a retained backup from an earlier run can be sitting there — moving
138
+ // that over a database whose compaction failed before its own backup was taken would
139
+ // replace healthy data with a stale snapshot.
140
+ if (!backedUp) continue;
114
141
  console.error('Moving backup database', backupDest, 'back to', dbPath);
115
142
  try {
116
143
  await move(backupDest, dbPath, { overwrite: true });
@@ -155,14 +182,133 @@ function noop() {
155
182
  // if there are any attempts to write to the db, ignore them
156
183
  }
157
184
 
158
- export async function copyDb(sourceDatabase: string, targetDatabasePath: string) {
185
+ function getRootStores(database): Set<any> {
186
+ const rootStores = new Set<any>();
187
+ for (const tableName in database) rootStores.add(database[tableName].primaryStore.rootStore);
188
+ return rootStores;
189
+ }
190
+
191
+ const BLOB_COPY_SUFFIX = '-blobs';
192
+
193
+ const STRUCTURES_KEY = Symbol.for('structures');
194
+
195
+ const MAX_COPY_RETRIES = 1000;
196
+
197
+ const MSGPACK_NIL = 0xc0;
198
+
199
+ function isWithin(path: string, directory: string): boolean {
200
+ const relativePath = relative(directory, path);
201
+ if (relativePath === '') return true;
202
+ if (isAbsolute(relativePath)) return false;
203
+ // Segment-aware: a child literally named e.g. `..copy.mdb-blobs` is a real child, not an escape —
204
+ // only a first segment of exactly `..` walks up out of `directory`.
205
+ return relativePath.split(sep)[0] !== '..';
206
+ }
207
+
208
+ /**
209
+ * Read and write raw stored bytes through this handle: `openDB` builds a RecordEncoder from the DBI
210
+ * options whatever `encoding` says, and the live audit store also wraps `getRange` to yield decoded
211
+ * audit records, so a byte-for-byte copy needs the encoder detached.
212
+ */
213
+ function useRawBytes(store) {
214
+ store.encoder = null;
215
+ store.decoder = null;
216
+ store.decoderCopies = false;
217
+ store.encoding = 'binary';
218
+ return store;
219
+ }
220
+
221
+ /**
222
+ * Copy a database's blob roots into `<targetDatabasePath>-blobs/<rootIndex>/…`. Blob files live
223
+ * outside the environment file and are addressed by database *name* against the running instance's
224
+ * configured roots, so a copy without them is unreadable anywhere but its own origin.
225
+ */
226
+ async function copyDatabaseBlobs(sourceDatabase: string, targetDatabasePath: string, blobRoots: string[]) {
227
+ const populatedRoots = blobRoots.filter((root) => existsSync(root));
228
+ const missingRoots = blobRoots.filter((root) => !existsSync(root));
229
+ if (missingRoots.length > 0) {
230
+ const message =
231
+ `Configured blob root(s) ${missingRoots.join(', ')} of ${sourceDatabase} do not exist and will be copied as ` +
232
+ `empty; if this database has ever written blobs to them (rather than never having used them), this copy is missing those blobs.`;
233
+ hdbLogger.warn(message);
234
+ console.warn(message);
235
+ }
236
+ if (populatedRoots.length === 0) return;
237
+ const destination = targetDatabasePath + BLOB_COPY_SUFFIX;
238
+ await copyBlobRootsByIndex(destination, blobRoots);
239
+ await writeFile(join(destination, 'README.md'), blobsReadmeContent(blobRoots, { variant: 'copy' }));
240
+ const message =
241
+ `Copied ${populatedRoots.length} blob root(s) of ${sourceDatabase} to ${destination}. This copy is not ` +
242
+ `restorable without them: blobs are addressed by database name, so each <rootIndex> directory has to be ` +
243
+ `placed into the matching blob root of the database the copy is restored as (see ${join(destination, 'README.md')})`;
244
+ hdbLogger.notify(message);
245
+ console.log(message);
246
+ }
247
+
248
+ /**
249
+ * Copy a database's LMDB environment to `targetDatabasePath`.
250
+ *
251
+ * `blobs` declares what happens to the database's file-backed blobs, and is required because both
252
+ * answers are silently destructive when wrong: `'copy'` writes them beside the target (what an
253
+ * operator copying a database elsewhere needs), `'preserve-source-roots'` leaves them untouched and
254
+ * is only sound when the copy replaces the source environment under the same database name, which is
255
+ * what makes the existing roots keep resolving.
256
+ */
257
+ export async function copyDb(
258
+ sourceDatabase: string,
259
+ targetDatabasePath: string,
260
+ options: { blobs: 'copy' | 'preserve-source-roots' }
261
+ ) {
262
+ const blobDisposition = options?.blobs;
263
+ if (blobDisposition !== 'copy' && blobDisposition !== 'preserve-source-roots')
264
+ throw new Error(
265
+ `copyDb requires a blob disposition: { blobs: 'copy' } to copy ${sourceDatabase}'s blob files beside the target, ` +
266
+ `or { blobs: 'preserve-source-roots' } when the copy replaces the source environment in place`
267
+ );
159
268
  console.log(`Copying database ${sourceDatabase} to ${targetDatabasePath}`);
160
269
  const sourceDb = getDatabases()[sourceDatabase];
161
270
  if (!sourceDb) throw new Error(`Source database not found: ${sourceDatabase}`);
162
- let rootStore;
271
+ const rootStores = getRootStores(sourceDb);
272
+ if (rootStores.size === 0) throw new Error(`Source database does not have any tables: ${sourceDatabase}`);
273
+ if (rootStores.size > 1)
274
+ throw new Error(
275
+ `Database ${sourceDatabase} spans ${rootStores.size} storage environments (table-specific paths); ` +
276
+ `copying it into the single environment ${targetDatabasePath} would relocate tables and strand their blobs`
277
+ );
278
+ const [rootStore] = rootStores;
279
+ if (rootStore instanceof RocksDatabase)
280
+ throw new Error(`Database ${sourceDatabase} is stored in RocksDB; copyDb copies LMDB environments only`);
281
+ if (existsSync(targetDatabasePath))
282
+ throw new Error(
283
+ `Copy target ${targetDatabasePath} already exists; remove it first — opening it would merge this copy into whatever it holds`
284
+ );
285
+ const blobRoots = blobDisposition === 'copy' ? getBlobPathsForDatabaseName(sourceDatabase) : [];
286
+ const blobDestination = targetDatabasePath + BLOB_COPY_SUFFIX;
287
+ if (blobDisposition === 'copy') {
288
+ if (existsSync(blobDestination))
289
+ throw new Error(`Blob copy target ${blobDestination} already exists; remove it first`);
290
+ // Every path a failure can remove or write through, not just the final blob destination — a
291
+ // staging or lock sibling landing inside a blob root would be just as destructive on cleanup.
292
+ const destinationPaths = [
293
+ targetDatabasePath,
294
+ targetDatabasePath + '-lock',
295
+ blobDestination,
296
+ blobDestination + '.tmp',
297
+ ];
298
+ for (const root of blobRoots) {
299
+ for (const destinationPath of destinationPaths) {
300
+ if (isWithin(destinationPath, root) || isWithin(root, destinationPath))
301
+ throw new Error(
302
+ `Copy target ${targetDatabasePath} overlaps the source blob root ${root}; choose a target outside it`
303
+ );
304
+ }
305
+ }
306
+ }
307
+ // Suppress source writes only once the copy is going ahead: a caller that catches a rejection above
308
+ // keeps using these stores.
309
+ const primaryStoresByDbi = new Map<string, any>();
163
310
  for (const tableName in sourceDb) {
164
311
  const table = sourceDb[tableName];
165
- // ensure that writes aren't occurring
166
312
  table.primaryStore.put = noop;
167
313
  table.primaryStore.remove = noop;
168
314
  for (const attributeName in table.indices) {
@@ -174,9 +320,27 @@ export async function copyDb(sourceDatabase: string, targetDatabasePath: string)
174
320
  table.auditStore.put = noop;
175
321
  table.auditStore.remove = noop;
176
322
  }
177
- rootStore = table.primaryStore.rootStore;
323
+ primaryStoresByDbi.set(table.primaryStore.name, table.primaryStore);
324
+ }
325
+ try {
326
+ await copyDbEnvironment(sourceDatabase, targetDatabasePath, rootStore, primaryStoresByDbi);
327
+ if (blobDisposition === 'copy') await copyDatabaseBlobs(sourceDatabase, targetDatabasePath, blobRoots);
328
+ } catch (error) {
329
+ // Every path removed here was created by this call — both targets are rejected above if they
330
+ // already exist — and a partial copy left behind is a copy someone can restore from.
331
+ await remove(targetDatabasePath).catch(() => {});
332
+ await remove(targetDatabasePath + '-lock').catch(() => {});
333
+ if (blobDisposition === 'copy') await remove(blobDestination).catch(() => {});
334
+ throw error;
178
335
  }
179
- if (!rootStore) throw new Error(`Source database does not have any tables: ${sourceDatabase}`);
336
+ }
337
+
338
+ async function copyDbEnvironment(
339
+ sourceDatabase: string,
340
+ targetDatabasePath: string,
341
+ rootStore,
342
+ primaryStoresByDbi: Map<string, any>
343
+ ) {
180
344
  // this contains the list of all the dbis
181
345
  const sourceDbisDb = rootStore.dbisDb;
182
346
  const sourceAuditStore = rootStore.auditStore;
@@ -184,6 +348,8 @@ export async function copyDb(sourceDatabase: string, targetDatabasePath: string)
184
348
  const targetDbisDb = targetEnv.openDB({ name: INTERNAL_DBIS_NAME });
185
349
  let written;
186
350
  let outstandingWrites = 0;
351
+ // One cutoff for the whole copy so a long copy classifies every tombstone against the same instant
352
+ const tombstoneCutoff = Date.now() - auditRetention;
187
353
  // we use a single transaction to get a snapshot, also we can't use snapshot: false on dupsort dbs
188
354
  const transaction = sourceDbisDb.useReadTransaction();
189
355
  try {
@@ -209,36 +375,83 @@ export async function copyDb(sourceDatabase: string, targetDatabasePath: string)
209
375
  dbiInit.encoding = 'binary';
210
376
  dbiInit.compression = existingCompression;
211
377
  //dbiInit.keyEncoding = 'binary';
212
- const sourceDbi = rootStore.openDB(key, dbiInit);
213
- sourceDbi.decoder = null;
214
- sourceDbi.decoderCopies = false;
215
- sourceDbi.encoding = 'binary';
378
+ const sourceDbi = useRawBytes(rootStore.openDB(key, dbiInit));
216
379
  dbiInit.compression = newCompression;
217
- const targetDbi = (targetEnv as any).openDB(key, dbiInit);
218
- (targetDbi as any).encoder = null;
380
+ const targetDbi = useRawBytes((targetEnv as any).openDB(key, dbiInit));
219
381
  console.log('copying', key, 'from', sourceDatabase, 'to', targetDatabasePath);
220
- await copyDbi(sourceDbi, targetDbi, isPrimary, transaction);
382
+ await copyDbi(sourceDbi, targetDbi, isPrimary, transaction, primaryStoresByDbi.get(key));
383
+ if (isPrimary) await verifyStructuresCopied(sourceDbi, targetDbi, key);
221
384
  }
222
385
  if (sourceAuditStore) {
223
- const targetAuditStore = rootStore.openDB(AUDIT_STORE_NAME, AUDIT_STORE_OPTIONS);
386
+ // Each handle belongs to its own environment: a "target" handle opened on the source env
387
+ // writes the audit log back into the source and leaves the copy without one.
388
+ const sourceAuditDbi = rootStore.openDB(AUDIT_STORE_NAME, { create: false, ...AUDIT_STORE_OPTIONS });
389
+ if (!sourceAuditDbi) throw new Error(`Could not open the audit store of ${sourceDatabase} to copy it`);
390
+ const targetAuditStore = (targetEnv as any).openDB(AUDIT_STORE_NAME, AUDIT_STORE_OPTIONS);
224
391
  console.log('copying audit log for', sourceDatabase, 'to', targetDatabasePath);
225
- copyDbi(sourceAuditStore, targetAuditStore, false, transaction);
392
+ await copyDbi(useRawBytes(sourceAuditDbi), useRawBytes(targetAuditStore), false, transaction);
226
393
  }
227
394
 
228
- async function copyDbi(sourceDbi, targetDbi, isPrimary, transaction) {
395
+ /**
396
+ * A primary DBI's shared-structures dictionary is the whole table's decodability: without it
397
+ * every copied record decodes to null. It rides through the copy as a symbol-keyed entry, so
398
+ * confirm it landed rather than trusting the walk.
399
+ */
400
+ async function verifyStructuresCopied(sourceDbi, targetDbi, dbiName) {
401
+ const sourceStructures = sourceDbi.getBinary?.(STRUCTURES_KEY);
402
+ if (!sourceStructures) return;
403
+ await written;
404
+ const copiedStructures = targetDbi.getBinary(STRUCTURES_KEY);
405
+ if (!copiedStructures || !Buffer.from(copiedStructures).equals(Buffer.from(sourceStructures)))
406
+ throw new Error(
407
+ `Copy of ${sourceDatabase}/${dbiName} to ${targetDatabasePath} lost the shared-structures dictionary ` +
408
+ `(${sourceStructures.length} source bytes, ${copiedStructures?.length ?? 0} copied) — every record in the copy would decode as null`
409
+ );
410
+ }
411
+
412
+ /**
413
+ * Return a delete tombstone's local retention timestamp, decided by decoding it with the live table's
414
+ * record decoder. Length cannot decide it — a small shared-structures dictionary and a small
415
+ * record both land in a tombstone's usual size range — and `decode` returning null is not
416
+ * sufficient either, since it also returns null for a record whose shared structure is missing
417
+ * on this node. Only a metadata-bearing decode proves a tombstone; anything unprovable is kept.
418
+ */
419
+ function getDeletedRecordTime(value, primaryStore, version) {
420
+ if (!primaryStore?.decoder) return;
421
+ try {
422
+ if (primaryStore.decoder.decode(value) === null && lastMetadata?.value === null)
423
+ return lastMetadata.localTime ?? version;
424
+ } catch {
425
+ return;
426
+ }
427
+ }
428
+
429
+ async function copyDbi(sourceDbi, targetDbi, isPrimary, transaction, primaryStore?) {
229
430
  let recordsCopied = 0;
230
431
  let bytesCopied = 0;
231
432
  let skippedRecord = 0;
232
- let retries = 10000000;
433
+ let failedRecords = 0;
434
+ let retries = MAX_COPY_RETRIES;
233
435
  let start = null;
234
- while (retries-- > 0) {
436
+ let completed = false;
437
+ while (!completed && retries-- > 0) {
235
438
  try {
236
- for (const key of sourceDbi.getKeys({ start, transaction })) {
439
+ // getRange, not getKeys + getEntry: on a dupSort index the latter yields one entry per
440
+ // unique key, dropping every duplicate
441
+ for (const { key, value, version } of sourceDbi.getRange(
442
+ isPrimary ? { start, transaction, versions: true } : { start, transaction }
443
+ )) {
237
444
  try {
238
445
  start = key;
239
- const { value, version } = sourceDbi.getEntry(key, { transaction });
240
- // deleted entries should be 13 bytes long (8 for timestamp, 4 bytes for flags, 1 byte of the encoding of null)
241
- if (value?.length < 14 && isPrimary) {
446
+ // Drop a tombstone only once it is past audit retention, the point the runtime
447
+ // removes it too: dropping a live one loses the delete, letting a peer that
448
+ // missed it resurrect the record. A tombstone's body is a lone msgpack nil, so
449
+ // the trailing byte keeps the decode off every other record.
450
+ const deletedRecordTime =
451
+ isPrimary && typeof key !== 'symbol' && value?.[value.length - 1] === MSGPACK_NIL
452
+ ? getDeletedRecordTime(value, primaryStore, version)
453
+ : undefined;
454
+ if (deletedRecordTime != null && deletedRecordTime < tombstoneCutoff) {
242
455
  skippedRecord++;
243
456
  continue;
244
457
  }
@@ -260,6 +473,7 @@ export async function copyDb(sourceDatabase: string, targetDatabasePath: string)
260
473
  outstandingWrites = 0;
261
474
  }
262
475
  } catch (error) {
476
+ failedRecords++;
263
477
  console.error(
264
478
  'Error copying record',
265
479
  typeof key === 'symbol' ? 'symbol' : key,
@@ -269,36 +483,46 @@ export async function copyDb(sourceDatabase: string, targetDatabasePath: string)
269
483
  targetDatabasePath,
270
484
  error
271
485
  );
486
+ break;
272
487
  }
273
488
  }
274
- console.log(
275
- 'finish copying, copied',
276
- recordsCopied,
277
- 'entries, skipped',
278
- skippedRecord,
279
- 'delete records,',
280
- bytesCopied,
281
- 'bytes'
489
+ completed = true;
490
+ } catch (error) {
491
+ // Resume from the last key read, never past it: re-copying that key is idempotent (an
492
+ // identical put, and an identical dupSort pair, is a no-op) while advancing the key
493
+ // would jump the copy over everything in between and still reach the success path.
494
+ console.error(
495
+ `Error iterating ${sourceDatabase} near key ${typeof start === 'symbol' ? 'symbol' : JSON.stringify(start)}, retrying (${retries} retries left):`,
496
+ error
282
497
  );
283
- return;
284
- } catch {
285
- // try to resume with a bigger key
286
- if (typeof start === 'string') {
287
- if (start === 'z') {
288
- return console.error('Reached end of dbi', start, 'for', sourceDatabase, 'to', targetDatabasePath);
289
- }
290
- start = start.slice(0, -2) + 'z';
291
- } else if (typeof start === 'number') start++;
292
- else return console.error('Unknown key type', start, 'for', sourceDatabase, 'to', targetDatabasePath);
293
498
  }
294
499
  }
500
+ // A copy that lost entries, or stopped part-way through a DBI, must not report success
501
+ if (!completed)
502
+ throw new Error(
503
+ `Copy of ${sourceDatabase} to ${targetDatabasePath} could not get past key ` +
504
+ `${typeof start === 'symbol' ? 'symbol' : JSON.stringify(start)} in ${MAX_COPY_RETRIES} attempts`
505
+ );
506
+ if (failedRecords > 0)
507
+ throw new Error(
508
+ `Copy of ${sourceDatabase} to ${targetDatabasePath} failed on ${failedRecords} entry/entries after copying ${recordsCopied}`
509
+ );
510
+ console.log(
511
+ 'finish copying, copied',
512
+ recordsCopied,
513
+ 'entries, skipped',
514
+ skippedRecord,
515
+ 'delete records,',
516
+ bytesCopied,
517
+ 'bytes'
518
+ );
295
519
  }
296
520
 
297
521
  await written;
298
522
  console.log('copied database ' + sourceDatabase + ' to ' + targetDatabasePath);
299
523
  } finally {
300
524
  transaction.done();
301
- targetEnv.close();
525
+ await targetEnv.close();
302
526
  }
303
527
  }
304
528
 
@@ -561,7 +785,6 @@ export async function copyDbToRocks(sourceRootStore, sourceDatabase: string, tar
561
785
  });
562
786
  targetHandles.push(targetDbisDb);
563
787
 
564
- const STRUCTURES_KEY = Symbol.for('structures');
565
788
  const copyStructures = (sourceDbi, storeName: string, extraTarget?: RocksDatabase) => {
566
789
  const buffer = sourceDbi.getBinary?.(STRUCTURES_KEY);
567
790
  if (buffer) {