@harperfast/harper 5.2.10 → 5.3.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (554) hide show
  1. package/agent/mcpTools.ts +1 -1
  2. package/agent/session.ts +25 -14
  3. package/bin/cliOperations.ts +46 -9
  4. package/bin/copyDb.ts +282 -59
  5. package/bin/deploySetup.ts +16 -5
  6. package/bin/harper.ts +1 -1
  7. package/bin/help.ts +4 -1
  8. package/bin/lite.ts +4 -1
  9. package/bin/restart.ts +59 -3
  10. package/bin/run.ts +6 -11
  11. package/bin/upgrade.js +7 -3
  12. package/bin/workloadIdentity.ts +119 -0
  13. package/components/Application.ts +2414 -242
  14. package/components/ApplicationScope.ts +8 -0
  15. package/components/EntryHandler.ts +59 -39
  16. package/components/OptionsWatcher.ts +150 -74
  17. package/components/RuntimeModuleTracker.ts +38 -7
  18. package/components/Scope.ts +37 -15
  19. package/components/awaitRestart.ts +84 -0
  20. package/components/componentLoader.ts +340 -30
  21. package/components/componentPreparationLock.ts +16 -5
  22. package/components/mcp/adapters/harperHttp.ts +4 -0
  23. package/components/mcp/listChanged.ts +4 -0
  24. package/components/mcp/toolRegistry.ts +2 -0
  25. package/components/mcp/tools/operations.ts +9 -0
  26. package/components/mcp/tools/schemas/operationDescriptions.ts +2 -2
  27. package/components/operations.js +270 -78
  28. package/components/operationsValidation.js +49 -1
  29. package/components/status/ComponentStatusRegistry.ts +59 -0
  30. package/config/RootConfigWatcher.ts +80 -34
  31. package/config/configUtils.ts +291 -34
  32. package/config/harperConfigEnvVars.ts +170 -27
  33. package/config-root.schema.json +29 -0
  34. package/dataLayer/blobBackup.ts +160 -50
  35. package/dataLayer/delete.ts +6 -1
  36. package/dataLayer/harperBridge/ResourceBridge.ts +52 -8
  37. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  38. package/dataLayer/hdbInfoController.ts +34 -1
  39. package/dataLayer/insert.ts +44 -1
  40. package/dataLayer/rocksdbBackup.ts +53 -10
  41. package/dataLayer/schema.ts +11 -1
  42. package/dataLayer/schemaDescribe.ts +8 -1
  43. package/dist/agent/mcpTools.js +1 -1
  44. package/dist/agent/mcpTools.js.map +1 -1
  45. package/dist/agent/session.d.ts +22 -0
  46. package/dist/agent/session.js +26 -15
  47. package/dist/agent/session.js.map +1 -1
  48. package/dist/bin/cliOperations.js +48 -9
  49. package/dist/bin/cliOperations.js.map +1 -1
  50. package/dist/bin/copyDb.d.ts +12 -1
  51. package/dist/bin/copyDb.js +248 -60
  52. package/dist/bin/copyDb.js.map +1 -1
  53. package/dist/bin/deploySetup.d.ts +2 -0
  54. package/dist/bin/deploySetup.js +11 -3
  55. package/dist/bin/deploySetup.js.map +1 -1
  56. package/dist/bin/harper.js +1 -1
  57. package/dist/bin/harper.js.map +1 -1
  58. package/dist/bin/help.js +4 -1
  59. package/dist/bin/help.js.map +1 -1
  60. package/dist/bin/lite.js +4 -1
  61. package/dist/bin/lite.js.map +1 -1
  62. package/dist/bin/restart.js +54 -5
  63. package/dist/bin/restart.js.map +1 -1
  64. package/dist/bin/run.js +4 -10
  65. package/dist/bin/run.js.map +1 -1
  66. package/dist/bin/upgrade.js +4 -3
  67. package/dist/bin/upgrade.js.map +1 -1
  68. package/dist/bin/workloadIdentity.d.ts +18 -0
  69. package/dist/bin/workloadIdentity.js +100 -0
  70. package/dist/bin/workloadIdentity.js.map +1 -0
  71. package/dist/components/Application.d.ts +139 -16
  72. package/dist/components/Application.js +2215 -267
  73. package/dist/components/Application.js.map +1 -1
  74. package/dist/components/ApplicationScope.d.ts +8 -0
  75. package/dist/components/ApplicationScope.js +7 -0
  76. package/dist/components/ApplicationScope.js.map +1 -1
  77. package/dist/components/EntryHandler.js +26 -10
  78. package/dist/components/EntryHandler.js.map +1 -1
  79. package/dist/components/OptionsWatcher.d.ts +1 -0
  80. package/dist/components/OptionsWatcher.js +141 -74
  81. package/dist/components/OptionsWatcher.js.map +1 -1
  82. package/dist/components/RuntimeModuleTracker.js +40 -6
  83. package/dist/components/RuntimeModuleTracker.js.map +1 -1
  84. package/dist/components/Scope.js +38 -13
  85. package/dist/components/Scope.js.map +1 -1
  86. package/dist/components/awaitRestart.d.ts +33 -0
  87. package/dist/components/awaitRestart.js +61 -0
  88. package/dist/components/awaitRestart.js.map +1 -0
  89. package/dist/components/componentLoader.d.ts +38 -1
  90. package/dist/components/componentLoader.js +279 -22
  91. package/dist/components/componentLoader.js.map +1 -1
  92. package/dist/components/componentPreparationLock.d.ts +5 -0
  93. package/dist/components/componentPreparationLock.js +14 -6
  94. package/dist/components/componentPreparationLock.js.map +1 -1
  95. package/dist/components/mcp/adapters/harperHttp.js +4 -0
  96. package/dist/components/mcp/adapters/harperHttp.js.map +1 -1
  97. package/dist/components/mcp/listChanged.js +5 -0
  98. package/dist/components/mcp/listChanged.js.map +1 -1
  99. package/dist/components/mcp/toolRegistry.d.ts +1 -0
  100. package/dist/components/mcp/toolRegistry.js.map +1 -1
  101. package/dist/components/mcp/tools/operations.d.ts +5 -0
  102. package/dist/components/mcp/tools/operations.js +9 -0
  103. package/dist/components/mcp/tools/operations.js.map +1 -1
  104. package/dist/components/mcp/tools/schemas/operationDescriptions.js +2 -2
  105. package/dist/components/mcp/tools/schemas/operationDescriptions.js.map +1 -1
  106. package/dist/components/operations.js +231 -77
  107. package/dist/components/operations.js.map +1 -1
  108. package/dist/components/operationsValidation.js +49 -1
  109. package/dist/components/operationsValidation.js.map +1 -1
  110. package/dist/components/status/ComponentStatusRegistry.d.ts +0 -4
  111. package/dist/components/status/ComponentStatusRegistry.js +63 -0
  112. package/dist/components/status/ComponentStatusRegistry.js.map +1 -1
  113. package/dist/config/RootConfigWatcher.d.ts +7 -1
  114. package/dist/config/RootConfigWatcher.js +64 -27
  115. package/dist/config/RootConfigWatcher.js.map +1 -1
  116. package/dist/config/configUtils.d.ts +9 -1
  117. package/dist/config/configUtils.js +254 -33
  118. package/dist/config/configUtils.js.map +1 -1
  119. package/dist/config/harperConfigEnvVars.d.ts +16 -0
  120. package/dist/config/harperConfigEnvVars.js +162 -25
  121. package/dist/config/harperConfigEnvVars.js.map +1 -1
  122. package/dist/dataLayer/blobBackup.d.ts +49 -20
  123. package/dist/dataLayer/blobBackup.js +139 -50
  124. package/dist/dataLayer/blobBackup.js.map +1 -1
  125. package/dist/dataLayer/delete.js +1 -1
  126. package/dist/dataLayer/delete.js.map +1 -1
  127. package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +14 -1
  128. package/dist/dataLayer/harperBridge/ResourceBridge.js +51 -10
  129. package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
  130. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.d.ts +3 -1
  131. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  132. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js.map +1 -1
  133. package/dist/dataLayer/hdbInfoController.d.ts +10 -0
  134. package/dist/dataLayer/hdbInfoController.js +30 -1
  135. package/dist/dataLayer/hdbInfoController.js.map +1 -1
  136. package/dist/dataLayer/insert.d.ts +9 -1
  137. package/dist/dataLayer/insert.js +30 -0
  138. package/dist/dataLayer/insert.js.map +1 -1
  139. package/dist/dataLayer/rocksdbBackup.d.ts +2 -2
  140. package/dist/dataLayer/rocksdbBackup.js +45 -8
  141. package/dist/dataLayer/rocksdbBackup.js.map +1 -1
  142. package/dist/dataLayer/schema.js +8 -0
  143. package/dist/dataLayer/schema.js.map +1 -1
  144. package/dist/dataLayer/schemaDescribe.js +8 -1
  145. package/dist/dataLayer/schemaDescribe.js.map +1 -1
  146. package/dist/index.d.ts +1 -1
  147. package/dist/index.js.map +1 -1
  148. package/dist/json/systemSchema.json +52 -0
  149. package/dist/resources/DatabaseTransaction.d.ts +55 -3
  150. package/dist/resources/DatabaseTransaction.js +460 -134
  151. package/dist/resources/DatabaseTransaction.js.map +1 -1
  152. package/dist/resources/LMDBTransaction.js +22 -4
  153. package/dist/resources/LMDBTransaction.js.map +1 -1
  154. package/dist/resources/PrimaryRocksDatabase.d.ts +1 -0
  155. package/dist/resources/PrimaryRocksDatabase.js +30 -2
  156. package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
  157. package/dist/resources/RecordEncoder.d.ts +20 -0
  158. package/dist/resources/RecordEncoder.js +94 -9
  159. package/dist/resources/RecordEncoder.js.map +1 -1
  160. package/dist/resources/RequestTarget.d.ts +2 -0
  161. package/dist/resources/RequestTarget.js.map +1 -1
  162. package/dist/resources/Resource.js +20 -11
  163. package/dist/resources/Resource.js.map +1 -1
  164. package/dist/resources/ResourceInterface.d.ts +20 -1
  165. package/dist/resources/ResourceInterface.js.map +1 -1
  166. package/dist/resources/RocksIndexStore.d.ts +6 -1
  167. package/dist/resources/RocksIndexStore.js +24 -10
  168. package/dist/resources/RocksIndexStore.js.map +1 -1
  169. package/dist/resources/RocksTransactionLogStore.d.ts +14 -1
  170. package/dist/resources/RocksTransactionLogStore.js +57 -17
  171. package/dist/resources/RocksTransactionLogStore.js.map +1 -1
  172. package/dist/resources/Table.d.ts +112 -8
  173. package/dist/resources/Table.js +1071 -197
  174. package/dist/resources/Table.js.map +1 -1
  175. package/dist/resources/auditStore.d.ts +11 -2
  176. package/dist/resources/auditStore.js +183 -18
  177. package/dist/resources/auditStore.js.map +1 -1
  178. package/dist/resources/blob.d.ts +129 -9
  179. package/dist/resources/blob.js +992 -114
  180. package/dist/resources/blob.js.map +1 -1
  181. package/dist/resources/branchDatabase.d.ts +48 -0
  182. package/dist/resources/branchDatabase.js +892 -0
  183. package/dist/resources/branchDatabase.js.map +1 -0
  184. package/dist/resources/crdt.js +50 -12
  185. package/dist/resources/crdt.js.map +1 -1
  186. package/dist/resources/databases.d.ts +150 -9
  187. package/dist/resources/databases.js +1247 -525
  188. package/dist/resources/databases.js.map +1 -1
  189. package/dist/resources/defineTable.d.ts +10 -2
  190. package/dist/resources/defineTable.js +9 -1
  191. package/dist/resources/defineTable.js.map +1 -1
  192. package/dist/resources/graphql.d.ts +1 -1
  193. package/dist/resources/graphql.js +50 -15
  194. package/dist/resources/graphql.js.map +1 -1
  195. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +1 -0
  196. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +6 -2
  197. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
  198. package/dist/resources/longLivedTransactions.d.ts +71 -0
  199. package/dist/resources/longLivedTransactions.js +358 -0
  200. package/dist/resources/longLivedTransactions.js.map +1 -0
  201. package/dist/resources/models/backendRegistry.d.ts +26 -0
  202. package/dist/resources/models/backendRegistry.js +60 -2
  203. package/dist/resources/models/backendRegistry.js.map +1 -1
  204. package/dist/resources/models/bootstrap.d.ts +33 -1
  205. package/dist/resources/models/bootstrap.js +416 -31
  206. package/dist/resources/models/bootstrap.js.map +1 -1
  207. package/dist/resources/recordLock.d.ts +80 -0
  208. package/dist/resources/recordLock.js +184 -0
  209. package/dist/resources/recordLock.js.map +1 -0
  210. package/dist/resources/replayLogs.d.ts +14 -1
  211. package/dist/resources/replayLogs.js +152 -24
  212. package/dist/resources/replayLogs.js.map +1 -1
  213. package/dist/resources/replayLogsGuards.d.ts +94 -7
  214. package/dist/resources/replayLogsGuards.js +111 -7
  215. package/dist/resources/replayLogsGuards.js.map +1 -1
  216. package/dist/resources/search.js +158 -32
  217. package/dist/resources/search.js.map +1 -1
  218. package/dist/resources/transactionBroadcast.d.ts +1 -1
  219. package/dist/resources/transactionBroadcast.js +2 -2
  220. package/dist/resources/transactionBroadcast.js.map +1 -1
  221. package/dist/security/auth.js +61 -30
  222. package/dist/security/auth.js.map +1 -1
  223. package/dist/security/authn/oidc/claims.d.ts +22 -0
  224. package/dist/security/authn/oidc/claims.js +71 -0
  225. package/dist/security/authn/oidc/claims.js.map +1 -0
  226. package/dist/security/authn/oidc/identityToken.d.ts +27 -0
  227. package/dist/security/authn/oidc/identityToken.js +111 -0
  228. package/dist/security/authn/oidc/identityToken.js.map +1 -0
  229. package/dist/security/authn/oidc/jwks.d.ts +25 -0
  230. package/dist/security/authn/oidc/jwks.js +261 -0
  231. package/dist/security/authn/oidc/jwks.js.map +1 -0
  232. package/dist/security/authn/oidc/providers/generic.d.ts +13 -0
  233. package/dist/security/authn/oidc/providers/generic.js +34 -0
  234. package/dist/security/authn/oidc/providers/generic.js.map +1 -0
  235. package/dist/security/authn/oidc/providers/githubActions.d.ts +11 -0
  236. package/dist/security/authn/oidc/providers/githubActions.js +129 -0
  237. package/dist/security/authn/oidc/providers/githubActions.js.map +1 -0
  238. package/dist/security/authn/oidc/providers/index.d.ts +37 -0
  239. package/dist/security/authn/oidc/providers/index.js +24 -0
  240. package/dist/security/authn/oidc/providers/index.js.map +1 -0
  241. package/dist/security/authn/oidc/tokenExchange.d.ts +12 -0
  242. package/dist/security/authn/oidc/tokenExchange.js +306 -0
  243. package/dist/security/authn/oidc/tokenExchange.js.map +1 -0
  244. package/dist/security/authn/oidc/trustPolicyOperations.d.ts +49 -0
  245. package/dist/security/authn/oidc/trustPolicyOperations.js +358 -0
  246. package/dist/security/authn/oidc/trustPolicyOperations.js.map +1 -0
  247. package/dist/security/authn/oidc/types.d.ts +38 -0
  248. package/dist/security/authn/oidc/types.js +6 -0
  249. package/dist/security/authn/oidc/types.js.map +1 -0
  250. package/dist/security/certificateVerification/index.js +40 -11
  251. package/dist/security/certificateVerification/index.js.map +1 -1
  252. package/dist/security/certificateVerification/trustedIssuers.d.ts +24 -0
  253. package/dist/security/certificateVerification/trustedIssuers.js +79 -0
  254. package/dist/security/certificateVerification/trustedIssuers.js.map +1 -0
  255. package/dist/security/certificateVerification/types.d.ts +1 -0
  256. package/dist/security/credentialProvenance.d.ts +35 -0
  257. package/dist/security/credentialProvenance.js +51 -0
  258. package/dist/security/credentialProvenance.js.map +1 -0
  259. package/dist/security/credentialRejection.d.ts +4 -0
  260. package/dist/security/credentialRejection.js +24 -0
  261. package/dist/security/credentialRejection.js.map +1 -0
  262. package/dist/security/deferredAuthentication.d.ts +36 -0
  263. package/dist/security/deferredAuthentication.js +70 -0
  264. package/dist/security/deferredAuthentication.js.map +1 -0
  265. package/dist/security/impersonation.d.ts +21 -0
  266. package/dist/security/impersonation.js +108 -9
  267. package/dist/security/impersonation.js.map +1 -1
  268. package/dist/security/jsLoader.d.ts +6 -0
  269. package/dist/security/jsLoader.js +75 -15
  270. package/dist/security/jsLoader.js.map +1 -1
  271. package/dist/security/keys.js +301 -71
  272. package/dist/security/keys.js.map +1 -1
  273. package/dist/security/operationScope.d.ts +21 -0
  274. package/dist/security/operationScope.js +36 -0
  275. package/dist/security/operationScope.js.map +1 -0
  276. package/dist/security/permissionsTranslator.js +21 -0
  277. package/dist/security/permissionsTranslator.js.map +1 -1
  278. package/dist/security/tokenAuthentication.d.ts +19 -1
  279. package/dist/security/tokenAuthentication.js +191 -10
  280. package/dist/security/tokenAuthentication.js.map +1 -1
  281. package/dist/security/user.js +4 -3
  282. package/dist/security/user.js.map +1 -1
  283. package/dist/server/DurableSubscriptionsSession.d.ts +2 -2
  284. package/dist/server/DurableSubscriptionsSession.js +67 -10
  285. package/dist/server/DurableSubscriptionsSession.js.map +1 -1
  286. package/dist/server/REST.js +73 -0
  287. package/dist/server/REST.js.map +1 -1
  288. package/dist/server/graphqlQuerying.js +4 -0
  289. package/dist/server/graphqlQuerying.js.map +1 -1
  290. package/dist/server/http.d.ts +11 -0
  291. package/dist/server/http.js +88 -15
  292. package/dist/server/http.js.map +1 -1
  293. package/dist/server/itc/serverHandlers.js +8 -1
  294. package/dist/server/itc/serverHandlers.js.map +1 -1
  295. package/dist/server/jobs/jobProcess.js +6 -2
  296. package/dist/server/jobs/jobProcess.js.map +1 -1
  297. package/dist/server/jobs/jobs.js +4 -1
  298. package/dist/server/jobs/jobs.js.map +1 -1
  299. package/dist/server/liveSubscriptionAuth.d.ts +26 -4
  300. package/dist/server/liveSubscriptionAuth.js +105 -39
  301. package/dist/server/liveSubscriptionAuth.js.map +1 -1
  302. package/dist/server/loadRootComponents.js +49 -10
  303. package/dist/server/loadRootComponents.js.map +1 -1
  304. package/dist/server/mqtt.d.ts +2 -0
  305. package/dist/server/mqtt.js +165 -30
  306. package/dist/server/mqtt.js.map +1 -1
  307. package/dist/server/nodeName.d.ts +2 -0
  308. package/dist/server/nodeName.js +107 -23
  309. package/dist/server/nodeName.js.map +1 -1
  310. package/dist/server/serverHelpers/Headers.d.ts +25 -0
  311. package/dist/server/serverHelpers/Headers.js +139 -1
  312. package/dist/server/serverHelpers/Headers.js.map +1 -1
  313. package/dist/server/serverHelpers/contentTypes.d.ts +9 -0
  314. package/dist/server/serverHelpers/contentTypes.js +32 -25
  315. package/dist/server/serverHelpers/contentTypes.js.map +1 -1
  316. package/dist/server/serverHelpers/deployValidationState.d.ts +3 -0
  317. package/dist/server/serverHelpers/deployValidationState.js +9 -19
  318. package/dist/server/serverHelpers/deployValidationState.js.map +1 -1
  319. package/dist/server/serverHelpers/operationAuthorizationState.d.ts +12 -0
  320. package/dist/server/serverHelpers/operationAuthorizationState.js +24 -2
  321. package/dist/server/serverHelpers/operationAuthorizationState.js.map +1 -1
  322. package/dist/server/serverHelpers/registeredOperations.d.ts +5 -4
  323. package/dist/server/serverHelpers/registeredOperations.js +74 -21
  324. package/dist/server/serverHelpers/registeredOperations.js.map +1 -1
  325. package/dist/server/serverHelpers/requestSanitization.d.ts +11 -0
  326. package/dist/server/serverHelpers/requestSanitization.js +20 -0
  327. package/dist/server/serverHelpers/requestSanitization.js.map +1 -0
  328. package/dist/server/serverHelpers/serverHandlers.js +6 -3
  329. package/dist/server/serverHelpers/serverHandlers.js.map +1 -1
  330. package/dist/server/serverHelpers/serverUtilities.d.ts +18 -0
  331. package/dist/server/serverHelpers/serverUtilities.js +90 -20
  332. package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
  333. package/dist/server/serverHelpers/sharedMessageEncoding.d.ts +67 -0
  334. package/dist/server/serverHelpers/sharedMessageEncoding.js +280 -0
  335. package/dist/server/serverHelpers/sharedMessageEncoding.js.map +1 -0
  336. package/dist/server/serverHelpers/uwsServer.js +19 -1
  337. package/dist/server/serverHelpers/uwsServer.js.map +1 -1
  338. package/dist/server/static.js +24 -28
  339. package/dist/server/static.js.map +1 -1
  340. package/dist/server/storageReclamation.d.ts +5 -0
  341. package/dist/server/storageReclamation.js +16 -0
  342. package/dist/server/storageReclamation.js.map +1 -1
  343. package/dist/server/threads/itc.d.ts +7 -2
  344. package/dist/server/threads/itc.js +5 -1
  345. package/dist/server/threads/itc.js.map +1 -1
  346. package/dist/server/threads/manageThreads.d.ts +26 -4
  347. package/dist/server/threads/manageThreads.js +517 -72
  348. package/dist/server/threads/manageThreads.js.map +1 -1
  349. package/dist/server/threads/socketRouter.js +89 -26
  350. package/dist/server/threads/socketRouter.js.map +1 -1
  351. package/dist/server/threads/threadHeapMemory.d.ts +2 -0
  352. package/dist/server/threads/threadHeapMemory.js +31 -0
  353. package/dist/server/threads/threadHeapMemory.js.map +1 -0
  354. package/dist/server/threads/threadServer.js +46 -15
  355. package/dist/server/threads/threadServer.js.map +1 -1
  356. package/dist/sqlEngine/config.d.ts +1 -3
  357. package/dist/sqlEngine/config.js +19 -16
  358. package/dist/sqlEngine/config.js.map +1 -1
  359. package/dist/sqlTranslator/index.d.ts +1 -1
  360. package/dist/sqlTranslator/index.js +30 -7
  361. package/dist/sqlTranslator/index.js.map +1 -1
  362. package/dist/upgrade/directives/5-3-0.d.ts +7 -0
  363. package/dist/upgrade/directives/5-3-0.js +148 -0
  364. package/dist/upgrade/directives/5-3-0.js.map +1 -0
  365. package/dist/upgrade/directives/directivesController.js +2 -1
  366. package/dist/upgrade/directives/directivesController.js.map +1 -1
  367. package/dist/utility/OperationFunctionCaller.js +2 -1
  368. package/dist/utility/OperationFunctionCaller.js.map +1 -1
  369. package/dist/utility/common_utils.d.ts +16 -0
  370. package/dist/utility/common_utils.js +32 -6
  371. package/dist/utility/common_utils.js.map +1 -1
  372. package/dist/utility/componentNames.d.ts +8 -0
  373. package/dist/utility/componentNames.js +12 -1
  374. package/dist/utility/componentNames.js.map +1 -1
  375. package/dist/utility/environment/environmentManager.js +3 -6
  376. package/dist/utility/environment/environmentManager.js.map +1 -1
  377. package/dist/utility/environment/systemInformation.d.ts +1 -0
  378. package/dist/utility/environment/systemInformation.js +1 -0
  379. package/dist/utility/environment/systemInformation.js.map +1 -1
  380. package/dist/utility/errors/commonErrors.d.ts +2 -0
  381. package/dist/utility/errors/commonErrors.js +2 -0
  382. package/dist/utility/errors/commonErrors.js.map +1 -1
  383. package/dist/utility/errors/hdbError.d.ts +17 -0
  384. package/dist/utility/errors/hdbError.js +30 -1
  385. package/dist/utility/errors/hdbError.js.map +1 -1
  386. package/dist/utility/globalSchema.d.ts +18 -0
  387. package/dist/utility/hdbTerms.d.ts +16 -0
  388. package/dist/utility/hdbTerms.js +18 -2
  389. package/dist/utility/hdbTerms.js.map +1 -1
  390. package/dist/utility/logging/harper_logger.d.ts +2 -0
  391. package/dist/utility/logging/harper_logger.js +91 -14
  392. package/dist/utility/logging/harper_logger.js.map +1 -1
  393. package/dist/utility/logging/logRotator.js +76 -49
  394. package/dist/utility/logging/logRotator.js.map +1 -1
  395. package/dist/utility/nodeIdentity.d.ts +9 -0
  396. package/dist/utility/nodeIdentity.js +58 -0
  397. package/dist/utility/nodeIdentity.js.map +1 -0
  398. package/dist/utility/npmUtilities.js +9 -7
  399. package/dist/utility/npmUtilities.js.map +1 -1
  400. package/dist/utility/operationPermissions.d.ts +3 -1
  401. package/dist/utility/operationPermissions.js +16 -1
  402. package/dist/utility/operationPermissions.js.map +1 -1
  403. package/dist/utility/operation_authorization.d.ts +10 -7
  404. package/dist/utility/operation_authorization.js +212 -41
  405. package/dist/utility/operation_authorization.js.map +1 -1
  406. package/dist/utility/watchPath.d.ts +29 -0
  407. package/dist/utility/watchPath.js +68 -0
  408. package/dist/utility/watchPath.js.map +1 -0
  409. package/dist/utility/watcherFallback.d.ts +86 -0
  410. package/dist/utility/watcherFallback.js +278 -1
  411. package/dist/utility/watcherFallback.js.map +1 -1
  412. package/dist/validation/configValidator.d.ts +12 -0
  413. package/dist/validation/configValidator.js +199 -72
  414. package/dist/validation/configValidator.js.map +1 -1
  415. package/dist/validation/installValidator.js +12 -0
  416. package/dist/validation/installValidator.js.map +1 -1
  417. package/dist/validation/validationWrapper.d.ts +11 -0
  418. package/dist/validation/validationWrapper.js +16 -3
  419. package/dist/validation/validationWrapper.js.map +1 -1
  420. package/index.ts +2 -0
  421. package/json/systemSchema.json +52 -0
  422. package/npm-shrinkwrap.json +235 -233
  423. package/package.json +8 -7
  424. package/resources/DESIGN.md +114 -52
  425. package/resources/DatabaseTransaction.ts +522 -130
  426. package/resources/LMDBTransaction.ts +26 -4
  427. package/resources/PrimaryRocksDatabase.ts +29 -3
  428. package/resources/RecordEncoder.ts +103 -8
  429. package/resources/RequestTarget.ts +2 -0
  430. package/resources/Resource.ts +17 -9
  431. package/resources/ResourceInterface.ts +23 -0
  432. package/resources/RocksIndexStore.ts +30 -10
  433. package/resources/RocksTransactionLogStore.ts +78 -21
  434. package/resources/Table.ts +1107 -164
  435. package/resources/auditStore.ts +187 -21
  436. package/resources/blob.ts +1029 -110
  437. package/resources/branchDatabase.ts +941 -0
  438. package/resources/crdt.ts +76 -12
  439. package/resources/databases.ts +1354 -522
  440. package/resources/defineTable.ts +18 -2
  441. package/resources/graphql.ts +70 -16
  442. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +6 -2
  443. package/resources/longLivedTransactions.ts +360 -0
  444. package/resources/models/backendRegistry.ts +84 -2
  445. package/resources/models/bootstrap.ts +473 -28
  446. package/resources/recordLock.ts +253 -0
  447. package/resources/replayLogs.ts +147 -26
  448. package/resources/replayLogsGuards.ts +171 -8
  449. package/resources/search.ts +154 -32
  450. package/resources/transactionBroadcast.ts +3 -3
  451. package/security/auth.ts +68 -29
  452. package/security/authn/oidc/claims.ts +72 -0
  453. package/security/authn/oidc/identityToken.ts +129 -0
  454. package/security/authn/oidc/jwks.ts +260 -0
  455. package/security/authn/oidc/providers/generic.ts +40 -0
  456. package/security/authn/oidc/providers/githubActions.ts +137 -0
  457. package/security/authn/oidc/providers/index.ts +52 -0
  458. package/security/authn/oidc/tokenExchange.ts +300 -0
  459. package/security/authn/oidc/trustPolicyOperations.ts +343 -0
  460. package/security/authn/oidc/types.ts +41 -0
  461. package/security/certificateVerification/index.ts +54 -13
  462. package/security/certificateVerification/trustedIssuers.ts +76 -0
  463. package/security/certificateVerification/types.ts +1 -0
  464. package/security/credentialProvenance.ts +47 -0
  465. package/security/credentialRejection.ts +22 -0
  466. package/security/deferredAuthentication.ts +71 -0
  467. package/security/impersonation.ts +117 -12
  468. package/security/jsLoader.ts +81 -18
  469. package/security/keys.ts +298 -72
  470. package/security/operationScope.ts +33 -0
  471. package/security/permissionsTranslator.js +23 -0
  472. package/security/tokenAuthentication.ts +233 -12
  473. package/security/user.ts +4 -3
  474. package/server/DESIGN.md +183 -16
  475. package/server/DurableSubscriptionsSession.ts +71 -11
  476. package/server/REST.ts +79 -1
  477. package/server/graphqlQuerying.ts +4 -0
  478. package/server/http.ts +99 -18
  479. package/server/itc/serverHandlers.js +8 -1
  480. package/server/jobs/jobProcess.ts +8 -2
  481. package/server/jobs/jobs.ts +4 -1
  482. package/server/liveSubscriptionAuth.ts +129 -46
  483. package/server/loadRootComponents.js +50 -8
  484. package/server/mqtt.ts +179 -38
  485. package/server/nodeName.ts +103 -21
  486. package/server/serverHelpers/Headers.ts +131 -0
  487. package/server/serverHelpers/contentTypes.ts +29 -21
  488. package/server/serverHelpers/deployValidationState.ts +24 -13
  489. package/server/serverHelpers/operationAuthorizationState.ts +34 -3
  490. package/server/serverHelpers/registeredOperations.ts +79 -22
  491. package/server/serverHelpers/requestSanitization.ts +15 -0
  492. package/server/serverHelpers/serverHandlers.js +6 -3
  493. package/server/serverHelpers/serverUtilities.ts +104 -31
  494. package/server/serverHelpers/sharedMessageEncoding.ts +307 -0
  495. package/server/serverHelpers/uwsServer.ts +17 -2
  496. package/server/static.ts +23 -29
  497. package/server/storageReclamation.ts +13 -0
  498. package/server/threads/itc.js +11 -1
  499. package/server/threads/manageThreads.js +526 -63
  500. package/server/threads/socketRouter.ts +81 -26
  501. package/server/threads/threadHeapMemory.ts +26 -0
  502. package/server/threads/threadServer.js +43 -15
  503. package/sqlTranslator/index.ts +31 -8
  504. package/studio/web/assets/{Chat-Br06zdMA.js → Chat-BnCBegQz.js} +1 -1
  505. package/studio/web/assets/{FloatingChat-BWImX5fA.js → FloatingChat-CoDW1ySS.js} +3 -3
  506. package/studio/web/assets/{apiToken-DN0nmDsq.js → apiToken-Bwk5BLXW.js} +1 -1
  507. package/studio/web/assets/{applications-kSxVoyeU.js → applications-DHxGi7JH.js} +1 -1
  508. package/studio/web/assets/{cssMode-C1JeufH5.js → cssMode-s0cWI-_M.js} +1 -1
  509. package/studio/web/assets/{editor-qoo9CrGO.js → editor-DNcRHK54.js} +1 -1
  510. package/studio/web/assets/{html-Dt4IIy04.js → html-Bdssedlg.js} +1 -1
  511. package/studio/web/assets/{htmlMode-DXgKKr4C.js → htmlMode-CoDlJ3fw.js} +1 -1
  512. package/studio/web/assets/{index-6onkYFOG.js → index-D6sxmFLR.js} +5 -5
  513. package/studio/web/assets/{index.lazy-BrCFnpNJ.js → index.lazy-tmU5BS8s.js} +1 -1
  514. package/studio/web/assets/{javascript-DNCQGUBc.js → javascript-B8meVSTH.js} +1 -1
  515. package/studio/web/assets/{jsonMode-CR6HWruP.js → jsonMode-DpIPd35T.js} +1 -1
  516. package/studio/web/assets/{languageServices-BM4fI4rS.js → languageServices-C_5FMJzQ.js} +1 -1
  517. package/studio/web/assets/{lspLanguageFeatures-DSa1ttcD.js → lspLanguageFeatures-BIzNBzPK.js} +1 -1
  518. package/studio/web/assets/{notifications-BHXLnh6x.js → notifications-CQf18QKb.js} +1 -1
  519. package/studio/web/assets/{notifications-CUmtIA6z.js → notifications-CvZivSbh.js} +1 -1
  520. package/studio/web/assets/{profile-8BeFSF3j.js → profile-DdOwtntb.js} +1 -1
  521. package/studio/web/assets/{regions-C8qR0HhD.js → regions-n69fwagr.js} +1 -1
  522. package/studio/web/assets/{register-B4n5i0SD.js → register-PfWTCXWB.js} +2 -2
  523. package/studio/web/assets/{setComponentFile-g0_B0lgX.js → setComponentFile-Bg6O7X0S.js} +1 -1
  524. package/studio/web/assets/{setup-B0CTj_Q5.js → setup-CUx_aUDl.js} +2 -2
  525. package/studio/web/assets/{status-C6Yib7-K.js → status-D7BVKqX9.js} +1 -1
  526. package/studio/web/assets/{toggleHighContrast-Dgta7bVi.js → toggleHighContrast-DBSyXzMr.js} +1 -1
  527. package/studio/web/assets/{tsMode-CH_jHvU-.js → tsMode-BByKCjBS.js} +1 -1
  528. package/studio/web/assets/{typescript-Co9LCXd5.js → typescript-DDLnLpw9.js} +1 -1
  529. package/studio/web/assets/{useEntityRestURL-wKC8NsC_.js → useEntityRestURL-31CHGaHk.js} +1 -1
  530. package/studio/web/assets/{workers-CWeLxCXA.js → workers-pR3jRY9D.js} +1 -1
  531. package/studio/web/assets/{xml-BadC-0Rk.js → xml-2iRnMhQO.js} +1 -1
  532. package/studio/web/assets/{yaml-BiUfxPbC.js → yaml-Bf92gJpd.js} +1 -1
  533. package/studio/web/index.html +1 -1
  534. package/upgrade/directives/5-3-0.ts +132 -0
  535. package/upgrade/directives/directivesController.ts +2 -1
  536. package/utility/OperationFunctionCaller.ts +2 -1
  537. package/utility/common_utils.ts +30 -5
  538. package/utility/componentNames.ts +12 -0
  539. package/utility/environment/environmentManager.ts +3 -7
  540. package/utility/environment/systemInformation.ts +7 -0
  541. package/utility/errors/commonErrors.ts +4 -0
  542. package/utility/errors/hdbError.ts +29 -0
  543. package/utility/hdbTerms.ts +17 -0
  544. package/utility/logging/harper_logger.ts +87 -14
  545. package/utility/logging/logRotator.ts +72 -45
  546. package/utility/nodeIdentity.ts +45 -0
  547. package/utility/npmUtilities.ts +10 -8
  548. package/utility/operationPermissions.ts +18 -1
  549. package/utility/operation_authorization.ts +231 -42
  550. package/utility/watchPath.ts +63 -0
  551. package/utility/watcherFallback.ts +270 -0
  552. package/validation/configValidator.ts +209 -72
  553. package/validation/installValidator.ts +15 -0
  554. package/validation/validationWrapper.ts +18 -4
