@harperfast/harper 5.2.13 → 5.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (655) hide show
  1. package/agent/mcpTools.ts +1 -1
  2. package/agent/session.ts +25 -14
  3. package/bin/cliOperations.ts +58 -9
  4. package/bin/copyDb.ts +282 -59
  5. package/bin/deploySetup.ts +16 -5
  6. package/bin/harper.ts +1 -1
  7. package/bin/help.ts +4 -1
  8. package/bin/lite.ts +4 -1
  9. package/bin/restart.ts +120 -4
  10. package/bin/run.ts +6 -11
  11. package/bin/upgrade.js +7 -3
  12. package/bin/workloadIdentity.ts +119 -0
  13. package/components/Application.ts +3436 -242
  14. package/components/ApplicationScope.ts +8 -0
  15. package/components/EntryHandler.ts +59 -39
  16. package/components/OptionsWatcher.ts +440 -98
  17. package/components/RuntimeModuleTracker.ts +38 -7
  18. package/components/Scope.ts +56 -15
  19. package/components/awaitRestart.ts +84 -0
  20. package/components/componentLoader.ts +381 -32
  21. package/components/componentPreparationLock.ts +16 -5
  22. package/components/deploymentOperations.ts +4 -1
  23. package/components/deploymentRecorder.ts +9 -2
  24. package/components/mcp/adapters/harperHttp.ts +4 -0
  25. package/components/mcp/listChanged.ts +4 -0
  26. package/components/mcp/toolRegistry.ts +2 -0
  27. package/components/mcp/tools/operations.ts +9 -0
  28. package/components/mcp/tools/schemas/operationDescriptions.ts +2 -2
  29. package/components/operations.js +537 -113
  30. package/components/operationsValidation.js +98 -3
  31. package/components/packageComponent.ts +25 -1
  32. package/components/requestRestart.ts +11 -0
  33. package/components/status/ComponentStatusRegistry.ts +59 -0
  34. package/config/RootConfigWatcher.ts +240 -40
  35. package/config/configReadRetry.ts +62 -0
  36. package/config/configUtils.ts +357 -48
  37. package/config/harperConfigEnvVars.ts +170 -27
  38. package/config/parseConfigFile.ts +34 -0
  39. package/config/readConfigFileSync.ts +44 -0
  40. package/config/watcherArming.ts +59 -0
  41. package/config-root.schema.json +33 -0
  42. package/dataLayer/blobBackup.ts +160 -50
  43. package/dataLayer/delete.ts +6 -1
  44. package/dataLayer/harperBridge/ResourceBridge.ts +80 -10
  45. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  46. package/dataLayer/hdbInfoController.ts +34 -1
  47. package/dataLayer/insert.ts +44 -1
  48. package/dataLayer/rocksdbBackup.ts +53 -10
  49. package/dataLayer/schema.ts +11 -1
  50. package/dataLayer/schemaDescribe.ts +8 -1
  51. package/dist/agent/mcpTools.js +1 -1
  52. package/dist/agent/mcpTools.js.map +1 -1
  53. package/dist/agent/session.d.ts +22 -0
  54. package/dist/agent/session.js +26 -15
  55. package/dist/agent/session.js.map +1 -1
  56. package/dist/bin/cliOperations.js +61 -9
  57. package/dist/bin/cliOperations.js.map +1 -1
  58. package/dist/bin/copyDb.d.ts +12 -1
  59. package/dist/bin/copyDb.js +248 -60
  60. package/dist/bin/copyDb.js.map +1 -1
  61. package/dist/bin/deploySetup.d.ts +2 -0
  62. package/dist/bin/deploySetup.js +11 -3
  63. package/dist/bin/deploySetup.js.map +1 -1
  64. package/dist/bin/harper.js +1 -1
  65. package/dist/bin/harper.js.map +1 -1
  66. package/dist/bin/help.js +4 -1
  67. package/dist/bin/help.js.map +1 -1
  68. package/dist/bin/lite.js +4 -1
  69. package/dist/bin/lite.js.map +1 -1
  70. package/dist/bin/restart.js +91 -6
  71. package/dist/bin/restart.js.map +1 -1
  72. package/dist/bin/run.js +4 -10
  73. package/dist/bin/run.js.map +1 -1
  74. package/dist/bin/upgrade.js +4 -3
  75. package/dist/bin/upgrade.js.map +1 -1
  76. package/dist/bin/workloadIdentity.d.ts +18 -0
  77. package/dist/bin/workloadIdentity.js +100 -0
  78. package/dist/bin/workloadIdentity.js.map +1 -0
  79. package/dist/components/Application.d.ts +235 -17
  80. package/dist/components/Application.js +3038 -238
  81. package/dist/components/Application.js.map +1 -1
  82. package/dist/components/ApplicationScope.d.ts +8 -0
  83. package/dist/components/ApplicationScope.js +7 -0
  84. package/dist/components/ApplicationScope.js.map +1 -1
  85. package/dist/components/EntryHandler.js +26 -10
  86. package/dist/components/EntryHandler.js.map +1 -1
  87. package/dist/components/OptionsWatcher.d.ts +4 -0
  88. package/dist/components/OptionsWatcher.js +440 -99
  89. package/dist/components/OptionsWatcher.js.map +1 -1
  90. package/dist/components/RuntimeModuleTracker.js +40 -6
  91. package/dist/components/RuntimeModuleTracker.js.map +1 -1
  92. package/dist/components/Scope.js +52 -13
  93. package/dist/components/Scope.js.map +1 -1
  94. package/dist/components/awaitRestart.d.ts +33 -0
  95. package/dist/components/awaitRestart.js +61 -0
  96. package/dist/components/awaitRestart.js.map +1 -0
  97. package/dist/components/componentLoader.d.ts +38 -1
  98. package/dist/components/componentLoader.js +313 -24
  99. package/dist/components/componentLoader.js.map +1 -1
  100. package/dist/components/componentPreparationLock.d.ts +5 -0
  101. package/dist/components/componentPreparationLock.js +14 -6
  102. package/dist/components/componentPreparationLock.js.map +1 -1
  103. package/dist/components/deploymentOperations.js +4 -1
  104. package/dist/components/deploymentOperations.js.map +1 -1
  105. package/dist/components/deploymentRecorder.d.ts +4 -2
  106. package/dist/components/deploymentRecorder.js +1 -0
  107. package/dist/components/deploymentRecorder.js.map +1 -1
  108. package/dist/components/mcp/adapters/harperHttp.js +4 -0
  109. package/dist/components/mcp/adapters/harperHttp.js.map +1 -1
  110. package/dist/components/mcp/listChanged.js +5 -0
  111. package/dist/components/mcp/listChanged.js.map +1 -1
  112. package/dist/components/mcp/toolRegistry.d.ts +1 -0
  113. package/dist/components/mcp/toolRegistry.js.map +1 -1
  114. package/dist/components/mcp/tools/operations.d.ts +5 -0
  115. package/dist/components/mcp/tools/operations.js +9 -0
  116. package/dist/components/mcp/tools/operations.js.map +1 -1
  117. package/dist/components/mcp/tools/schemas/operationDescriptions.js +2 -2
  118. package/dist/components/mcp/tools/schemas/operationDescriptions.js.map +1 -1
  119. package/dist/components/operations.d.ts +28 -0
  120. package/dist/components/operations.js +476 -113
  121. package/dist/components/operations.js.map +1 -1
  122. package/dist/components/operationsValidation.js +97 -3
  123. package/dist/components/operationsValidation.js.map +1 -1
  124. package/dist/components/packageComponent.js +24 -0
  125. package/dist/components/packageComponent.js.map +1 -1
  126. package/dist/components/requestRestart.d.ts +1 -0
  127. package/dist/components/requestRestart.js +7 -0
  128. package/dist/components/requestRestart.js.map +1 -1
  129. package/dist/components/status/ComponentStatusRegistry.d.ts +0 -4
  130. package/dist/components/status/ComponentStatusRegistry.js +63 -0
  131. package/dist/components/status/ComponentStatusRegistry.js.map +1 -1
  132. package/dist/config/RootConfigWatcher.d.ts +9 -1
  133. package/dist/config/RootConfigWatcher.js +228 -37
  134. package/dist/config/RootConfigWatcher.js.map +1 -1
  135. package/dist/config/configReadRetry.d.ts +8 -0
  136. package/dist/config/configReadRetry.js +62 -0
  137. package/dist/config/configReadRetry.js.map +1 -0
  138. package/dist/config/configUtils.d.ts +11 -2
  139. package/dist/config/configUtils.js +304 -47
  140. package/dist/config/configUtils.js.map +1 -1
  141. package/dist/config/harperConfigEnvVars.d.ts +16 -0
  142. package/dist/config/harperConfigEnvVars.js +162 -25
  143. package/dist/config/harperConfigEnvVars.js.map +1 -1
  144. package/dist/config/parseConfigFile.d.ts +4 -0
  145. package/dist/config/parseConfigFile.js +35 -0
  146. package/dist/config/parseConfigFile.js.map +1 -0
  147. package/dist/config/readConfigFileSync.d.ts +1 -0
  148. package/dist/config/readConfigFileSync.js +47 -0
  149. package/dist/config/readConfigFileSync.js.map +1 -0
  150. package/dist/config/watcherArming.d.ts +15 -0
  151. package/dist/config/watcherArming.js +59 -0
  152. package/dist/config/watcherArming.js.map +1 -0
  153. package/dist/dataLayer/blobBackup.d.ts +49 -20
  154. package/dist/dataLayer/blobBackup.js +139 -50
  155. package/dist/dataLayer/blobBackup.js.map +1 -1
  156. package/dist/dataLayer/delete.js +1 -1
  157. package/dist/dataLayer/delete.js.map +1 -1
  158. package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +14 -1
  159. package/dist/dataLayer/harperBridge/ResourceBridge.js +72 -12
  160. package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
  161. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.d.ts +3 -1
  162. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  163. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js.map +1 -1
  164. package/dist/dataLayer/hdbInfoController.d.ts +10 -0
  165. package/dist/dataLayer/hdbInfoController.js +30 -1
  166. package/dist/dataLayer/hdbInfoController.js.map +1 -1
  167. package/dist/dataLayer/insert.d.ts +9 -1
  168. package/dist/dataLayer/insert.js +30 -0
  169. package/dist/dataLayer/insert.js.map +1 -1
  170. package/dist/dataLayer/rocksdbBackup.d.ts +2 -2
  171. package/dist/dataLayer/rocksdbBackup.js +45 -8
  172. package/dist/dataLayer/rocksdbBackup.js.map +1 -1
  173. package/dist/dataLayer/schema.js +8 -0
  174. package/dist/dataLayer/schema.js.map +1 -1
  175. package/dist/dataLayer/schemaDescribe.js +8 -1
  176. package/dist/dataLayer/schemaDescribe.js.map +1 -1
  177. package/dist/index.d.ts +2 -1
  178. package/dist/index.js +4 -1
  179. package/dist/index.js.map +1 -1
  180. package/dist/json/systemSchema.json +55 -0
  181. package/dist/resources/DatabaseTransaction.d.ts +77 -0
  182. package/dist/resources/DatabaseTransaction.js +586 -54
  183. package/dist/resources/DatabaseTransaction.js.map +1 -1
  184. package/dist/resources/LMDBTransaction.d.ts +2 -1
  185. package/dist/resources/LMDBTransaction.js +43 -6
  186. package/dist/resources/LMDBTransaction.js.map +1 -1
  187. package/dist/resources/PrimaryRocksDatabase.d.ts +1 -0
  188. package/dist/resources/PrimaryRocksDatabase.js +49 -5
  189. package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
  190. package/dist/resources/RecordEncoder.d.ts +20 -0
  191. package/dist/resources/RecordEncoder.js +110 -9
  192. package/dist/resources/RecordEncoder.js.map +1 -1
  193. package/dist/resources/RequestTarget.d.ts +2 -0
  194. package/dist/resources/RequestTarget.js.map +1 -1
  195. package/dist/resources/Resource.js +117 -24
  196. package/dist/resources/Resource.js.map +1 -1
  197. package/dist/resources/ResourceInterface.d.ts +28 -1
  198. package/dist/resources/ResourceInterface.js.map +1 -1
  199. package/dist/resources/RocksIndexStore.d.ts +6 -1
  200. package/dist/resources/RocksIndexStore.js +24 -9
  201. package/dist/resources/RocksIndexStore.js.map +1 -1
  202. package/dist/resources/RocksTransactionLogStore.d.ts +24 -1
  203. package/dist/resources/RocksTransactionLogStore.js +160 -49
  204. package/dist/resources/RocksTransactionLogStore.js.map +1 -1
  205. package/dist/resources/Table.d.ts +165 -10
  206. package/dist/resources/Table.js +1805 -303
  207. package/dist/resources/Table.js.map +1 -1
  208. package/dist/resources/analytics/write.js +10 -3
  209. package/dist/resources/analytics/write.js.map +1 -1
  210. package/dist/resources/auditStore.d.ts +181 -2
  211. package/dist/resources/auditStore.js +640 -29
  212. package/dist/resources/auditStore.js.map +1 -1
  213. package/dist/resources/blob.d.ts +129 -9
  214. package/dist/resources/blob.js +992 -114
  215. package/dist/resources/blob.js.map +1 -1
  216. package/dist/resources/branchDatabase.d.ts +48 -0
  217. package/dist/resources/branchDatabase.js +892 -0
  218. package/dist/resources/branchDatabase.js.map +1 -0
  219. package/dist/resources/crdt.js +50 -12
  220. package/dist/resources/crdt.js.map +1 -1
  221. package/dist/resources/dataLoader.js +3 -4
  222. package/dist/resources/dataLoader.js.map +1 -1
  223. package/dist/resources/databases.d.ts +157 -14
  224. package/dist/resources/databases.js +1462 -325
  225. package/dist/resources/databases.js.map +1 -1
  226. package/dist/resources/defineTable.d.ts +10 -2
  227. package/dist/resources/defineTable.js +9 -1
  228. package/dist/resources/defineTable.js.map +1 -1
  229. package/dist/resources/derivedIndexRegistry.d.ts +5 -0
  230. package/dist/resources/derivedIndexRegistry.js +68 -0
  231. package/dist/resources/derivedIndexRegistry.js.map +1 -0
  232. package/dist/resources/derivedIndexRuntime.d.ts +215 -0
  233. package/dist/resources/derivedIndexRuntime.js +2027 -0
  234. package/dist/resources/derivedIndexRuntime.js.map +1 -0
  235. package/dist/resources/graphql.d.ts +1 -1
  236. package/dist/resources/graphql.js +52 -16
  237. package/dist/resources/graphql.js.map +1 -1
  238. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +103 -9
  239. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +854 -41
  240. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
  241. package/dist/resources/indexes/hnswDerivedIndex.d.ts +67 -0
  242. package/dist/resources/indexes/hnswDerivedIndex.js +464 -0
  243. package/dist/resources/indexes/hnswDerivedIndex.js.map +1 -0
  244. package/dist/resources/indexes/hnswPlaneBinding.d.ts +65 -0
  245. package/dist/resources/indexes/hnswPlaneBinding.js +91 -0
  246. package/dist/resources/indexes/hnswPlaneBinding.js.map +1 -0
  247. package/dist/resources/longLivedTransactions.d.ts +71 -0
  248. package/dist/resources/longLivedTransactions.js +358 -0
  249. package/dist/resources/longLivedTransactions.js.map +1 -0
  250. package/dist/resources/models/backendRegistry.d.ts +26 -0
  251. package/dist/resources/models/backendRegistry.js +60 -2
  252. package/dist/resources/models/backendRegistry.js.map +1 -1
  253. package/dist/resources/models/bootstrap.d.ts +33 -1
  254. package/dist/resources/models/bootstrap.js +416 -31
  255. package/dist/resources/models/bootstrap.js.map +1 -1
  256. package/dist/resources/nodeIdMapping.d.ts +5 -0
  257. package/dist/resources/nodeIdMapping.js +49 -0
  258. package/dist/resources/nodeIdMapping.js.map +1 -1
  259. package/dist/resources/recordLock.d.ts +123 -0
  260. package/dist/resources/recordLock.js +315 -0
  261. package/dist/resources/recordLock.js.map +1 -0
  262. package/dist/resources/recordLockCoordinator.d.ts +557 -0
  263. package/dist/resources/recordLockCoordinator.js +2565 -0
  264. package/dist/resources/recordLockCoordinator.js.map +1 -0
  265. package/dist/resources/replayLogs.d.ts +14 -1
  266. package/dist/resources/replayLogs.js +157 -24
  267. package/dist/resources/replayLogs.js.map +1 -1
  268. package/dist/resources/replayLogsGuards.d.ts +94 -7
  269. package/dist/resources/replayLogsGuards.js +111 -7
  270. package/dist/resources/replayLogsGuards.js.map +1 -1
  271. package/dist/resources/replicatedApplyFailure.d.ts +16 -0
  272. package/dist/resources/replicatedApplyFailure.js +63 -0
  273. package/dist/resources/replicatedApplyFailure.js.map +1 -0
  274. package/dist/resources/scheduler/scheduler.js +3 -3
  275. package/dist/resources/scheduler/scheduler.js.map +1 -1
  276. package/dist/resources/search.d.ts +10 -4
  277. package/dist/resources/search.js +283 -37
  278. package/dist/resources/search.js.map +1 -1
  279. package/dist/resources/tracked.d.ts +5 -1
  280. package/dist/resources/tracked.js +74 -23
  281. package/dist/resources/tracked.js.map +1 -1
  282. package/dist/resources/transactionBroadcast.d.ts +1 -1
  283. package/dist/resources/transactionBroadcast.js +2 -2
  284. package/dist/resources/transactionBroadcast.js.map +1 -1
  285. package/dist/security/auth.js +61 -30
  286. package/dist/security/auth.js.map +1 -1
  287. package/dist/security/authn/oidc/claims.d.ts +22 -0
  288. package/dist/security/authn/oidc/claims.js +71 -0
  289. package/dist/security/authn/oidc/claims.js.map +1 -0
  290. package/dist/security/authn/oidc/identityToken.d.ts +27 -0
  291. package/dist/security/authn/oidc/identityToken.js +111 -0
  292. package/dist/security/authn/oidc/identityToken.js.map +1 -0
  293. package/dist/security/authn/oidc/jwks.d.ts +25 -0
  294. package/dist/security/authn/oidc/jwks.js +261 -0
  295. package/dist/security/authn/oidc/jwks.js.map +1 -0
  296. package/dist/security/authn/oidc/providers/generic.d.ts +13 -0
  297. package/dist/security/authn/oidc/providers/generic.js +34 -0
  298. package/dist/security/authn/oidc/providers/generic.js.map +1 -0
  299. package/dist/security/authn/oidc/providers/githubActions.d.ts +11 -0
  300. package/dist/security/authn/oidc/providers/githubActions.js +129 -0
  301. package/dist/security/authn/oidc/providers/githubActions.js.map +1 -0
  302. package/dist/security/authn/oidc/providers/index.d.ts +37 -0
  303. package/dist/security/authn/oidc/providers/index.js +24 -0
  304. package/dist/security/authn/oidc/providers/index.js.map +1 -0
  305. package/dist/security/authn/oidc/tokenExchange.d.ts +12 -0
  306. package/dist/security/authn/oidc/tokenExchange.js +306 -0
  307. package/dist/security/authn/oidc/tokenExchange.js.map +1 -0
  308. package/dist/security/authn/oidc/trustPolicyOperations.d.ts +49 -0
  309. package/dist/security/authn/oidc/trustPolicyOperations.js +358 -0
  310. package/dist/security/authn/oidc/trustPolicyOperations.js.map +1 -0
  311. package/dist/security/authn/oidc/types.d.ts +38 -0
  312. package/dist/security/authn/oidc/types.js +6 -0
  313. package/dist/security/authn/oidc/types.js.map +1 -0
  314. package/dist/security/certificateVerification/index.js +40 -11
  315. package/dist/security/certificateVerification/index.js.map +1 -1
  316. package/dist/security/certificateVerification/trustedIssuers.d.ts +24 -0
  317. package/dist/security/certificateVerification/trustedIssuers.js +79 -0
  318. package/dist/security/certificateVerification/trustedIssuers.js.map +1 -0
  319. package/dist/security/certificateVerification/types.d.ts +1 -0
  320. package/dist/security/credentialProvenance.d.ts +35 -0
  321. package/dist/security/credentialProvenance.js +51 -0
  322. package/dist/security/credentialProvenance.js.map +1 -0
  323. package/dist/security/credentialRejection.d.ts +4 -0
  324. package/dist/security/credentialRejection.js +24 -0
  325. package/dist/security/credentialRejection.js.map +1 -0
  326. package/dist/security/deferredAuthentication.d.ts +36 -0
  327. package/dist/security/deferredAuthentication.js +70 -0
  328. package/dist/security/deferredAuthentication.js.map +1 -0
  329. package/dist/security/impersonation.d.ts +21 -0
  330. package/dist/security/impersonation.js +108 -9
  331. package/dist/security/impersonation.js.map +1 -1
  332. package/dist/security/jsLoader.d.ts +6 -0
  333. package/dist/security/jsLoader.js +77 -15
  334. package/dist/security/jsLoader.js.map +1 -1
  335. package/dist/security/keys.js +301 -71
  336. package/dist/security/keys.js.map +1 -1
  337. package/dist/security/operationScope.d.ts +21 -0
  338. package/dist/security/operationScope.js +36 -0
  339. package/dist/security/operationScope.js.map +1 -0
  340. package/dist/security/permissionsTranslator.js +21 -0
  341. package/dist/security/permissionsTranslator.js.map +1 -1
  342. package/dist/security/tokenAuthentication.d.ts +19 -1
  343. package/dist/security/tokenAuthentication.js +191 -10
  344. package/dist/security/tokenAuthentication.js.map +1 -1
  345. package/dist/security/user.js +4 -3
  346. package/dist/security/user.js.map +1 -1
  347. package/dist/server/DurableSubscriptionsSession.d.ts +2 -2
  348. package/dist/server/DurableSubscriptionsSession.js +67 -10
  349. package/dist/server/DurableSubscriptionsSession.js.map +1 -1
  350. package/dist/server/REST.js +106 -2
  351. package/dist/server/REST.js.map +1 -1
  352. package/dist/server/graphqlQuerying.js +4 -0
  353. package/dist/server/graphqlQuerying.js.map +1 -1
  354. package/dist/server/http.d.ts +16 -1
  355. package/dist/server/http.js +122 -17
  356. package/dist/server/http.js.map +1 -1
  357. package/dist/server/itc/serverHandlers.js +8 -1
  358. package/dist/server/itc/serverHandlers.js.map +1 -1
  359. package/dist/server/jobs/jobProcess.js +6 -2
  360. package/dist/server/jobs/jobProcess.js.map +1 -1
  361. package/dist/server/jobs/jobs.js +4 -1
  362. package/dist/server/jobs/jobs.js.map +1 -1
  363. package/dist/server/liveSubscriptionAuth.d.ts +26 -4
  364. package/dist/server/liveSubscriptionAuth.js +105 -39
  365. package/dist/server/liveSubscriptionAuth.js.map +1 -1
  366. package/dist/server/loadRootComponents.js +49 -10
  367. package/dist/server/loadRootComponents.js.map +1 -1
  368. package/dist/server/mqtt.d.ts +2 -0
  369. package/dist/server/mqtt.js +165 -30
  370. package/dist/server/mqtt.js.map +1 -1
  371. package/dist/server/nodeName.d.ts +2 -0
  372. package/dist/server/nodeName.js +107 -23
  373. package/dist/server/nodeName.js.map +1 -1
  374. package/dist/server/serverHelpers/Headers.d.ts +27 -0
  375. package/dist/server/serverHelpers/Headers.js +145 -1
  376. package/dist/server/serverHelpers/Headers.js.map +1 -1
  377. package/dist/server/serverHelpers/NodeAdapterResponse.d.ts +48 -0
  378. package/dist/server/serverHelpers/NodeAdapterResponse.js +220 -0
  379. package/dist/server/serverHelpers/NodeAdapterResponse.js.map +1 -0
  380. package/dist/server/serverHelpers/Request.d.ts +5 -10
  381. package/dist/server/serverHelpers/Request.js +38 -136
  382. package/dist/server/serverHelpers/Request.js.map +1 -1
  383. package/dist/server/serverHelpers/contentTypes.d.ts +11 -0
  384. package/dist/server/serverHelpers/contentTypes.js +221 -40
  385. package/dist/server/serverHelpers/contentTypes.js.map +1 -1
  386. package/dist/server/serverHelpers/deployValidationState.d.ts +3 -0
  387. package/dist/server/serverHelpers/deployValidationState.js +9 -19
  388. package/dist/server/serverHelpers/deployValidationState.js.map +1 -1
  389. package/dist/server/serverHelpers/operationAuthorizationState.d.ts +12 -0
  390. package/dist/server/serverHelpers/operationAuthorizationState.js +24 -2
  391. package/dist/server/serverHelpers/operationAuthorizationState.js.map +1 -1
  392. package/dist/server/serverHelpers/registeredOperations.d.ts +5 -4
  393. package/dist/server/serverHelpers/registeredOperations.js +74 -21
  394. package/dist/server/serverHelpers/registeredOperations.js.map +1 -1
  395. package/dist/server/serverHelpers/requestSanitization.d.ts +11 -0
  396. package/dist/server/serverHelpers/requestSanitization.js +20 -0
  397. package/dist/server/serverHelpers/requestSanitization.js.map +1 -0
  398. package/dist/server/serverHelpers/serverHandlers.js +6 -3
  399. package/dist/server/serverHelpers/serverHandlers.js.map +1 -1
  400. package/dist/server/serverHelpers/serverUtilities.d.ts +18 -0
  401. package/dist/server/serverHelpers/serverUtilities.js +178 -29
  402. package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
  403. package/dist/server/serverHelpers/sharedMessageEncoding.d.ts +67 -0
  404. package/dist/server/serverHelpers/sharedMessageEncoding.js +280 -0
  405. package/dist/server/serverHelpers/sharedMessageEncoding.js.map +1 -0
  406. package/dist/server/serverHelpers/uwsServer.js +19 -1
  407. package/dist/server/serverHelpers/uwsServer.js.map +1 -1
  408. package/dist/server/static.js +24 -28
  409. package/dist/server/static.js.map +1 -1
  410. package/dist/server/storageReclamation.d.ts +5 -0
  411. package/dist/server/storageReclamation.js +17 -1
  412. package/dist/server/storageReclamation.js.map +1 -1
  413. package/dist/server/threads/isolatedApplications.d.ts +47 -0
  414. package/dist/server/threads/isolatedApplications.js +171 -0
  415. package/dist/server/threads/isolatedApplications.js.map +1 -0
  416. package/dist/server/threads/itc.d.ts +7 -2
  417. package/dist/server/threads/itc.js +5 -1
  418. package/dist/server/threads/itc.js.map +1 -1
  419. package/dist/server/threads/logRotationTransport.d.ts +1 -0
  420. package/dist/server/threads/logRotationTransport.js +33 -0
  421. package/dist/server/threads/logRotationTransport.js.map +1 -0
  422. package/dist/server/threads/manageThreads.d.ts +83 -3
  423. package/dist/server/threads/manageThreads.js +769 -75
  424. package/dist/server/threads/manageThreads.js.map +1 -1
  425. package/dist/server/threads/socketRouter.d.ts +1 -0
  426. package/dist/server/threads/socketRouter.js +277 -31
  427. package/dist/server/threads/socketRouter.js.map +1 -1
  428. package/dist/server/threads/threadHeapMemory.d.ts +2 -0
  429. package/dist/server/threads/threadHeapMemory.js +31 -0
  430. package/dist/server/threads/threadHeapMemory.js.map +1 -0
  431. package/dist/server/threads/threadServer.js +76 -22
  432. package/dist/server/threads/threadServer.js.map +1 -1
  433. package/dist/sqlEngine/config.d.ts +1 -3
  434. package/dist/sqlEngine/config.js +19 -16
  435. package/dist/sqlEngine/config.js.map +1 -1
  436. package/dist/sqlTranslator/index.d.ts +1 -1
  437. package/dist/sqlTranslator/index.js +30 -7
  438. package/dist/sqlTranslator/index.js.map +1 -1
  439. package/dist/upgrade/directives/5-3-0.d.ts +7 -0
  440. package/dist/upgrade/directives/5-3-0.js +148 -0
  441. package/dist/upgrade/directives/5-3-0.js.map +1 -0
  442. package/dist/upgrade/directives/directivesController.js +2 -1
  443. package/dist/upgrade/directives/directivesController.js.map +1 -1
  444. package/dist/utility/OperationFunctionCaller.js +2 -1
  445. package/dist/utility/OperationFunctionCaller.js.map +1 -1
  446. package/dist/utility/common_utils.d.ts +16 -0
  447. package/dist/utility/common_utils.js +32 -6
  448. package/dist/utility/common_utils.js.map +1 -1
  449. package/dist/utility/componentNames.d.ts +8 -0
  450. package/dist/utility/componentNames.js +12 -1
  451. package/dist/utility/componentNames.js.map +1 -1
  452. package/dist/utility/environment/environmentManager.js +3 -6
  453. package/dist/utility/environment/environmentManager.js.map +1 -1
  454. package/dist/utility/environment/systemInformation.d.ts +1 -0
  455. package/dist/utility/environment/systemInformation.js +1 -0
  456. package/dist/utility/environment/systemInformation.js.map +1 -1
  457. package/dist/utility/errors/commonErrors.d.ts +2 -0
  458. package/dist/utility/errors/commonErrors.js +2 -0
  459. package/dist/utility/errors/commonErrors.js.map +1 -1
  460. package/dist/utility/errors/hdbError.d.ts +33 -0
  461. package/dist/utility/errors/hdbError.js +58 -1
  462. package/dist/utility/errors/hdbError.js.map +1 -1
  463. package/dist/utility/globalSchema.d.ts +18 -0
  464. package/dist/utility/hdbTerms.d.ts +18 -0
  465. package/dist/utility/hdbTerms.js +20 -2
  466. package/dist/utility/hdbTerms.js.map +1 -1
  467. package/dist/utility/logging/harper_logger.d.ts +2 -0
  468. package/dist/utility/logging/harper_logger.js +286 -30
  469. package/dist/utility/logging/harper_logger.js.map +1 -1
  470. package/dist/utility/logging/logGenerationCoordinator.d.ts +35 -0
  471. package/dist/utility/logging/logGenerationCoordinator.js +184 -0
  472. package/dist/utility/logging/logGenerationCoordinator.js.map +1 -0
  473. package/dist/utility/logging/logRotation.d.ts +46 -0
  474. package/dist/utility/logging/logRotation.js +365 -0
  475. package/dist/utility/logging/logRotation.js.map +1 -0
  476. package/dist/utility/logging/logRotator.d.ts +1 -1
  477. package/dist/utility/logging/logRotator.js +192 -85
  478. package/dist/utility/logging/logRotator.js.map +1 -1
  479. package/dist/utility/nodeIdentity.d.ts +9 -0
  480. package/dist/utility/nodeIdentity.js +58 -0
  481. package/dist/utility/nodeIdentity.js.map +1 -0
  482. package/dist/utility/npmUtilities.js +11 -7
  483. package/dist/utility/npmUtilities.js.map +1 -1
  484. package/dist/utility/operationPermissions.d.ts +3 -1
  485. package/dist/utility/operationPermissions.js +16 -1
  486. package/dist/utility/operationPermissions.js.map +1 -1
  487. package/dist/utility/operation_authorization.d.ts +10 -7
  488. package/dist/utility/operation_authorization.js +212 -41
  489. package/dist/utility/operation_authorization.js.map +1 -1
  490. package/dist/utility/watchPath.d.ts +29 -0
  491. package/dist/utility/watchPath.js +68 -0
  492. package/dist/utility/watchPath.js.map +1 -0
  493. package/dist/utility/watcherFallback.d.ts +41 -0
  494. package/dist/utility/watcherFallback.js +153 -0
  495. package/dist/utility/watcherFallback.js.map +1 -1
  496. package/dist/validation/configValidator.d.ts +12 -0
  497. package/dist/validation/configValidator.js +205 -75
  498. package/dist/validation/configValidator.js.map +1 -1
  499. package/dist/validation/installValidator.js +12 -0
  500. package/dist/validation/installValidator.js.map +1 -1
  501. package/dist/validation/validationWrapper.d.ts +11 -0
  502. package/dist/validation/validationWrapper.js +16 -3
  503. package/dist/validation/validationWrapper.js.map +1 -1
  504. package/index.ts +8 -0
  505. package/json/systemSchema.json +55 -0
  506. package/npm-shrinkwrap.json +286 -194
  507. package/package.json +15 -7
  508. package/resources/DESIGN.md +219 -52
  509. package/resources/DatabaseTransaction.ts +657 -52
  510. package/resources/LMDBTransaction.ts +46 -6
  511. package/resources/PrimaryRocksDatabase.ts +46 -7
  512. package/resources/RecordEncoder.ts +124 -9
  513. package/resources/RequestTarget.ts +2 -0
  514. package/resources/Resource.ts +114 -22
  515. package/resources/ResourceInterface.ts +31 -0
  516. package/resources/RocksIndexStore.ts +30 -9
  517. package/resources/RocksTransactionLogStore.ts +188 -51
  518. package/resources/Table.ts +1960 -301
  519. package/resources/analytics/write.ts +10 -3
  520. package/resources/auditStore.ts +647 -32
  521. package/resources/blob.ts +1029 -110
  522. package/resources/branchDatabase.ts +941 -0
  523. package/resources/crdt.ts +76 -12
  524. package/resources/dataLoader.ts +3 -4
  525. package/resources/databases.ts +1584 -320
  526. package/resources/defineTable.ts +18 -2
  527. package/resources/derivedIndexRegistry.ts +56 -0
  528. package/resources/derivedIndexRuntime.ts +2292 -0
  529. package/resources/graphql.ts +72 -17
  530. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +911 -48
  531. package/resources/indexes/hnswDerivedIndex.ts +531 -0
  532. package/resources/indexes/hnswPlaneBinding.ts +174 -0
  533. package/resources/longLivedTransactions.ts +360 -0
  534. package/resources/models/backendRegistry.ts +84 -2
  535. package/resources/models/bootstrap.ts +473 -28
  536. package/resources/nodeIdMapping.ts +50 -0
  537. package/resources/recordLock.ts +419 -0
  538. package/resources/recordLockCoordinator.ts +3043 -0
  539. package/resources/replayLogs.ts +152 -26
  540. package/resources/replayLogsGuards.ts +171 -8
  541. package/resources/replicatedApplyFailure.ts +77 -0
  542. package/resources/scheduler/scheduler.ts +4 -4
  543. package/resources/search.ts +288 -46
  544. package/resources/tracked.ts +73 -22
  545. package/resources/transactionBroadcast.ts +3 -3
  546. package/security/auth.ts +68 -29
  547. package/security/authn/oidc/claims.ts +72 -0
  548. package/security/authn/oidc/identityToken.ts +129 -0
  549. package/security/authn/oidc/jwks.ts +260 -0
  550. package/security/authn/oidc/providers/generic.ts +40 -0
  551. package/security/authn/oidc/providers/githubActions.ts +137 -0
  552. package/security/authn/oidc/providers/index.ts +52 -0
  553. package/security/authn/oidc/tokenExchange.ts +300 -0
  554. package/security/authn/oidc/trustPolicyOperations.ts +343 -0
  555. package/security/authn/oidc/types.ts +41 -0
  556. package/security/certificateVerification/index.ts +54 -13
  557. package/security/certificateVerification/trustedIssuers.ts +76 -0
  558. package/security/certificateVerification/types.ts +1 -0
  559. package/security/credentialProvenance.ts +47 -0
  560. package/security/credentialRejection.ts +22 -0
  561. package/security/deferredAuthentication.ts +71 -0
  562. package/security/impersonation.ts +117 -12
  563. package/security/jsLoader.ts +83 -18
  564. package/security/keys.ts +298 -72
  565. package/security/operationScope.ts +33 -0
  566. package/security/permissionsTranslator.js +23 -0
  567. package/security/tokenAuthentication.ts +233 -12
  568. package/security/user.ts +4 -3
  569. package/server/DESIGN.md +194 -16
  570. package/server/DurableSubscriptionsSession.ts +71 -11
  571. package/server/REST.ts +115 -4
  572. package/server/graphqlQuerying.ts +4 -0
  573. package/server/http.ts +133 -20
  574. package/server/itc/serverHandlers.js +8 -1
  575. package/server/jobs/jobProcess.ts +8 -2
  576. package/server/jobs/jobs.ts +4 -1
  577. package/server/liveSubscriptionAuth.ts +129 -46
  578. package/server/loadRootComponents.js +50 -8
  579. package/server/mqtt.ts +179 -38
  580. package/server/nodeName.ts +103 -21
  581. package/server/serverHelpers/Headers.ts +135 -0
  582. package/server/serverHelpers/NodeAdapterResponse.ts +221 -0
  583. package/server/serverHelpers/Request.ts +33 -131
  584. package/server/serverHelpers/contentTypes.ts +217 -36
  585. package/server/serverHelpers/deployValidationState.ts +24 -13
  586. package/server/serverHelpers/operationAuthorizationState.ts +34 -3
  587. package/server/serverHelpers/registeredOperations.ts +79 -22
  588. package/server/serverHelpers/requestSanitization.ts +15 -0
  589. package/server/serverHelpers/serverHandlers.js +6 -3
  590. package/server/serverHelpers/serverUtilities.ts +232 -40
  591. package/server/serverHelpers/sharedMessageEncoding.ts +307 -0
  592. package/server/serverHelpers/uwsServer.ts +17 -2
  593. package/server/static.ts +23 -29
  594. package/server/storageReclamation.ts +15 -2
  595. package/server/threads/isolatedApplications.ts +157 -0
  596. package/server/threads/itc.js +11 -1
  597. package/server/threads/logRotationTransport.ts +40 -0
  598. package/server/threads/manageThreads.js +771 -66
  599. package/server/threads/socketRouter.ts +291 -30
  600. package/server/threads/threadHeapMemory.ts +26 -0
  601. package/server/threads/threadServer.js +73 -22
  602. package/sqlTranslator/index.ts +31 -8
  603. package/studio/web/assets/{Chat-4RrB5134.js → Chat-D3j-1yY1.js} +1 -1
  604. package/studio/web/assets/{FloatingChat-omlNMDcJ.js → FloatingChat-BxJGYcfB.js} +3 -3
  605. package/studio/web/assets/{apiToken-Bke3wvfZ.js → apiToken-CT55oWOe.js} +1 -1
  606. package/studio/web/assets/{applications-DvFDYJgK.js → applications-D9Ct9_vm.js} +1 -1
  607. package/studio/web/assets/{cssMode-C1vRa7zh.js → cssMode-DV8H7VwA.js} +1 -1
  608. package/studio/web/assets/{editor-3XRWEDWX.js → editor-uatc0unt.js} +1 -1
  609. package/studio/web/assets/{html-CTY5tdMr.js → html-Bm6D6paN.js} +1 -1
  610. package/studio/web/assets/{htmlMode-CG1vSD9t.js → htmlMode-CEn7tpLG.js} +1 -1
  611. package/studio/web/assets/{index-Dfpeofdu.js → index-BIXW6Pu4.js} +5 -5
  612. package/studio/web/assets/{index.lazy-B1VOIv-t.js → index.lazy-UI7L-Vrk.js} +1 -1
  613. package/studio/web/assets/{javascript-CJeJzGnI.js → javascript-CJ0G3AFZ.js} +1 -1
  614. package/studio/web/assets/{jsonMode-CYPBwM82.js → jsonMode-DQADAYEa.js} +1 -1
  615. package/studio/web/assets/{languageServices-IKH4GUHl.js → languageServices-CAQJXWcI.js} +1 -1
  616. package/studio/web/assets/{lspLanguageFeatures-BC8_gxKG.js → lspLanguageFeatures-CCQ8P5sY.js} +1 -1
  617. package/studio/web/assets/{notifications-BfKBpYcq.js → notifications-BbxTU6Aw.js} +1 -1
  618. package/studio/web/assets/{notifications-DFbArTfC.js → notifications-Cvb3P1lB.js} +1 -1
  619. package/studio/web/assets/{profile-Q4-T6c-S.js → profile-Yyb7gsvL.js} +1 -1
  620. package/studio/web/assets/{regions-CtkV0xje.js → regions-OgjGHlU5.js} +1 -1
  621. package/studio/web/assets/{register-1ZZuMsiA.js → register-6qwNEOY3.js} +2 -2
  622. package/studio/web/assets/{setComponentFile-ZWLcWv5X.js → setComponentFile-BilDMtgB.js} +1 -1
  623. package/studio/web/assets/{setup-DWprJyJy.js → setup-J6qJ7OIU.js} +2 -2
  624. package/studio/web/assets/{status--aNm8isn.js → status-0RWGcfyD.js} +1 -1
  625. package/studio/web/assets/{toggleHighContrast-Cq_lt3XD.js → toggleHighContrast-BIn-vErT.js} +1 -1
  626. package/studio/web/assets/{tsMode-pjgytARx.js → tsMode-DgUXku4d.js} +1 -1
  627. package/studio/web/assets/{typescript-Cdg0mqUh.js → typescript-C9orXcsM.js} +1 -1
  628. package/studio/web/assets/{useEntityRestURL-RZhaY8Rn.js → useEntityRestURL-BEoXXbUB.js} +1 -1
  629. package/studio/web/assets/{workers-BgoXIqQe.js → workers-JVzSDmgx.js} +1 -1
  630. package/studio/web/assets/{xml-BwSeDMiP.js → xml-Cq-S8S4X.js} +1 -1
  631. package/studio/web/assets/{yaml-DotCUG5l.js → yaml-sfoRdh1M.js} +1 -1
  632. package/studio/web/index.html +1 -1
  633. package/upgrade/directives/5-3-0.ts +132 -0
  634. package/upgrade/directives/directivesController.ts +2 -1
  635. package/utility/OperationFunctionCaller.ts +2 -1
  636. package/utility/common_utils.ts +30 -5
  637. package/utility/componentNames.ts +12 -0
  638. package/utility/environment/environmentManager.ts +3 -7
  639. package/utility/environment/systemInformation.ts +7 -0
  640. package/utility/errors/commonErrors.ts +4 -0
  641. package/utility/errors/hdbError.ts +57 -0
  642. package/utility/hdbTerms.ts +19 -0
  643. package/utility/logging/harper_logger.ts +278 -26
  644. package/utility/logging/logGenerationCoordinator.ts +196 -0
  645. package/utility/logging/logRotation.ts +367 -0
  646. package/utility/logging/logRotator.ts +213 -81
  647. package/utility/nodeIdentity.ts +45 -0
  648. package/utility/npmUtilities.ts +12 -8
  649. package/utility/operationPermissions.ts +18 -1
  650. package/utility/operation_authorization.ts +231 -42
  651. package/utility/watchPath.ts +63 -0
  652. package/utility/watcherFallback.ts +148 -0
  653. package/validation/configValidator.ts +215 -75
  654. package/validation/installValidator.ts +15 -0
  655. package/validation/validationWrapper.ts +18 -4
@@ -0,0 +1,419 @@
1
+ import { performance } from 'node:perf_hooks';
2
+ import harperLogger from '../utility/logging/harper_logger.ts';
3
+ import { ClientError } from '../utility/errors/hdbError.ts';
4
+
5
+ /**
6
+ * Exclusive per-record locks (harper#483).
7
+ *
8
+ * The intra-node authority is the rocksdb-js process-wide key lock: one `locks` map per DBDescriptor
9
+ * shared by every worker thread's handle. Acquiring and releasing it write nothing to the store, and
10
+ * the record's version and bytes are unchanged.
11
+ *
12
+ * Phase 1 layers cluster-wide exclusion on top without changing that: once the native key is held,
13
+ * `Table.lock()` obtains a delegation for the key from its home node (see `recordLockCoordinator.ts`)
14
+ * and calls `joinClusterRound()` on the handle. A live delegation serves repeat locks with no cluster
15
+ * message at all. A node-scoped lock (`{ scope: 'node' }`), or any lock on a database with no
16
+ * transport registered, skips the cluster step entirely and behaves exactly as it did in Phase 0.
17
+ */
18
+
19
+ export const DEFAULT_LOCK_LEASE_MS = 30_000;
20
+ /** Below this a generation can expire before the caller's work completes, handing back a lock already lost. */
21
+ export const MIN_LOCK_LEASE_MS = 100;
22
+ export const MAX_LOCK_LEASE_MS = 300_000;
23
+ export const DEFAULT_LOCK_TIMEOUT_MS = 30_000;
24
+ export const MAX_LOCK_TIMEOUT_MS = 300_000;
25
+ const LOCK_KEY_PREFIX = Symbol.for('record-lock');
26
+
27
+ export interface RecordLockOptions {
28
+ /** Lease in ms; the lock expires on its own if the holder never releases it (default 30 s, max 5 min) */
29
+ lease?: number;
30
+ /** How long to wait for a contended lock in ms before failing with 423 (default 30 s, max 5 min) */
31
+ timeout?: number;
32
+ /** A held lock outlives the acquiring transaction; it is released by `unlock()` or by its lease */
33
+ hold?: boolean;
34
+ /**
35
+ * `'cluster'` (default) is exclusive across every participating node; `'node'` keeps Phase 0
36
+ * semantics and is exclusive only across this node's worker threads.
37
+ */
38
+ scope?: 'cluster' | 'node';
39
+ }
40
+
41
+ export interface ResolvedRecordLockOptions {
42
+ lease: number;
43
+ timeout: number;
44
+ hold: boolean;
45
+ scope: 'cluster' | 'node';
46
+ /** True when the caller named `scope` explicitly, which makes `'cluster'` fail-closed. */
47
+ scopeRequested: boolean;
48
+ }
49
+
50
+ /**
51
+ * The handle returned by `lock()` and held by each gated write until its transaction completes.
52
+ * `release()` is synchronous: it calls `store.unlock(key)` which is ownerless and fires any
53
+ * waiting callbacks cross-thread. The `expired` flag is set in the holder thread by the lease
54
+ * timer, so a stale holder cannot accidentally call unlock after its lease already fired and
55
+ * released the key to a new holder.
56
+ */
57
+ export interface RecordLockHandle {
58
+ store: any;
59
+ key: any[]; // lockAttemptKey, passed to store.tryLock / store.unlock
60
+ keyId: unknown; // writeKeyId(id), used to scan the per-transaction recordLocks array
61
+ expiresAt: number;
62
+ hold: boolean;
63
+ released: boolean;
64
+ expired: boolean;
65
+ /** Monotonic timestamp at which tryLock succeeded; used as the base version for holder writes. */
66
+ acquiredAt: number;
67
+ /** Advance, but never lower, the version floor from the transaction that owns the actual write timestamp. */
68
+ noteHolderVersion(version: number): void;
69
+ /** Preserve a caller timestamp as a candidate floor without treating it as a committed write. */
70
+ noteCandidateFloor(version: number): void;
71
+ /** Compute a holder-write version without advancing the floor until that write commits. */
72
+ holderVersionCandidate(floor?: number): number;
73
+ /** `ts_R` of the granted cluster round; undefined while the hold is node-scoped (Phase 0). */
74
+ clusterTsR?: number;
75
+ /**
76
+ * Whether this handle may still authorize a write, evaluated NOW rather than trusting the lease
77
+ * timer to have run. A holder whose event loop stalled past its deadline would otherwise commit
78
+ * between the deadline and its own timer callback, while peers had already expired the hold.
79
+ * Expiry is detected on a monotonic clock, so a wall-clock jump cannot extend a lease.
80
+ */
81
+ isExpired(): boolean;
82
+ /**
83
+ * Whether the LEASE elapsed. Distinct from `isExpired()` in that a deliberate release does NOT
84
+ * make it true on its own: a write staged while the lock was held stays valid at commit if the
85
+ * caller merely unlocked. Once the deadline passes it is true either way, because by then peers
86
+ * have passed their own bound and the key may already belong to someone else.
87
+ */
88
+ isLeaseExpired(): boolean;
89
+ /** Revoke authority ahead of the lease, so a staged-but-uncommitted write is fenced at commit. */
90
+ revokeLease(): void;
91
+ /**
92
+ * Re-anchor a granted cluster round: the hold now runs from `tsR` (no margin, so this node
93
+ * always expires before any participant does) and `onRelease` emits the durable LOCK_RELEASE.
94
+ * Returns false when the round completed after the lease had already elapsed.
95
+ *
96
+ * `mintedMono` is `performance.now()` at the instant `tsR` was minted. The remaining lease is
97
+ * measured from it rather than from `tsR - Date.now()`: `tsR` comes from a never-decreasing
98
+ * monotonic source, so after a backward wall-clock step that subtraction would hand back MORE
99
+ * lease than the round was granted, past what every peer bounded from its own observation.
100
+ */
101
+ joinClusterRound(tsR: number, leaseMs: number, mintedMono: number, onRelease: () => void): boolean;
102
+ /**
103
+ * Return the next version to stamp a holder write with. Starts at acquiredAt when no transaction
104
+ * version has been noted; otherwise advances by the minimum monotonic step from the recorded floor.
105
+ */
106
+ nextHolderVersion(): number;
107
+ release(): boolean;
108
+ /**
109
+ * Flip this handle to hold mode and reset its lease timer. Used during scoped→hold upgrades
110
+ * so all instances that reference this handle object remain valid (no retire + replace).
111
+ */
112
+ upgradeToHold(lease: number): void;
113
+ }
114
+
115
+ function requireDuration(name: string, value: unknown, fallback: number, min: number, max: number): number {
116
+ if (value === undefined) return fallback;
117
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < min)
118
+ throw new ClientError(
119
+ `Lock option ${name} must be a number of milliseconds of at least ${min}, but received ${value}`
120
+ );
121
+ if (value > max) throw new ClientError(`Lock option ${name} must not exceed ${max}ms, but received ${value}`);
122
+ return value;
123
+ }
124
+
125
+ export function resolveLockOptions(options?: RecordLockOptions | null): ResolvedRecordLockOptions {
126
+ if (options != null && typeof options !== 'object')
127
+ throw new ClientError(`Lock options must be an object, but received ${typeof options}`);
128
+ const hold = options?.hold ?? false;
129
+ if (typeof hold !== 'boolean') throw new ClientError(`Lock option hold must be a boolean, but received ${hold}`);
130
+ const scope = options?.scope ?? 'cluster';
131
+ if (scope !== 'cluster' && scope !== 'node')
132
+ throw new ClientError(`Lock option scope must be 'cluster' or 'node', but received ${scope}`);
133
+ return {
134
+ lease: requireDuration('lease', options?.lease, DEFAULT_LOCK_LEASE_MS, MIN_LOCK_LEASE_MS, MAX_LOCK_LEASE_MS),
135
+ timeout: requireDuration('timeout', options?.timeout, DEFAULT_LOCK_TIMEOUT_MS, 1, MAX_LOCK_TIMEOUT_MS),
136
+ hold,
137
+ scope,
138
+ scopeRequested: options?.scope !== undefined,
139
+ };
140
+ }
141
+
142
+ /**
143
+ * The 409 for a write staged through a handle that is no longer live. A lease that ran out and a
144
+ * lock that was handed back are different causes, and a caller told the wrong one debugs the wrong
145
+ * thing — a commit-released scoped handle is not a timeout.
146
+ */
147
+ export function lockNotHeldError(handle: Pick<RecordLockHandle, 'expired'>): ClientError {
148
+ return new ClientError(handle.expired ? 'Record lock lease expired' : 'Record lock already released', 409);
149
+ }
150
+
151
+ /** The advisory key for this (table, record) pair, distinct from getFromSource's bare-id single-flight lock. */
152
+ export function lockAttemptKey(tableId: number, id: any): any[] {
153
+ return Array.isArray(id) ? [LOCK_KEY_PREFIX, tableId, ...id] : [LOCK_KEY_PREFIX, tableId, id];
154
+ }
155
+
156
+ const warnedLeaseTimerStores = new WeakSet();
157
+ /**
158
+ * Rate-limited rather than latched, for the reason `warnOnce` in the coordinator gives: a release
159
+ * that cannot be written leaves peers waiting out the lease, and a latch would show an operator the
160
+ * first occurrence and then hide the condition for as long as it lasts.
161
+ */
162
+ const CLUSTER_RELEASE_WARN_INTERVAL_MS = 60_000;
163
+ let lastClusterReleaseWarn = -Infinity;
164
+ function warnClusterReleaseFailure(err: unknown) {
165
+ const now = performance.now();
166
+ if (now - lastClusterReleaseWarn < CLUSTER_RELEASE_WARN_INTERVAL_MS) return;
167
+ lastClusterReleaseWarn = now;
168
+ harperLogger.warn?.('cluster record lock release could not be written; peers will expire the hold', err);
169
+ }
170
+
171
+ class KeyLockHandle implements RecordLockHandle {
172
+ store: any;
173
+ key: any[];
174
+ keyId: unknown;
175
+ expiresAt: number;
176
+ hold: boolean;
177
+ released = false;
178
+ expired = false;
179
+ acquiredAt: number;
180
+ clusterTsR: number | undefined;
181
+ #lastHolderVersion: number | undefined;
182
+ #candidateFloor: number | undefined;
183
+ #timer: ReturnType<typeof setTimeout> | undefined;
184
+ // Monotonic mirror of expiresAt. The wall-clock field stays public (callers and the cluster
185
+ // protocol both speak in timestamps) but the enforcement compares monotonic readings, so neither
186
+ // an NTP step nor a manual clock change can extend a lease past what peers assumed.
187
+ #deadlineMono: number | undefined;
188
+ #onRelease: (() => void) | undefined;
189
+
190
+ constructor(store: any, key: any[], keyId: unknown, lease?: number, hold = false, acquiredAt?: number) {
191
+ this.store = store;
192
+ this.key = key;
193
+ this.keyId = keyId;
194
+ this.expiresAt = lease != null ? Date.now() + lease : Infinity;
195
+ this.hold = hold;
196
+ this.acquiredAt = acquiredAt ?? store.getMonotonicTimestamp();
197
+ if (lease != null) {
198
+ this.#deadlineMono = performance.now() + lease;
199
+ this.#timer = setTimeout(() => this.#onLeaseExpire(), lease).unref();
200
+ }
201
+ }
202
+
203
+ noteHolderVersion(version: number): void {
204
+ this.#lastHolderVersion = Math.max(this.#lastHolderVersion ?? version, version);
205
+ }
206
+
207
+ noteCandidateFloor(version: number): void {
208
+ this.#candidateFloor = Math.max(this.#candidateFloor ?? version, version);
209
+ }
210
+
211
+ holderVersionCandidate(floor?: number): number {
212
+ // A small nonzero step prevents exact LWW ties without materially moving past the observed floor.
213
+ const MIN_STEP = 0.000488;
214
+ return Math.max(
215
+ this.#lastHolderVersion != null ? this.#lastHolderVersion + MIN_STEP : this.acquiredAt,
216
+ this.acquiredAt,
217
+ this.#candidateFloor ?? -Infinity,
218
+ floor ?? -Infinity
219
+ );
220
+ }
221
+
222
+ isExpired(): boolean {
223
+ return this.released || this.expired || this.#leaseLapsed();
224
+ }
225
+
226
+ isLeaseExpired(): boolean {
227
+ return this.expired || this.#leaseLapsed();
228
+ }
229
+
230
+ // The single place the deadline is evaluated, so the two predicates cannot disagree about it. A
231
+ // deliberate release does not make a lapsed lease valid again: by then peers have passed their own
232
+ // bound and the key may belong to someone else.
233
+ #leaseLapsed(): boolean {
234
+ if (this.#deadlineMono === undefined || performance.now() < this.#deadlineMono) return false;
235
+ // Finish the expiry rather than only reporting it: the native key must actually go back so a
236
+ // stalled holder does not keep a key every participant has already written off.
237
+ if (!this.released) this.#onLeaseExpire();
238
+ return true;
239
+ }
240
+
241
+ /**
242
+ * Revoke this handle's authority immediately, ahead of its lease. A recall must stop a delegate
243
+ * from COMMITTING, not merely from admitting: a caller that already staged a write and then called
244
+ * `unlock()` has nothing outstanding for a drain to wait on, but its write is still in the
245
+ * transaction and would land after the successor was admitted. Expiring the handle is what makes
246
+ * the commit-time fence reject it (§6).
247
+ */
248
+ revokeLease(): void {
249
+ if (this.expired) return;
250
+ // `expired` is what the commit-time fence reads, and it must be set even when the caller has
251
+ // ALREADY unlocked: a write staged before `unlock()` is still in its transaction, and that is
252
+ // precisely the handoff §6 exists to fence. Gating this on `released` made the revocation a
253
+ // no-op in the one state it was written for.
254
+ this.expired = true;
255
+ if (this.released) {
256
+ // The native key is already back and `onRelease` already fired; only the fence flag and the
257
+ // lease timer are left to settle.
258
+ clearTimeout(this.#timer);
259
+ return;
260
+ }
261
+ this.#onLeaseExpire();
262
+ }
263
+
264
+ joinClusterRound(tsR: number, leaseMs: number, mintedMono: number, onRelease: () => void): boolean {
265
+ // A round that completed after the native lease already fired yields no usable hold: the key
266
+ // has gone back and another worker may hold it, so every write through this handle would 409.
267
+ if (this.isLeaseExpired()) return false;
268
+ const remaining = leaseMs - (performance.now() - mintedMono);
269
+ if (remaining <= 0) return false;
270
+ this.clusterTsR = tsR;
271
+ this.acquiredAt = tsR;
272
+ this.#lastHolderVersion = undefined;
273
+ this.#onRelease = onRelease;
274
+ this.expiresAt = tsR + leaseMs;
275
+ // From the mint origin, not a second clock read: the design says this bound has no margin.
276
+ this.#deadlineMono = mintedMono + leaseMs;
277
+ clearTimeout(this.#timer);
278
+ this.#timer = setTimeout(() => this.#onLeaseExpire(), remaining).unref();
279
+ return true;
280
+ }
281
+
282
+ nextHolderVersion(): number {
283
+ // TODO(harper#2412): under the settled dual-clock model the lock-ordered stamp belongs in the
284
+ // distinct-version second word (HAS_DISTINCT_VERSION_FLAG), not the transaction timestamp.
285
+ // Until that lands, Phase 1 keeps this Phase 0 mechanism, anchored at ts_R in cluster mode.
286
+ const next = this.holderVersionCandidate();
287
+ this.#lastHolderVersion = next;
288
+ return next;
289
+ }
290
+
291
+ #onLeaseExpire() {
292
+ if (this.released) return;
293
+ this.released = true;
294
+ this.expired = true;
295
+ clearTimeout(this.#timer);
296
+ try {
297
+ this.store.unlock(this.key);
298
+ } catch (err) {
299
+ if (!warnedLeaseTimerStores.has(this.store)) {
300
+ warnedLeaseTimerStores.add(this.store);
301
+ harperLogger.warn?.('record lock lease timer failed (store may have been dropped)', err);
302
+ }
303
+ }
304
+ this.#emitRelease();
305
+ }
306
+
307
+ // The cluster release is a durability optimization, not the safety mechanism — peers expire the
308
+ // hold on their own lease bound — so neither a throw nor a rejected promise may escape here. This
309
+ // runs from a lease timer and from post-commit cleanup, where an escaping rejection would take
310
+ // down the worker or turn a committed transaction into a 500.
311
+ #emitRelease() {
312
+ const onRelease = this.#onRelease;
313
+ if (!onRelease) return;
314
+ this.#onRelease = undefined;
315
+ try {
316
+ const result = onRelease() as unknown;
317
+ if (result && typeof (result as Promise<void>).then === 'function')
318
+ (result as Promise<void>).then(undefined, warnClusterReleaseFailure);
319
+ } catch (err) {
320
+ warnClusterReleaseFailure(err);
321
+ }
322
+ }
323
+
324
+ release(): boolean {
325
+ if (this.released) return false;
326
+ this.released = true;
327
+ clearTimeout(this.#timer);
328
+ try {
329
+ this.store.unlock(this.key);
330
+ } catch (err) {
331
+ if (!warnedLeaseTimerStores.has(this.store)) {
332
+ warnedLeaseTimerStores.add(this.store);
333
+ harperLogger.warn?.('record lock release failed (store may have been dropped)', err);
334
+ }
335
+ }
336
+ this.#emitRelease();
337
+ return true;
338
+ }
339
+
340
+ upgradeToHold(lease: number): void {
341
+ this.hold = true;
342
+ clearTimeout(this.#timer);
343
+ // A granted cluster round may not be extended locally: peers bound the hold from the request
344
+ // they saw, and a longer local lease is exactly the two-holder window this protocol removes.
345
+ // Clamped on the monotonic deadline, not on expiresAt, so a backward wall-clock step cannot
346
+ // turn the upgrade into the extension this is here to refuse.
347
+ const now = performance.now();
348
+ const extended = now + lease;
349
+ const deadline = this.clusterTsR === undefined ? extended : Math.min(extended, this.#deadlineMono ?? extended);
350
+ const remaining = deadline - now;
351
+ this.#deadlineMono = deadline;
352
+ this.expiresAt = Date.now() + remaining;
353
+ this.#timer = setTimeout(() => this.#onLeaseExpire(), remaining).unref();
354
+ // Prime the nextHolderVersion counter so a later CLOSED-path save (e.g. after the
355
+ // enclosing transaction commits) gets acquiredAt+MIN_STEP rather than acquiredAt again
356
+ // — the same priming the fresh-hold path performs. Without this, a post-commit save
357
+ // and any in-transaction save both get acquiredAt, causing a LWW tie that drops the write.
358
+ this.nextHolderVersion();
359
+ }
360
+ }
361
+
362
+ export function makeKeyLockHandle(
363
+ store: any,
364
+ key: any[],
365
+ keyId: unknown,
366
+ lease?: number,
367
+ hold = false,
368
+ acquiredAt?: number
369
+ ): RecordLockHandle {
370
+ return new KeyLockHandle(store, key, keyId, lease, hold, acquiredAt);
371
+ }
372
+
373
+ /**
374
+ * Acquire the native key lock for a record, looping until acquired or deadline passes. Re-entrant
375
+ * within a transaction: if the transaction already holds this key (non-expired handle in its
376
+ * recordLocks map) the existing handle is returned without a second tryLock.
377
+ */
378
+ export async function acquireRecordKey(
379
+ txn: { recordLockFor(store: any, keyId: unknown): RecordLockHandle | undefined },
380
+ store: any,
381
+ key: any[],
382
+ keyId: unknown,
383
+ waitMs: number,
384
+ lease?: number,
385
+ hold = false
386
+ ): Promise<RecordLockHandle> {
387
+ const existing = txn.recordLockFor(store, keyId);
388
+ if (existing && !existing.isExpired()) return existing;
389
+
390
+ const deadline = Date.now() + waitMs;
391
+ // One persistent wake slot: at most one onUnlocked callback is registered per waiter at any
392
+ // time. After the callback fires (holder released), hasCallback is cleared so the next
393
+ // tryLock can register a fresh callback for the new holder. When the timeout fires instead
394
+ // (the holder has not released yet), hasCallback stays true and subsequent retries skip the
395
+ // callback registration, preventing unbounded accumulation on a hot key.
396
+ let wakeResolve: (() => void) | undefined;
397
+ let hasCallback = false;
398
+ while (true) {
399
+ const onUnlocked = hasCallback
400
+ ? undefined
401
+ : () => {
402
+ hasCallback = false;
403
+ wakeResolve?.();
404
+ };
405
+ const acquired = store.tryLock(key, onUnlocked);
406
+ if (acquired) return makeKeyLockHandle(store, key, keyId, lease, hold, store.getMonotonicTimestamp());
407
+ if (onUnlocked) hasCallback = true; // callback now registered; do not register another until it fires
408
+ const remaining = deadline - Date.now();
409
+ if (remaining <= 0) throw new ClientError(`Record is locked and was not released in time`, 423);
410
+ await new Promise<void>((resolve) => {
411
+ const t = setTimeout(resolve, remaining).unref();
412
+ wakeResolve = () => {
413
+ clearTimeout(t);
414
+ resolve();
415
+ };
416
+ });
417
+ wakeResolve = undefined;
418
+ }
419
+ }