@@ -4,7 +4,7 @@ import { AUDIT_STORE_NAME } from '../utility/lmdb/terms.ts';
4
4
  import { CONFIG_PARAMS } from '../utility/hdbTerms.ts';
5
5
  import { getWorkerIndex, getWorkerCount } from '../server/threads/manageThreads.js';
6
6
  import { convertToMS } from '../utility/common_utils.ts';
7
- import { PREVIOUS_TIMESTAMP_PLACEHOLDER, LAST_TIMESTAMP_PLACEHOLDER } from './RecordEncoder.ts';
7
+ import { LAST_TIMESTAMP_PLACEHOLDER, HAS_STRUCTURE_UPDATE, PENDING_LOCAL_TIME } from './RecordEncoder.ts';
8
8
  import * as harperLogger from '../utility/logging/harper_logger.ts';
9
9
  import { getRecordAtTime } from './crdt.ts';
10
10
  import { decodeFromDatabase } from './blob.ts';
@@ -33,9 +33,8 @@ import { isReadOnlyMode } from './databases.ts';
33
33
  initSync();
34
34
 
35
35
  export type AuditRecord = {
36
- version: number;
37
- recordVersion?: number; // the record's own version; on RocksDB reads `version` becomes the log key, so record identity uses this
38
- localTime: number; // log position: LMDB audit-store key; RocksDB transaction-log timestamp
36
+ version: number; // the record's own version: LWW ordering, @updatedTime, ETag
37
+ txnLogKey: number; // position in the origin's transaction log
39
38
  type: string;
40
39
  encodedRecord?: Buffer;
41
40
  extendedType?: number;
@@ -116,6 +115,13 @@ const MAX_CLEANUP_DELAY = 2 ** 31 - 1;
116
115
  // mint latch keyed per (table, type) so one entry type can't silence another's producer stack
117
116
  const warnedBodylessMints = new Set<string>();
118
117
  const warnedBodylessTables = new Set<number>();
118
+ // legacy-format latches, mirroring the bodyless ones above: a range scan over millions of pre-#2247
119
+ // entries must not turn a recovered read into a log flood. Recovery latches per table (the table is
120
+ // known by then); an undecodable header has no table, so it latches once per process.
121
+ const warnedRecoveredTables = new Set<number>();
122
+ let warnedUndecodableHeader = false;
123
+ // keyed per (table, type) like warnedBodylessMints, so one entry type cannot silence another's stack
124
+ const warnedPendingPreviousVersion = new Set<string>();
119
125
  const FLOAT_TARGET = new Float64Array(1);
120
126
  const FLOAT_BUFFER = new Uint8Array(FLOAT_TARGET.buffer);
121
127
 
@@ -149,7 +155,7 @@ export function openAuditStore(rootStore) {
149
155
  auditStore.getRange = function (options) {
150
156
  if (options.values === false) return superGetRange(options); // getKeys shouldn't be modified
151
157
  return superGetRange(options).map(({ key, value }) => {
152
- value.key = value.localTime = key;
158
+ value.key = value.txnLogKey = key;
153
159
  return value;
154
160
  });
155
161
  };
@@ -165,6 +171,7 @@ export function openAuditStore(rootStore) {
165
171
  return {
166
172
  remove() {
167
173
  delete deleteCallbacks[tableId];
174
+ if (auditStore.tableStores[tableId] === table) delete auditStore.tableStores[tableId];
168
175
  },
169
176
  };
170
177
  };
@@ -374,16 +381,46 @@ export function openAuditStore(rootStore) {
374
381
  return auditStore;
375
382
  }
376
383
 
384
+ /**
385
+ * Whether `entry` is the very write `auditRecord` describes. Write identity is (origin node, log key),
386
+ * never the record version: a version is legitimately non-unique, so a version match can name a
387
+ * different write and authorize destroying live state (a tombstone, a still-referenced blob).
388
+ *
389
+ * On LMDB this is exact — the audit-store key IS the record's `txnLogKey`. On RocksDB a record stores
390
+ * its version in the compatibility word and keeps a divergent log key in `additionalAuditRefs`.
391
+ * Absent identity answers false. The direction is deliberate: uncertainty retains.
392
+ */
393
+ export function isAuditEntryWrite(entry: any, auditRecord: AuditRecord): boolean {
394
+ if (entry == null || auditRecord.txnLogKey == null) return false;
395
+ const auditNodeId = auditRecord.nodeId ?? 0;
396
+ return (
397
+ (entry.localTime === auditRecord.txnLogKey && (entry.nodeId ?? 0) === auditNodeId) ||
398
+ entry.additionalAuditRefs?.some(
399
+ (ref) => ref.version === auditRecord.txnLogKey && (ref.nodeId ?? 0) === auditNodeId
400
+ ) === true
401
+ );
402
+ }
403
+
377
404
  export function removeAuditEntry(auditStore: any, auditRecord: AuditRecord): Promise<void> {
405
+ let tombstoneRemoval: Promise<void> | undefined;
378
406
  if (auditRecord.type === 'delete') {
379
407
  // if this is a delete, we remove the delete entry from the primary table
380
- // at the same time so the audit table the primary table are in sync, assuming the entry matches this audit record version
408
+ // at the same time so the audit table the primary table are in sync, assuming the entry is still
409
+ // the record state this audit record wrote
381
410
  const tableId = auditRecord.tableId;
382
411
  const primaryStore = auditStore.tableStores[auditRecord.tableId];
383
- if (primaryStore?.getEntry(auditRecord.recordId)?.version === auditRecord.version)
384
- auditStore.deleteCallbacks?.[tableId]?.(auditRecord.recordId, auditRecord.version);
412
+ const tombstone = primaryStore?.getEntry(auditRecord.recordId);
413
+ if (isAuditEntryWrite(tombstone, auditRecord))
414
+ // a failed tombstone removal doesn't mean the audit entry removal failed — only
415
+ // auditStore.remove() below decides this function's outcome
416
+ tombstoneRemoval = new Promise<void>((resolve) => {
417
+ resolve(auditStore.deleteCallbacks?.[tableId]?.(auditRecord.recordId, tombstone.version));
418
+ }).catch((error) => {
419
+ harperLogger.warn('Error removing deleted record while removing its audit entry', error);
420
+ });
385
421
  }
386
- return auditStore.remove(auditRecord.key);
422
+ const auditRemoval = auditStore.remove(auditRecord.key);
423
+ return tombstoneRemoval ? Promise.all([tombstoneRemoval, auditRemoval]).then(() => undefined) : auditRemoval;
387
424
  }
388
425
 
389
426
  function updateLastRemoved(auditStore, lastKey) {
@@ -473,13 +510,63 @@ const EVENT_TYPES = {
473
510
  remoteSequenceUpdate: REMOTE_SEQUENCE_UPDATE,
474
511
  [REMOTE_SEQUENCE_UPDATE]: 'remoteSequenceUpdate',
475
512
  };
513
+ /**
514
+ * The LMDB audit entry states the presence of its leading 8-byte previousVersion field with that
515
+ * field's own first byte. The same test is what harperdb 4.x's reader uses and what both versions'
516
+ * replication senders use to strip the field before framing an entry for the wire, so it is a
517
+ * cross-version contract, not a local convention: a field written with any other leading byte is
518
+ * skipped by every reader and shifts action/nodeId/tableId/recordId/version by 8. See harper#2247.
519
+ */
520
+ const PREVIOUS_VERSION_FIRST_BYTE = 66;
521
+ /**
522
+ * Which first bytes can begin an action, and so cannot be a previousVersion field. Derived from what
523
+ * the encoding can express, not from the types defined today: nibbles 9-15 are reserved for future
524
+ * entry types, and a peer one version ahead must keep decoding rather than look corrupt here.
525
+ */
526
+ const ACTION_FIRST_BYTE = new Uint8Array(256);
527
+ // single-byte form; 0 is not an entry type, so a zero low nibble cannot start one
528
+ for (let firstByte = 1; firstByte <= (HAS_RECORD | HAS_PARTIAL_RECORD | 0xf); firstByte++) {
529
+ if (firstByte & 0xf) ACTION_FIRST_BYTE[firstByte] = 1;
530
+ }
531
+ // extended form, written as `action | extendedType | 0xc0000000`; 0xff is the five-byte readInt form
532
+ for (let firstByte = 0xc0; firstByte < 0xff; firstByte++) ACTION_FIRST_BYTE[firstByte] = 1;
533
+ let knownActionFlags: number | undefined;
534
+ /**
535
+ * Whether an action word decodes wholly into what this version understands. Consulted only to accept
536
+ * or reject a legacy prefix recovery — never to validate a normally-framed entry, where an unknown
537
+ * future flag must stay forwards-compatible rather than corrupt. The mask is built on first use
538
+ * because HAS_STRUCTURE_UPDATE crosses the RecordEncoder import cycle: read at module scope it
539
+ * resolves to undefined whenever RecordEncoder is the cycle's entry, silently dropping that bit.
540
+ */
541
+ function isDecodableAction(action: number) {
542
+ knownActionFlags ??=
543
+ 0xf |
544
+ HAS_RECORD |
545
+ HAS_PARTIAL_RECORD |
546
+ HAS_STRUCTURE_UPDATE |
547
+ HAS_CURRENT_RESIDENCY_ID |
548
+ HAS_PREVIOUS_RESIDENCY_ID |
549
+ HAS_ORIGINATING_OPERATION |
550
+ HAS_EXPIRATION_EXTENDED_TYPE |
551
+ HAS_BLOBS |
552
+ HAS_ADDITIONAL_AUDIT_REFS |
553
+ LOCAL_ONLY;
554
+ return (action & 0xf) !== 0 && !(action & ~knownActionFlags);
555
+ }
476
556
  const ORIGINATING_OPERATIONS = {
477
557
  insert: 1,
478
558
  update: 2,
479
559
  upsert: 3,
560
+ // `put` must be persisted, not inferred: the physical write type is also `put` for an `upsert`
561
+ // that happened to create a record, so the history readers cannot tell the two apart from the
562
+ // type alone. Without an id here the originating operation decoded as undefined, the readers fell
563
+ // back to the physical type, and replication catch-up replayed a `put` as an `upsert` — patching
564
+ // the replica and RETAINING attributes the source had removed.
565
+ put: 4,
480
566
  1: 'insert',
481
567
  2: 'update',
482
568
  3: 'upsert',
569
+ 4: 'put',
483
570
  };
484
571
 
485
572
  /**
@@ -531,12 +618,43 @@ export function createAuditEntry(auditRecord: AuditRecord, start = 0) {
531
618
  }
532
619
  action &= ~HAS_RECORD;
533
620
  }
534
- let position = start + 1;
535
- if (previousVersion) {
536
- if (previousVersion > 1) ENTRY_DATAVIEW.setFloat64(start, previousVersion);
537
- else ENTRY_HEADER.set(PREVIOUS_TIMESTAMP_PLACEHOLDER, start);
538
- position = start + 9;
621
+ let hasPreviousVersion: boolean;
622
+ if (start > 0) {
623
+ // RocksTransactionLogStore states presence with its own prelude flag, derived from this same
624
+ // truthiness, so this container's field stays unconditional and its value is unconstrained.
625
+ hasPreviousVersion = !!previousVersion;
626
+ if (hasPreviousVersion) ENTRY_DATAVIEW.setFloat64(start, previousVersion);
627
+ } else if (previousVersion == null || previousVersion === 0) {
628
+ // absence is stated, not inferred from truthiness: NaN is falsy and would otherwise be
629
+ // silently dropped rather than rejected below
630
+ hasPreviousVersion = false;
631
+ } else if (previousVersion === PENDING_LOCAL_TIME) {
632
+ // The previous entry has no log position yet, and a format whose presence signal is the value's
633
+ // own first byte cannot express "to be filled in at commit". The superseded code deferred to
634
+ // lmdb-js's instructed-write substitution, which resolves to 2.0 whenever no previous time was
635
+ // recorded — the unreadable entry behind harper-pro#737. It resolved correctly when one was, so
636
+ // this trades a lost link on that path for never minting the unreadable form. Not a throw: a
637
+ // pending previous is a producer state, unlike a value the format cannot hold.
638
+ hasPreviousVersion = false;
639
+ if (!warnedPendingPreviousVersion.has(`${tableId}:${type}`)) {
640
+ warnedPendingPreviousVersion.add(`${tableId}:${type}`);
641
+ warnContained(
642
+ `Audit entry (${type}) for record ${recordId} in table ${tableId} has a pending previous version; recording it without a previous-version link`,
643
+ new Error('pending audit previousVersion')
644
+ );
645
+ }
646
+ } else {
647
+ ENTRY_DATAVIEW.setFloat64(start, previousVersion);
648
+ if (ENTRY_HEADER[start] !== PREVIOUS_VERSION_FIRST_BYTE) {
649
+ throw new Error(
650
+ `Audit entry previousVersion ${previousVersion} for record ${recordId} in table ${tableId} is not representable. ` +
651
+ 'The LMDB audit format signals this field with its own leading 0x42 byte, so only values in [2**33, 2**49) can be written; ' +
652
+ 'writing any other value produces an entry every reader parses 8 bytes off.'
653
+ );
654
+ }
655
+ hasPreviousVersion = true;
539
656
  }
657
+ let position = start + (hasPreviousVersion ? 9 : 1);
540
658
  if (extendedType) {
541
659
  if (extendedType & 0xff) {
542
660
  throw new Error('Illegal extended type');
@@ -575,8 +693,9 @@ export function createAuditEntry(auditRecord: AuditRecord, start = 0) {
575
693
 
576
694
  if (user) writeValue(user);
577
695
  else ENTRY_HEADER[position++] = 0;
578
- if (extendedType) ENTRY_DATAVIEW.setUint32(start + (previousVersion ? 8 : 0), action | extendedType | 0xc0000000);
579
- else ENTRY_HEADER[start + (previousVersion ? 8 : 0)] = action;
696
+ const actionPosition = start + (hasPreviousVersion ? 8 : 0);
697
+ if (extendedType) ENTRY_DATAVIEW.setUint32(actionPosition, action | extendedType | 0xc0000000);
698
+ else ENTRY_HEADER[actionPosition] = action;
580
699
  const header = ENTRY_HEADER.subarray(0, position);
581
700
  if (encodedRecord) {
582
701
  return Buffer.concat([header, encodedRecord]);
@@ -634,13 +753,40 @@ export function readAuditEntry(buffer: Uint8Array, start = 0, end = undefined):
634
753
  ((buffer as any).decoder = new Decoder(buffer.buffer, buffer.byteOffset, buffer.byteLength));
635
754
  decoder.position = start;
636
755
  let previousVersion;
637
- if (buffer[decoder.position] == 66) {
638
- // 66 is the first byte in a date double.
756
+ let entryStart = start;
757
+ const firstByte = buffer[start];
758
+ if (firstByte === PREVIOUS_VERSION_FIRST_BYTE) {
639
759
  previousVersion = decoder.readFloat64();
760
+ } else if (ACTION_FIRST_BYTE[firstByte] !== 1) {
761
+ // Written before the writer enforced the leading-0x42 contract (harper#2247): the field is
762
+ // physically here but does not announce itself, so the action sits 8 bytes further on.
763
+ // Recover only when the bytes cannot be anything else, and never for the RocksDB container,
764
+ // whose prelude flag already consumed its previousVersion before this offset.
765
+ if (start !== 0 || start + 9 > buffer.byteLength || ACTION_FIRST_BYTE[buffer[start + 8]] !== 1) {
766
+ return corruptEntry(buffer, start, end, firstByte);
767
+ }
768
+ // > 1 is exactly what the superseded writer's own guard could emit, the tightest available
769
+ // bound on "these bytes really are an old previousVersion"
770
+ if (!(decoder.getFloat64(start) > 1)) return corruptEntry(buffer, start, end, firstByte);
771
+ entryStart = decoder.position = start + 8;
772
+ // The value itself is dropped, not reported. It cannot lead with 0x42 (that is the branch
773
+ // above), and audit keys carry the same constraint, so it could never have addressed a
774
+ // retrievable entry; reporting it would only feed an unrepresentable value back to
775
+ // createAuditEntry through the resolveRecord re-mint in RecordEncoder, which now rejects it.
640
776
  }
641
777
  const action = decoder.readInt();
778
+ if (entryStart !== start && !isDecodableAction(action)) {
779
+ return corruptEntry(buffer, start, end, firstByte);
780
+ }
642
781
  const nodeId = decoder.readInt();
643
782
  const tableId = decoder.readInt();
783
+ if (entryStart !== start && !warnedRecoveredTables.has(tableId)) {
784
+ warnedRecoveredTables.add(tableId);
785
+ warnContained('Audit entry carries an unannounced previousVersion field; recovering its field offsets', {
786
+ tableId,
787
+ firstByte,
788
+ });
789
+ }
644
790
  let length = decoder.readInt();
645
791
  // A corrupt length field (e.g., a 0xff-prefixed uint32) would otherwise push
646
792
  // decoder.position hundreds of megabytes past the buffer; the next readFloat64
@@ -713,7 +859,6 @@ export function readAuditEntry(buffer: Uint8Array, start = 0, end = undefined):
713
859
  return buffer.subarray(recordIdStart, recordIdEnd);
714
860
  },
715
861
  version,
716
- recordVersion: version,
717
862
  previousVersion,
718
863
  get user() {
719
864
  try {
@@ -726,10 +871,14 @@ export function readAuditEntry(buffer: Uint8Array, start = 0, end = undefined):
726
871
  }
727
872
  },
728
873
  get encoded() {
729
- return start ? buffer.subarray(start, end) : buffer;
874
+ // On a recovered entry this drops the unannounced prefix, so a replication sender —
875
+ // which strips by the same leading-0x42 test and frames by encoded.length — forwards a
876
+ // clean entry instead of passing the same misparse to the next hop.
877
+ return entryStart ? buffer.subarray(entryStart, end) : buffer;
730
878
  },
731
879
  get size() {
732
- return start !== undefined && end !== undefined ? end - start : buffer.byteLength;
880
+ // only the recovered prefix is discounted; every other case keeps its existing basis
881
+ return (end !== undefined ? end - start : buffer.byteLength) - (entryStart - start);
733
882
  },
734
883
  getValue(store, fullRecord?, auditTime?) {
735
884
  if (action & HAS_RECORD || (action & HAS_PARTIAL_RECORD && !fullRecord)) {
@@ -778,6 +927,23 @@ export function readAuditEntry(buffer: Uint8Array, start = 0, end = undefined):
778
927
  }
779
928
  }
780
929
 
930
+ /**
931
+ * Reject a header whose first byte can be neither an action nor a previousVersion field. Returns the
932
+ * sentinel directly rather than throwing into readAuditEntry's catch, whose error log is not
933
+ * contained: a throwing log sink there would escape the decoder and stall the iteration it runs in.
934
+ */
935
+ function corruptEntry(buffer: Uint8Array, start: number, end: number | undefined, firstByte: number): AuditRecord {
936
+ if (!warnedUndecodableHeader) {
937
+ warnedUndecodableHeader = true;
938
+ warnContained('Audit entry header begins with neither an action nor a previousVersion; treating as corrupt', {
939
+ firstByte,
940
+ // the 8 prefix bytes plus the action byte: the classifying bytes, stopping before the recordId
941
+ header: Buffer.from(buffer.subarray(start, Math.min(start + 9, buffer.byteLength))).toString('hex'),
942
+ });
943
+ }
944
+ return createCorruptAuditSentinel(buffer, start, end);
945
+ }
946
+
781
947
  /**
782
948
  * Build a structurally complete audit record for an entry that failed to decode. The fields
783
949
  * mirror the happy-path shape so downstream consumers that access (e.g.) `getValue` or the