@harperfast/harper 5.2.9 → 5.3.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (668) hide show
  1. package/agent/mcpTools.ts +1 -1
  2. package/agent/session.ts +25 -14
  3. package/bin/cliOperations.ts +46 -9
  4. package/bin/copyDb.ts +282 -59
  5. package/bin/deploySetup.ts +16 -5
  6. package/bin/harper.ts +1 -1
  7. package/bin/help.ts +4 -1
  8. package/bin/lite.ts +4 -1
  9. package/bin/restart.ts +59 -3
  10. package/bin/run.ts +6 -11
  11. package/bin/upgrade.js +7 -3
  12. package/bin/workloadIdentity.ts +119 -0
  13. package/components/Application.ts +2414 -242
  14. package/components/ApplicationScope.ts +8 -0
  15. package/components/EntryHandler.ts +59 -39
  16. package/components/OptionsWatcher.ts +150 -74
  17. package/components/RuntimeModuleTracker.ts +38 -7
  18. package/components/Scope.ts +37 -15
  19. package/components/awaitRestart.ts +84 -0
  20. package/components/componentLoader.ts +340 -30
  21. package/components/componentPreparationLock.ts +16 -5
  22. package/components/mcp/adapters/harperHttp.ts +4 -0
  23. package/components/mcp/listChanged.ts +4 -0
  24. package/components/mcp/toolRegistry.ts +2 -0
  25. package/components/mcp/tools/operations.ts +9 -0
  26. package/components/mcp/tools/schemas/operationDescriptions.ts +2 -2
  27. package/components/operations.js +270 -78
  28. package/components/operationsValidation.js +49 -1
  29. package/components/status/ComponentStatusRegistry.ts +59 -0
  30. package/config/RootConfigWatcher.ts +80 -34
  31. package/config/configUtils.ts +291 -34
  32. package/config/harperConfigEnvVars.ts +170 -27
  33. package/config-root.schema.json +29 -0
  34. package/dataLayer/blobBackup.ts +160 -50
  35. package/dataLayer/delete.ts +6 -1
  36. package/dataLayer/harperBridge/ResourceBridge.ts +52 -8
  37. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  38. package/dataLayer/hdbInfoController.ts +34 -1
  39. package/dataLayer/insert.ts +44 -1
  40. package/dataLayer/rocksdbBackup.ts +53 -10
  41. package/dataLayer/schema.ts +11 -1
  42. package/dataLayer/schemaDescribe.ts +8 -1
  43. package/dist/agent/mcpTools.js +1 -1
  44. package/dist/agent/mcpTools.js.map +1 -1
  45. package/dist/agent/session.d.ts +22 -0
  46. package/dist/agent/session.js +26 -15
  47. package/dist/agent/session.js.map +1 -1
  48. package/dist/bin/cliOperations.js +48 -9
  49. package/dist/bin/cliOperations.js.map +1 -1
  50. package/dist/bin/copyDb.d.ts +12 -1
  51. package/dist/bin/copyDb.js +248 -60
  52. package/dist/bin/copyDb.js.map +1 -1
  53. package/dist/bin/deploySetup.d.ts +2 -0
  54. package/dist/bin/deploySetup.js +11 -3
  55. package/dist/bin/deploySetup.js.map +1 -1
  56. package/dist/bin/harper.js +1 -1
  57. package/dist/bin/harper.js.map +1 -1
  58. package/dist/bin/help.js +4 -1
  59. package/dist/bin/help.js.map +1 -1
  60. package/dist/bin/lite.js +4 -1
  61. package/dist/bin/lite.js.map +1 -1
  62. package/dist/bin/restart.js +54 -5
  63. package/dist/bin/restart.js.map +1 -1
  64. package/dist/bin/run.js +4 -10
  65. package/dist/bin/run.js.map +1 -1
  66. package/dist/bin/upgrade.js +4 -3
  67. package/dist/bin/upgrade.js.map +1 -1
  68. package/dist/bin/workloadIdentity.d.ts +18 -0
  69. package/dist/bin/workloadIdentity.js +100 -0
  70. package/dist/bin/workloadIdentity.js.map +1 -0
  71. package/dist/components/Application.d.ts +139 -16
  72. package/dist/components/Application.js +2215 -267
  73. package/dist/components/Application.js.map +1 -1
  74. package/dist/components/ApplicationScope.d.ts +8 -0
  75. package/dist/components/ApplicationScope.js +7 -0
  76. package/dist/components/ApplicationScope.js.map +1 -1
  77. package/dist/components/EntryHandler.js +26 -10
  78. package/dist/components/EntryHandler.js.map +1 -1
  79. package/dist/components/OptionsWatcher.d.ts +1 -0
  80. package/dist/components/OptionsWatcher.js +141 -74
  81. package/dist/components/OptionsWatcher.js.map +1 -1
  82. package/dist/components/RuntimeModuleTracker.js +40 -6
  83. package/dist/components/RuntimeModuleTracker.js.map +1 -1
  84. package/dist/components/Scope.js +38 -13
  85. package/dist/components/Scope.js.map +1 -1
  86. package/dist/components/awaitRestart.d.ts +33 -0
  87. package/dist/components/awaitRestart.js +61 -0
  88. package/dist/components/awaitRestart.js.map +1 -0
  89. package/dist/components/componentLoader.d.ts +38 -1
  90. package/dist/components/componentLoader.js +279 -22
  91. package/dist/components/componentLoader.js.map +1 -1
  92. package/dist/components/componentPreparationLock.d.ts +5 -0
  93. package/dist/components/componentPreparationLock.js +14 -6
  94. package/dist/components/componentPreparationLock.js.map +1 -1
  95. package/dist/components/mcp/adapters/harperHttp.js +4 -0
  96. package/dist/components/mcp/adapters/harperHttp.js.map +1 -1
  97. package/dist/components/mcp/listChanged.js +5 -0
  98. package/dist/components/mcp/listChanged.js.map +1 -1
  99. package/dist/components/mcp/toolRegistry.d.ts +1 -0
  100. package/dist/components/mcp/toolRegistry.js.map +1 -1
  101. package/dist/components/mcp/tools/operations.d.ts +5 -0
  102. package/dist/components/mcp/tools/operations.js +9 -0
  103. package/dist/components/mcp/tools/operations.js.map +1 -1
  104. package/dist/components/mcp/tools/schemas/operationDescriptions.js +2 -2
  105. package/dist/components/mcp/tools/schemas/operationDescriptions.js.map +1 -1
  106. package/dist/components/operations.js +231 -77
  107. package/dist/components/operations.js.map +1 -1
  108. package/dist/components/operationsValidation.js +49 -1
  109. package/dist/components/operationsValidation.js.map +1 -1
  110. package/dist/components/status/ComponentStatusRegistry.d.ts +0 -4
  111. package/dist/components/status/ComponentStatusRegistry.js +63 -0
  112. package/dist/components/status/ComponentStatusRegistry.js.map +1 -1
  113. package/dist/config/RootConfigWatcher.d.ts +7 -1
  114. package/dist/config/RootConfigWatcher.js +64 -27
  115. package/dist/config/RootConfigWatcher.js.map +1 -1
  116. package/dist/config/configUtils.d.ts +9 -1
  117. package/dist/config/configUtils.js +254 -33
  118. package/dist/config/configUtils.js.map +1 -1
  119. package/dist/config/harperConfigEnvVars.d.ts +16 -0
  120. package/dist/config/harperConfigEnvVars.js +162 -25
  121. package/dist/config/harperConfigEnvVars.js.map +1 -1
  122. package/dist/dataLayer/blobBackup.d.ts +49 -20
  123. package/dist/dataLayer/blobBackup.js +139 -50
  124. package/dist/dataLayer/blobBackup.js.map +1 -1
  125. package/dist/dataLayer/delete.js +1 -1
  126. package/dist/dataLayer/delete.js.map +1 -1
  127. package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +14 -1
  128. package/dist/dataLayer/harperBridge/ResourceBridge.js +51 -10
  129. package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
  130. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.d.ts +3 -1
  131. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
  132. package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js.map +1 -1
  133. package/dist/dataLayer/hdbInfoController.d.ts +10 -0
  134. package/dist/dataLayer/hdbInfoController.js +30 -1
  135. package/dist/dataLayer/hdbInfoController.js.map +1 -1
  136. package/dist/dataLayer/insert.d.ts +9 -1
  137. package/dist/dataLayer/insert.js +30 -0
  138. package/dist/dataLayer/insert.js.map +1 -1
  139. package/dist/dataLayer/rocksdbBackup.d.ts +2 -2
  140. package/dist/dataLayer/rocksdbBackup.js +45 -8
  141. package/dist/dataLayer/rocksdbBackup.js.map +1 -1
  142. package/dist/dataLayer/schema.js +8 -0
  143. package/dist/dataLayer/schema.js.map +1 -1
  144. package/dist/dataLayer/schemaDescribe.js +8 -1
  145. package/dist/dataLayer/schemaDescribe.js.map +1 -1
  146. package/dist/index.d.ts +1 -1
  147. package/dist/index.js.map +1 -1
  148. package/dist/json/systemSchema.json +52 -0
  149. package/dist/resources/DatabaseTransaction.d.ts +55 -0
  150. package/dist/resources/DatabaseTransaction.js +459 -45
  151. package/dist/resources/DatabaseTransaction.js.map +1 -1
  152. package/dist/resources/LMDBTransaction.js +22 -4
  153. package/dist/resources/LMDBTransaction.js.map +1 -1
  154. package/dist/resources/PrimaryRocksDatabase.d.ts +1 -0
  155. package/dist/resources/PrimaryRocksDatabase.js +29 -0
  156. package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
  157. package/dist/resources/RecordEncoder.d.ts +20 -0
  158. package/dist/resources/RecordEncoder.js +94 -9
  159. package/dist/resources/RecordEncoder.js.map +1 -1
  160. package/dist/resources/RequestTarget.d.ts +2 -0
  161. package/dist/resources/RequestTarget.js.map +1 -1
  162. package/dist/resources/Resource.js +20 -11
  163. package/dist/resources/Resource.js.map +1 -1
  164. package/dist/resources/ResourceInterface.d.ts +20 -1
  165. package/dist/resources/ResourceInterface.js.map +1 -1
  166. package/dist/resources/RocksIndexStore.d.ts +6 -1
  167. package/dist/resources/RocksIndexStore.js +24 -9
  168. package/dist/resources/RocksIndexStore.js.map +1 -1
  169. package/dist/resources/RocksTransactionLogStore.d.ts +14 -1
  170. package/dist/resources/RocksTransactionLogStore.js +57 -17
  171. package/dist/resources/RocksTransactionLogStore.js.map +1 -1
  172. package/dist/resources/Table.d.ts +112 -8
  173. package/dist/resources/Table.js +1073 -191
  174. package/dist/resources/Table.js.map +1 -1
  175. package/dist/resources/auditStore.d.ts +11 -2
  176. package/dist/resources/auditStore.js +325 -71
  177. package/dist/resources/auditStore.js.map +1 -1
  178. package/dist/resources/blob.d.ts +129 -9
  179. package/dist/resources/blob.js +992 -114
  180. package/dist/resources/blob.js.map +1 -1
  181. package/dist/resources/branchDatabase.d.ts +48 -0
  182. package/dist/resources/branchDatabase.js +892 -0
  183. package/dist/resources/branchDatabase.js.map +1 -0
  184. package/dist/resources/crdt.js +50 -12
  185. package/dist/resources/crdt.js.map +1 -1
  186. package/dist/resources/databases.d.ts +150 -0
  187. package/dist/resources/databases.js +1200 -239
  188. package/dist/resources/databases.js.map +1 -1
  189. package/dist/resources/defineTable.d.ts +10 -2
  190. package/dist/resources/defineTable.js +9 -1
  191. package/dist/resources/defineTable.js.map +1 -1
  192. package/dist/resources/graphql.d.ts +1 -1
  193. package/dist/resources/graphql.js +50 -15
  194. package/dist/resources/graphql.js.map +1 -1
  195. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +1 -0
  196. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +6 -2
  197. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
  198. package/dist/resources/longLivedTransactions.d.ts +71 -0
  199. package/dist/resources/longLivedTransactions.js +358 -0
  200. package/dist/resources/longLivedTransactions.js.map +1 -0
  201. package/dist/resources/models/backendRegistry.d.ts +26 -0
  202. package/dist/resources/models/backendRegistry.js +60 -2
  203. package/dist/resources/models/backendRegistry.js.map +1 -1
  204. package/dist/resources/models/bootstrap.d.ts +33 -1
  205. package/dist/resources/models/bootstrap.js +416 -31
  206. package/dist/resources/models/bootstrap.js.map +1 -1
  207. package/dist/resources/recordLock.d.ts +80 -0
  208. package/dist/resources/recordLock.js +184 -0
  209. package/dist/resources/recordLock.js.map +1 -0
  210. package/dist/resources/replayLogs.d.ts +14 -1
  211. package/dist/resources/replayLogs.js +152 -24
  212. package/dist/resources/replayLogs.js.map +1 -1
  213. package/dist/resources/replayLogsGuards.d.ts +94 -7
  214. package/dist/resources/replayLogsGuards.js +111 -7
  215. package/dist/resources/replayLogsGuards.js.map +1 -1
  216. package/dist/resources/search.js +158 -6
  217. package/dist/resources/search.js.map +1 -1
  218. package/dist/resources/transactionBroadcast.d.ts +1 -1
  219. package/dist/resources/transactionBroadcast.js +2 -2
  220. package/dist/resources/transactionBroadcast.js.map +1 -1
  221. package/dist/security/auth.js +61 -30
  222. package/dist/security/auth.js.map +1 -1
  223. package/dist/security/authn/oidc/claims.d.ts +22 -0
  224. package/dist/security/authn/oidc/claims.js +71 -0
  225. package/dist/security/authn/oidc/claims.js.map +1 -0
  226. package/dist/security/authn/oidc/identityToken.d.ts +27 -0
  227. package/dist/security/authn/oidc/identityToken.js +111 -0
  228. package/dist/security/authn/oidc/identityToken.js.map +1 -0
  229. package/dist/security/authn/oidc/jwks.d.ts +25 -0
  230. package/dist/security/authn/oidc/jwks.js +261 -0
  231. package/dist/security/authn/oidc/jwks.js.map +1 -0
  232. package/dist/security/authn/oidc/providers/generic.d.ts +13 -0
  233. package/dist/security/authn/oidc/providers/generic.js +34 -0
  234. package/dist/security/authn/oidc/providers/generic.js.map +1 -0
  235. package/dist/security/authn/oidc/providers/githubActions.d.ts +11 -0
  236. package/dist/security/authn/oidc/providers/githubActions.js +129 -0
  237. package/dist/security/authn/oidc/providers/githubActions.js.map +1 -0
  238. package/dist/security/authn/oidc/providers/index.d.ts +37 -0
  239. package/dist/security/authn/oidc/providers/index.js +24 -0
  240. package/dist/security/authn/oidc/providers/index.js.map +1 -0
  241. package/dist/security/authn/oidc/tokenExchange.d.ts +12 -0
  242. package/dist/security/authn/oidc/tokenExchange.js +306 -0
  243. package/dist/security/authn/oidc/tokenExchange.js.map +1 -0
  244. package/dist/security/authn/oidc/trustPolicyOperations.d.ts +49 -0
  245. package/dist/security/authn/oidc/trustPolicyOperations.js +358 -0
  246. package/dist/security/authn/oidc/trustPolicyOperations.js.map +1 -0
  247. package/dist/security/authn/oidc/types.d.ts +38 -0
  248. package/dist/security/authn/oidc/types.js +6 -0
  249. package/dist/security/authn/oidc/types.js.map +1 -0
  250. package/dist/security/certificateVerification/index.js +40 -11
  251. package/dist/security/certificateVerification/index.js.map +1 -1
  252. package/dist/security/certificateVerification/trustedIssuers.d.ts +24 -0
  253. package/dist/security/certificateVerification/trustedIssuers.js +79 -0
  254. package/dist/security/certificateVerification/trustedIssuers.js.map +1 -0
  255. package/dist/security/certificateVerification/types.d.ts +1 -0
  256. package/dist/security/credentialProvenance.d.ts +35 -0
  257. package/dist/security/credentialProvenance.js +51 -0
  258. package/dist/security/credentialProvenance.js.map +1 -0
  259. package/dist/security/credentialRejection.d.ts +4 -0
  260. package/dist/security/credentialRejection.js +24 -0
  261. package/dist/security/credentialRejection.js.map +1 -0
  262. package/dist/security/deferredAuthentication.d.ts +36 -0
  263. package/dist/security/deferredAuthentication.js +70 -0
  264. package/dist/security/deferredAuthentication.js.map +1 -0
  265. package/dist/security/impersonation.d.ts +21 -0
  266. package/dist/security/impersonation.js +108 -9
  267. package/dist/security/impersonation.js.map +1 -1
  268. package/dist/security/jsLoader.d.ts +6 -0
  269. package/dist/security/jsLoader.js +75 -15
  270. package/dist/security/jsLoader.js.map +1 -1
  271. package/dist/security/keys.js +301 -71
  272. package/dist/security/keys.js.map +1 -1
  273. package/dist/security/operationScope.d.ts +21 -0
  274. package/dist/security/operationScope.js +36 -0
  275. package/dist/security/operationScope.js.map +1 -0
  276. package/dist/security/permissionsTranslator.js +21 -0
  277. package/dist/security/permissionsTranslator.js.map +1 -1
  278. package/dist/security/tokenAuthentication.d.ts +19 -1
  279. package/dist/security/tokenAuthentication.js +191 -10
  280. package/dist/security/tokenAuthentication.js.map +1 -1
  281. package/dist/security/user.js +4 -3
  282. package/dist/security/user.js.map +1 -1
  283. package/dist/server/DurableSubscriptionsSession.d.ts +2 -2
  284. package/dist/server/DurableSubscriptionsSession.js +67 -10
  285. package/dist/server/DurableSubscriptionsSession.js.map +1 -1
  286. package/dist/server/REST.js +73 -0
  287. package/dist/server/REST.js.map +1 -1
  288. package/dist/server/graphqlQuerying.js +4 -0
  289. package/dist/server/graphqlQuerying.js.map +1 -1
  290. package/dist/server/http.d.ts +11 -0
  291. package/dist/server/http.js +88 -15
  292. package/dist/server/http.js.map +1 -1
  293. package/dist/server/itc/serverHandlers.js +8 -1
  294. package/dist/server/itc/serverHandlers.js.map +1 -1
  295. package/dist/server/jobs/jobProcess.js +6 -2
  296. package/dist/server/jobs/jobProcess.js.map +1 -1
  297. package/dist/server/jobs/jobs.js +4 -1
  298. package/dist/server/jobs/jobs.js.map +1 -1
  299. package/dist/server/liveSubscriptionAuth.d.ts +26 -4
  300. package/dist/server/liveSubscriptionAuth.js +105 -39
  301. package/dist/server/liveSubscriptionAuth.js.map +1 -1
  302. package/dist/server/loadRootComponents.js +49 -10
  303. package/dist/server/loadRootComponents.js.map +1 -1
  304. package/dist/server/mqtt.d.ts +2 -0
  305. package/dist/server/mqtt.js +165 -30
  306. package/dist/server/mqtt.js.map +1 -1
  307. package/dist/server/nodeName.d.ts +2 -0
  308. package/dist/server/nodeName.js +107 -23
  309. package/dist/server/nodeName.js.map +1 -1
  310. package/dist/server/serverHelpers/Headers.d.ts +25 -0
  311. package/dist/server/serverHelpers/Headers.js +139 -1
  312. package/dist/server/serverHelpers/Headers.js.map +1 -1
  313. package/dist/server/serverHelpers/contentTypes.d.ts +9 -0
  314. package/dist/server/serverHelpers/contentTypes.js +32 -25
  315. package/dist/server/serverHelpers/contentTypes.js.map +1 -1
  316. package/dist/server/serverHelpers/deployValidationState.d.ts +3 -0
  317. package/dist/server/serverHelpers/deployValidationState.js +9 -19
  318. package/dist/server/serverHelpers/deployValidationState.js.map +1 -1
  319. package/dist/server/serverHelpers/operationAuthorizationState.d.ts +12 -0
  320. package/dist/server/serverHelpers/operationAuthorizationState.js +24 -2
  321. package/dist/server/serverHelpers/operationAuthorizationState.js.map +1 -1
  322. package/dist/server/serverHelpers/registeredOperations.d.ts +5 -4
  323. package/dist/server/serverHelpers/registeredOperations.js +74 -21
  324. package/dist/server/serverHelpers/registeredOperations.js.map +1 -1
  325. package/dist/server/serverHelpers/requestSanitization.d.ts +11 -0
  326. package/dist/server/serverHelpers/requestSanitization.js +20 -0
  327. package/dist/server/serverHelpers/requestSanitization.js.map +1 -0
  328. package/dist/server/serverHelpers/serverHandlers.js +6 -3
  329. package/dist/server/serverHelpers/serverHandlers.js.map +1 -1
  330. package/dist/server/serverHelpers/serverUtilities.d.ts +18 -0
  331. package/dist/server/serverHelpers/serverUtilities.js +90 -20
  332. package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
  333. package/dist/server/serverHelpers/sharedMessageEncoding.d.ts +67 -0
  334. package/dist/server/serverHelpers/sharedMessageEncoding.js +280 -0
  335. package/dist/server/serverHelpers/sharedMessageEncoding.js.map +1 -0
  336. package/dist/server/serverHelpers/uwsServer.js +19 -1
  337. package/dist/server/serverHelpers/uwsServer.js.map +1 -1
  338. package/dist/server/static.js +24 -28
  339. package/dist/server/static.js.map +1 -1
  340. package/dist/server/storageReclamation.d.ts +12 -0
  341. package/dist/server/storageReclamation.js +26 -0
  342. package/dist/server/storageReclamation.js.map +1 -1
  343. package/dist/server/threads/itc.d.ts +7 -2
  344. package/dist/server/threads/itc.js +5 -1
  345. package/dist/server/threads/itc.js.map +1 -1
  346. package/dist/server/threads/manageThreads.d.ts +26 -3
  347. package/dist/server/threads/manageThreads.js +517 -65
  348. package/dist/server/threads/manageThreads.js.map +1 -1
  349. package/dist/server/threads/socketRouter.js +89 -26
  350. package/dist/server/threads/socketRouter.js.map +1 -1
  351. package/dist/server/threads/threadHeapMemory.d.ts +2 -0
  352. package/dist/server/threads/threadHeapMemory.js +31 -0
  353. package/dist/server/threads/threadHeapMemory.js.map +1 -0
  354. package/dist/server/threads/threadServer.js +46 -15
  355. package/dist/server/threads/threadServer.js.map +1 -1
  356. package/dist/sqlEngine/config.d.ts +1 -3
  357. package/dist/sqlEngine/config.js +19 -16
  358. package/dist/sqlEngine/config.js.map +1 -1
  359. package/dist/sqlTranslator/index.d.ts +1 -1
  360. package/dist/sqlTranslator/index.js +30 -7
  361. package/dist/sqlTranslator/index.js.map +1 -1
  362. package/dist/upgrade/directives/5-3-0.d.ts +7 -0
  363. package/dist/upgrade/directives/5-3-0.js +148 -0
  364. package/dist/upgrade/directives/5-3-0.js.map +1 -0
  365. package/dist/upgrade/directives/directivesController.js +2 -1
  366. package/dist/upgrade/directives/directivesController.js.map +1 -1
  367. package/dist/utility/OperationFunctionCaller.js +2 -1
  368. package/dist/utility/OperationFunctionCaller.js.map +1 -1
  369. package/dist/utility/common_utils.d.ts +16 -0
  370. package/dist/utility/common_utils.js +32 -6
  371. package/dist/utility/common_utils.js.map +1 -1
  372. package/dist/utility/componentNames.d.ts +8 -0
  373. package/dist/utility/componentNames.js +12 -1
  374. package/dist/utility/componentNames.js.map +1 -1
  375. package/dist/utility/environment/environmentManager.js +3 -6
  376. package/dist/utility/environment/environmentManager.js.map +1 -1
  377. package/dist/utility/environment/systemInformation.d.ts +1 -0
  378. package/dist/utility/environment/systemInformation.js +1 -0
  379. package/dist/utility/environment/systemInformation.js.map +1 -1
  380. package/dist/utility/errors/commonErrors.d.ts +2 -0
  381. package/dist/utility/errors/commonErrors.js +2 -0
  382. package/dist/utility/errors/commonErrors.js.map +1 -1
  383. package/dist/utility/errors/hdbError.d.ts +17 -0
  384. package/dist/utility/errors/hdbError.js +30 -1
  385. package/dist/utility/errors/hdbError.js.map +1 -1
  386. package/dist/utility/globalSchema.d.ts +18 -0
  387. package/dist/utility/hdbTerms.d.ts +16 -0
  388. package/dist/utility/hdbTerms.js +18 -2
  389. package/dist/utility/hdbTerms.js.map +1 -1
  390. package/dist/utility/logging/harper_logger.d.ts +2 -0
  391. package/dist/utility/logging/harper_logger.js +91 -14
  392. package/dist/utility/logging/harper_logger.js.map +1 -1
  393. package/dist/utility/logging/logRotator.js +76 -49
  394. package/dist/utility/logging/logRotator.js.map +1 -1
  395. package/dist/utility/nodeIdentity.d.ts +9 -0
  396. package/dist/utility/nodeIdentity.js +58 -0
  397. package/dist/utility/nodeIdentity.js.map +1 -0
  398. package/dist/utility/npmUtilities.js +9 -7
  399. package/dist/utility/npmUtilities.js.map +1 -1
  400. package/dist/utility/operationPermissions.d.ts +3 -1
  401. package/dist/utility/operationPermissions.js +16 -1
  402. package/dist/utility/operationPermissions.js.map +1 -1
  403. package/dist/utility/operation_authorization.d.ts +10 -7
  404. package/dist/utility/operation_authorization.js +212 -41
  405. package/dist/utility/operation_authorization.js.map +1 -1
  406. package/dist/utility/watchPath.d.ts +29 -0
  407. package/dist/utility/watchPath.js +68 -0
  408. package/dist/utility/watchPath.js.map +1 -0
  409. package/dist/utility/watcherFallback.d.ts +86 -0
  410. package/dist/utility/watcherFallback.js +278 -1
  411. package/dist/utility/watcherFallback.js.map +1 -1
  412. package/dist/validation/configValidator.d.ts +12 -0
  413. package/dist/validation/configValidator.js +199 -72
  414. package/dist/validation/configValidator.js.map +1 -1
  415. package/dist/validation/installValidator.js +12 -0
  416. package/dist/validation/installValidator.js.map +1 -1
  417. package/dist/validation/validationWrapper.d.ts +11 -0
  418. package/dist/validation/validationWrapper.js +16 -3
  419. package/dist/validation/validationWrapper.js.map +1 -1
  420. package/index.ts +2 -0
  421. package/json/systemSchema.json +52 -0
  422. package/npm-shrinkwrap.json +196 -194
  423. package/package.json +7 -6
  424. package/resources/DESIGN.md +114 -52
  425. package/resources/DatabaseTransaction.ts +521 -43
  426. package/resources/LMDBTransaction.ts +26 -4
  427. package/resources/PrimaryRocksDatabase.ts +28 -1
  428. package/resources/RecordEncoder.ts +103 -8
  429. package/resources/RequestTarget.ts +2 -0
  430. package/resources/Resource.ts +17 -9
  431. package/resources/ResourceInterface.ts +23 -0
  432. package/resources/RocksIndexStore.ts +30 -9
  433. package/resources/RocksTransactionLogStore.ts +78 -21
  434. package/resources/Table.ts +1110 -159
  435. package/resources/auditStore.ts +331 -73
  436. package/resources/blob.ts +1029 -110
  437. package/resources/branchDatabase.ts +941 -0
  438. package/resources/crdt.ts +76 -12
  439. package/resources/databases.ts +1310 -252
  440. package/resources/defineTable.ts +18 -2
  441. package/resources/graphql.ts +70 -16
  442. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +6 -2
  443. package/resources/longLivedTransactions.ts +360 -0
  444. package/resources/models/backendRegistry.ts +84 -2
  445. package/resources/models/bootstrap.ts +473 -28
  446. package/resources/recordLock.ts +253 -0
  447. package/resources/replayLogs.ts +147 -26
  448. package/resources/replayLogsGuards.ts +171 -8
  449. package/resources/search.ts +154 -7
  450. package/resources/transactionBroadcast.ts +3 -3
  451. package/security/auth.ts +68 -29
  452. package/security/authn/oidc/claims.ts +72 -0
  453. package/security/authn/oidc/identityToken.ts +129 -0
  454. package/security/authn/oidc/jwks.ts +260 -0
  455. package/security/authn/oidc/providers/generic.ts +40 -0
  456. package/security/authn/oidc/providers/githubActions.ts +137 -0
  457. package/security/authn/oidc/providers/index.ts +52 -0
  458. package/security/authn/oidc/tokenExchange.ts +300 -0
  459. package/security/authn/oidc/trustPolicyOperations.ts +343 -0
  460. package/security/authn/oidc/types.ts +41 -0
  461. package/security/certificateVerification/index.ts +54 -13
  462. package/security/certificateVerification/trustedIssuers.ts +76 -0
  463. package/security/certificateVerification/types.ts +1 -0
  464. package/security/credentialProvenance.ts +47 -0
  465. package/security/credentialRejection.ts +22 -0
  466. package/security/deferredAuthentication.ts +71 -0
  467. package/security/impersonation.ts +117 -12
  468. package/security/jsLoader.ts +81 -18
  469. package/security/keys.ts +298 -72
  470. package/security/operationScope.ts +33 -0
  471. package/security/permissionsTranslator.js +23 -0
  472. package/security/tokenAuthentication.ts +233 -12
  473. package/security/user.ts +4 -3
  474. package/server/DESIGN.md +183 -16
  475. package/server/DurableSubscriptionsSession.ts +71 -11
  476. package/server/REST.ts +79 -1
  477. package/server/graphqlQuerying.ts +4 -0
  478. package/server/http.ts +99 -18
  479. package/server/itc/serverHandlers.js +8 -1
  480. package/server/jobs/jobProcess.ts +8 -2
  481. package/server/jobs/jobs.ts +4 -1
  482. package/server/liveSubscriptionAuth.ts +129 -46
  483. package/server/loadRootComponents.js +50 -8
  484. package/server/mqtt.ts +179 -38
  485. package/server/nodeName.ts +103 -21
  486. package/server/serverHelpers/Headers.ts +131 -0
  487. package/server/serverHelpers/contentTypes.ts +29 -21
  488. package/server/serverHelpers/deployValidationState.ts +24 -13
  489. package/server/serverHelpers/operationAuthorizationState.ts +34 -3
  490. package/server/serverHelpers/registeredOperations.ts +79 -22
  491. package/server/serverHelpers/requestSanitization.ts +15 -0
  492. package/server/serverHelpers/serverHandlers.js +6 -3
  493. package/server/serverHelpers/serverUtilities.ts +104 -31
  494. package/server/serverHelpers/sharedMessageEncoding.ts +307 -0
  495. package/server/serverHelpers/uwsServer.ts +17 -2
  496. package/server/static.ts +23 -29
  497. package/server/storageReclamation.ts +23 -0
  498. package/server/threads/itc.js +11 -1
  499. package/server/threads/manageThreads.js +526 -56
  500. package/server/threads/socketRouter.ts +81 -26
  501. package/server/threads/threadHeapMemory.ts +26 -0
  502. package/server/threads/threadServer.js +43 -15
  503. package/sqlTranslator/index.ts +31 -8
  504. package/studio/web/assets/Chat-BnCBegQz.js +2267 -0
  505. package/studio/web/assets/FloatingChat-CoDW1ySS.js +23 -0
  506. package/studio/web/assets/{abnfDiagram-VCTEODGH-C0_BAZyO.js → abnfDiagram-VCTEODGH-B0BebmD2.js} +1 -1
  507. package/studio/web/assets/{alertDialog-DIHt7Z0r.js → alertDialog-CQyAJJhl.js} +1 -1
  508. package/studio/web/assets/{apiToken-c3Rd-w6g.js → apiToken-Bwk5BLXW.js} +1 -1
  509. package/studio/web/assets/applications-DHxGi7JH.js +296 -0
  510. package/studio/web/assets/architecture-7GRP2DOG-LB-MLAAb.js +1 -0
  511. package/studio/web/assets/{architectureDiagram-5GKGNRK7-BWzrASgm.js → architectureDiagram-5GKGNRK7-7SW3GD-K.js} +1 -1
  512. package/studio/web/assets/authStore-C3Nfubqr.js +3 -0
  513. package/studio/web/assets/{blockDiagram-NRAW4CY4-BdJX9Khj.js → blockDiagram-I7D4REHJ-BqguiadH.js} +2 -2
  514. package/studio/web/assets/{button-DhiX-njv.js → button-BIsUKRZq.js} +2 -2
  515. package/studio/web/assets/{c4Diagram-UCG6FXSJ-CI6MzGmQ.js → c4Diagram-7LVT6UL2-LBNf8t_X.js} +1 -1
  516. package/studio/web/assets/channel-yictG-U-.js +1 -0
  517. package/studio/web/assets/{chevron-up-Df2c8uoU.js → chevron-up-DtKGqDn3.js} +1 -1
  518. package/studio/web/assets/{chunk-TEH6E4GO-P87k5mNi.js → chunk-4HAMMTFA-DWtTut21.js} +1 -1
  519. package/studio/web/assets/{chunk-75Z2AOVW-BT8tVmks.js → chunk-75Z2AOVW-QGQD6th2.js} +1 -1
  520. package/studio/web/assets/{chunk-DU6HZSFF-9kAOOmI6.js → chunk-DU6HZSFF-Chq20Ba5.js} +1 -1
  521. package/studio/web/assets/{chunk-F27PBJKO-BW7ao8AY.js → chunk-F27PBJKO-BVA5EPhV.js} +1 -1
  522. package/studio/web/assets/{chunk-GMAD6QVW-BNyXpoQO.js → chunk-GMAD6QVW-BeS7S07A.js} +1 -1
  523. package/studio/web/assets/{chunk-OBVCFTLP-D4wWOqDQ.js → chunk-GVQU2GXP-sbwVIQ8i.js} +1 -1
  524. package/studio/web/assets/{chunk-G27WJ6UU-COyLMcgK.js → chunk-IMKFNOWR-Bnh3tAVd.js} +1 -1
  525. package/studio/web/assets/{chunk-JQ64N6SF-Cyz1IeLf.js → chunk-L3NEJ4N5-COfUyKII.js} +1 -1
  526. package/studio/web/assets/chunk-OSK3NFVY-ByciRftO.js +10 -0
  527. package/studio/web/assets/{chunk-P2QGCYS3-DmIFY4d7.js → chunk-P2QGCYS3-CP1VhG_c.js} +1 -1
  528. package/studio/web/assets/{chunk-POPQ4Y6H-BPrvMyKz.js → chunk-POPQ4Y6H-ClWhhkwW.js} +1 -1
  529. package/studio/web/assets/{chunk-PWAF6VOD-2zB6IW9i.js → chunk-PWAF6VOD-1z1THyS5.js} +1 -1
  530. package/studio/web/assets/{chunk-RHFEMEQ7-2FgyI8YU.js → chunk-SHT3W25Y-LpQkMsah.js} +2 -2
  531. package/studio/web/assets/{chunk-SVP7TREG-FwtbH2QC.js → chunk-SVP7TREG-jtdAHw0S.js} +1 -1
  532. package/studio/web/assets/{chunk-LCL6LL3I-HOzK_ppE.js → chunk-TICWLB2K-VOwzetX-.js} +1 -1
  533. package/studio/web/assets/classDiagram-ZZMXUADV-VaEwSy_g.js +1 -0
  534. package/studio/web/assets/classDiagram-v2-VYDZK3BY-VaEwSy_g.js +1 -0
  535. package/studio/web/assets/{createLucideIcon-BKGPfjm2.js → createLucideIcon-CzW9508A.js} +1 -1
  536. package/studio/web/assets/{cssMode-CEN2mzSA.js → cssMode-s0cWI-_M.js} +1 -1
  537. package/studio/web/assets/{cynefin-OW5HDTMX-BRkpLFQV.js → cynefin-OW5HDTMX-BbdbCvub.js} +1 -1
  538. package/studio/web/assets/{cynefinDiagram-5FMLGOSQ-CHT1DaX6.js → cynefinDiagram-5FMLGOSQ-TP-aIqbt.js} +1 -1
  539. package/studio/web/assets/{dagre-3AP2YEHR-DpUXBh63.js → dagre-GXQ25YYZ-DShnGpGo.js} +1 -1
  540. package/studio/web/assets/{diagram-S7CK7UJ4-BuymVFZT.js → diagram-S7CK7UJ4-aoCVTtcy.js} +1 -1
  541. package/studio/web/assets/{diagram-UQ7AKVKN-CyP148RM.js → diagram-UQ7AKVKN-DglXtQ6x.js} +1 -1
  542. package/studio/web/assets/{diagram-VSXAHHWV-CoCAg3M9.js → diagram-VSXAHHWV-fhEdmkwM.js} +1 -1
  543. package/studio/web/assets/{diagram-VX7I27RA-BpOqCFca.js → diagram-VX7I27RA-DccVJet6.js} +1 -1
  544. package/studio/web/assets/{diagram-Z3DM3KII-Bfpw7Vbj.js → diagram-Z3DM3KII-D-RyJJb7.js} +1 -1
  545. package/studio/web/assets/{dialog-CBf0Mr1d.js → dialog-Cn2uWgD4.js} +1 -1
  546. package/studio/web/assets/{dist-lkA3O3eM.js → dist-DP8UjMB_.js} +1 -1
  547. package/studio/web/assets/{download-BtTOBem-.js → download-B5T5r7ss.js} +1 -1
  548. package/studio/web/assets/{ebnfDiagram-PWID7BFC-DS_6aWqL.js → ebnfDiagram-PWID7BFC-DJGpIpz_.js} +1 -1
  549. package/studio/web/assets/{editor-D8oDeCTL.js → editor-DNcRHK54.js} +1 -1
  550. package/studio/web/assets/{erDiagram-SSCWMZ5O-DJNk6Fgw.js → erDiagram-RLTQ6QDP-CIfNlgkC.js} +1 -1
  551. package/studio/web/assets/eventmodeling-NTZA5JFV-CLxnp2CR.js +1 -0
  552. package/studio/web/assets/flowDiagram-HODETNUW-BIbhmz9f.js +1 -0
  553. package/studio/web/assets/{ganttDiagram-EL5Y4UJY-2pOExxMY.js → ganttDiagram-EL5Y4UJY-BxToTzzD.js} +1 -1
  554. package/studio/web/assets/{getAnalytics-D4LKGeVy.js → getAnalytics-GHK8ORfM.js} +1 -1
  555. package/studio/web/assets/{gitGraph-4MIJSDKK-CH5ZxwzF.js → gitGraph-4MIJSDKK-D2s2w8lE.js} +1 -1
  556. package/studio/web/assets/{gitGraphDiagram-WWUBYQGX-DVIsIhbO.js → gitGraphDiagram-WWUBYQGX-Dwntd4-x.js} +1 -1
  557. package/studio/web/assets/{html-u3vOg7LJ.js → html-Bdssedlg.js} +1 -1
  558. package/studio/web/assets/{htmlMode-DyO31v-P.js → htmlMode-CoDlJ3fw.js} +1 -1
  559. package/studio/web/assets/{index-Cxj2_wsl.css → index-7RMEgVG1.css} +1 -1
  560. package/studio/web/assets/index-D6sxmFLR.js +824 -0
  561. package/studio/web/assets/index.lazy-tmU5BS8s.js +2 -0
  562. package/studio/web/assets/{info-A6RAGUB7-CPQfTnaG.js → info-A6RAGUB7-DYjkvb0C.js} +1 -1
  563. package/studio/web/assets/{infoDiagram-RXCK75RN-DlwLYlwm.js → infoDiagram-27XIBGKW-Bnp1FJE5.js} +1 -1
  564. package/studio/web/assets/{ishikawaDiagram-5VMMS53U-BRXRp29U.js → ishikawaDiagram-5VMMS53U-D9Xh2r6X.js} +1 -1
  565. package/studio/web/assets/{javascript-CUvxOyTC.js → javascript-B8meVSTH.js} +1 -1
  566. package/studio/web/assets/{journeyDiagram-EYS64GPL-B0ou8k0n.js → journeyDiagram-3NMN7TZE-CokIi6ll.js} +2 -2
  567. package/studio/web/assets/{jsonMode-f_IwbF3D.js → jsonMode-DpIPd35T.js} +1 -1
  568. package/studio/web/assets/{kanban-definition-3QL26DDD-uYg7iYzp.js → kanban-definition-UXKFOSKX-CukSFJfX.js} +1 -1
  569. package/studio/web/assets/{languageServices-DXtZ6rEF.js → languageServices-C_5FMJzQ.js} +1 -1
  570. package/studio/web/assets/{lspLanguageFeatures-B4pCF1zO.js → lspLanguageFeatures-BIzNBzPK.js} +1 -1
  571. package/studio/web/assets/{mermaid-parser.core-Ck-fC8b7.js → mermaid-parser.core-BlEsOWNO.js} +3 -3
  572. package/studio/web/assets/{mermaid.core-CP8aNNYm.js → mermaid.core-BlkGaMIH.js} +5 -5
  573. package/studio/web/assets/{mindmap-definition-FBJOCRG2-CgTZ-rit.js → mindmap-definition-YA3MSWOX-IprMc_0j.js} +1 -1
  574. package/studio/web/assets/{notifications-D3tIQ4sg.js → notifications-CQf18QKb.js} +1 -1
  575. package/studio/web/assets/notifications-CvZivSbh.js +1 -0
  576. package/studio/web/assets/{packet-AYTQ26CC-DEyoPtPb.js → packet-AYTQ26CC-Bi3V04Zi.js} +1 -1
  577. package/studio/web/assets/{pegDiagram-XKGWAZYB-DrD-7sD9.js → pegDiagram-XKGWAZYB-BNuPDLZY.js} +1 -1
  578. package/studio/web/assets/{pie-WAS4IAKB-wjj-EI1d.js → pie-WAS4IAKB-_6DoDbng.js} +1 -1
  579. package/studio/web/assets/{pieDiagram-E7YTZNPT-GntqDCzv.js → pieDiagram-E7YTZNPT-DqNb6Ht2.js} +1 -1
  580. package/studio/web/assets/{profile-DZWU7MgT.js → profile-DdOwtntb.js} +1 -1
  581. package/studio/web/assets/{quadrantDiagram-AXDQQJYC-0UeqXQGd.js → quadrantDiagram-AXDQQJYC-BGH9E2YR.js} +1 -1
  582. package/studio/web/assets/{radar-RG4KPBEZ-DFSA5h7k.js → radar-RG4KPBEZ-DDdVczcL.js} +1 -1
  583. package/studio/web/assets/{railroad-74A4TZTK-CaOUG9wR.js → railroad-74A4TZTK-BJUP4Jds.js} +1 -1
  584. package/studio/web/assets/railroad-abnf-HS5TGJTU-Bm3L1L0h.js +1 -0
  585. package/studio/web/assets/railroad-ebnf-LZEXJU2U-CKzLGlkw.js +1 -0
  586. package/studio/web/assets/railroad-peg-WCYAUIDC-S8xLjslx.js +1 -0
  587. package/studio/web/assets/{railroadDiagram-O6MQD6OU-yHUELZaV.js → railroadDiagram-O6MQD6OU-DGTPh2KZ.js} +1 -1
  588. package/studio/web/assets/{regions-CkyurXzE.js → regions-n69fwagr.js} +1 -1
  589. package/studio/web/assets/{register-BUyhWjBO.js → register-PfWTCXWB.js} +3 -3
  590. package/studio/web/assets/{requirementDiagram-EFPCY7ZU-DNEGFjuW.js → requirementDiagram-BXWQKSXE-BJnO6uLz.js} +1 -1
  591. package/studio/web/assets/{sankeyDiagram-P5KCCOFB-DpyAmSVR.js → sankeyDiagram-P5KCCOFB-0vSOdymH.js} +1 -1
  592. package/studio/web/assets/{sequenceDiagram-WJ2MYXX4-TyaT7xNk.js → sequenceDiagram-WJ2MYXX4-hETizDWE.js} +1 -1
  593. package/studio/web/assets/{setComponentFile-CeyKSZAa.js → setComponentFile-Bg6O7X0S.js} +1 -1
  594. package/studio/web/assets/{setup-D2kn7cAA.js → setup-CUx_aUDl.js} +2 -2
  595. package/studio/web/assets/{stateDiagram-HBIQ2CUA-CeEdTArZ.js → stateDiagram-D77RDMKH-CdYQ_KtC.js} +1 -1
  596. package/studio/web/assets/stateDiagram-v2-MP3YSRHH-CdKuzQMT.js +1 -0
  597. package/studio/web/assets/status-D7BVKqX9.js +61 -0
  598. package/studio/web/assets/{swimlanes-XN3QIQJK-B54FmF46.js → swimlanes-42K2YHIH-B8cHIpU4.js} +1 -1
  599. package/studio/web/assets/swimlanesDiagram-VR7AAH4N-DmOSJwaH.js +8 -0
  600. package/studio/web/assets/{tabs-B_G5zscN.js → tabs-BrHu7gJi.js} +1 -1
  601. package/studio/web/assets/{timeline-definition-24CTP7MA-D-a9ujbo.js → timeline-definition-24CTP7MA-BJWYSXqF.js} +1 -1
  602. package/studio/web/assets/{toggleHighContrast-C0UW6rI2.js → toggleHighContrast-DBSyXzMr.js} +1 -1
  603. package/studio/web/assets/{treeView-Q6P3EWNA-CrW_6JnS.js → treeView-Q6P3EWNA-qxe_v6CQ.js} +1 -1
  604. package/studio/web/assets/{treemap-WGGIJYW6-BxyYLdP_.js → treemap-WGGIJYW6-dDo97XXF.js} +1 -1
  605. package/studio/web/assets/{tsMode-DBC0zmDx.js → tsMode-BByKCjBS.js} +1 -1
  606. package/studio/web/assets/{typescript-DApRQir3.js → typescript-DDLnLpw9.js} +1 -1
  607. package/studio/web/assets/{useEntityRestURL-DB6JStU1.js → useEntityRestURL-31CHGaHk.js} +1 -1
  608. package/studio/web/assets/{useLocalStorage-Dtj1QS8_.js → useLocalStorage-BqMR3D8_.js} +1 -1
  609. package/studio/web/assets/vendor-core-c2JRRJpV.js +58 -0
  610. package/studio/web/assets/vendor-datadog-CLUcJXOo.js +6 -0
  611. package/studio/web/assets/{vendor-react-Dyj4O3HE.js → vendor-react-CJV_K1u4.js} +1 -1
  612. package/studio/web/assets/vendor-tanstack-DxzraizX.js +1 -0
  613. package/studio/web/assets/{vendor-ui-vhu-UHhF.js → vendor-ui-BUjK0h8a.js} +2 -2
  614. package/studio/web/assets/{vennDiagram-4TSXK5OY-Cy7s7Mpy.js → vennDiagram-4TSXK5OY-A3i-lCdl.js} +1 -1
  615. package/studio/web/assets/{wardley-WFR3VGLG-BeBL35g2.js → wardley-WFR3VGLG-B0ik-_6g.js} +1 -1
  616. package/studio/web/assets/{wardleyDiagram-VM6X3IG4-BylmIGSg.js → wardleyDiagram-VM6X3IG4-CjrkKWUR.js} +1 -1
  617. package/studio/web/assets/{workers-C0bFIedw.js → workers-pR3jRY9D.js} +1 -1
  618. package/studio/web/assets/x-DIzaLEdK.js +1 -0
  619. package/studio/web/assets/{xml-HWd01lU-.js → xml-2iRnMhQO.js} +1 -1
  620. package/studio/web/assets/{xychartDiagram-S5SC5T6Z-CoKALMXr.js → xychartDiagram-S5SC5T6Z-Biok4GYV.js} +1 -1
  621. package/studio/web/assets/{yaml-CIH0Nt-h.js → yaml-Bf92gJpd.js} +1 -1
  622. package/studio/web/index.html +14 -14
  623. package/upgrade/directives/5-3-0.ts +132 -0
  624. package/upgrade/directives/directivesController.ts +2 -1
  625. package/utility/OperationFunctionCaller.ts +2 -1
  626. package/utility/common_utils.ts +30 -5
  627. package/utility/componentNames.ts +12 -0
  628. package/utility/environment/environmentManager.ts +3 -7
  629. package/utility/environment/systemInformation.ts +7 -0
  630. package/utility/errors/commonErrors.ts +4 -0
  631. package/utility/errors/hdbError.ts +29 -0
  632. package/utility/hdbTerms.ts +17 -0
  633. package/utility/logging/harper_logger.ts +87 -14
  634. package/utility/logging/logRotator.ts +72 -45
  635. package/utility/nodeIdentity.ts +45 -0
  636. package/utility/npmUtilities.ts +10 -8
  637. package/utility/operationPermissions.ts +18 -1
  638. package/utility/operation_authorization.ts +231 -42
  639. package/utility/watchPath.ts +63 -0
  640. package/utility/watcherFallback.ts +270 -0
  641. package/validation/configValidator.ts +209 -72
  642. package/validation/installValidator.ts +15 -0
  643. package/validation/validationWrapper.ts +18 -4
  644. package/studio/web/assets/Chat-JpO8EtUu.js +0 -2067
  645. package/studio/web/assets/FloatingChat-Bcj3xSZu.js +0 -23
  646. package/studio/web/assets/applications-ByqLRKyZ.js +0 -296
  647. package/studio/web/assets/architecture-7GRP2DOG-DNdx5tEU.js +0 -1
  648. package/studio/web/assets/authStore-qKmCZcaf.js +0 -3
  649. package/studio/web/assets/channel-DtCV8PTL.js +0 -1
  650. package/studio/web/assets/chunk-R7TYR2AO-Irip67yr.js +0 -10
  651. package/studio/web/assets/classDiagram-DTDB5LWJ-DbO_dCNE.js +0 -1
  652. package/studio/web/assets/classDiagram-v2-JRS7N3AN-DbO_dCNE.js +0 -1
  653. package/studio/web/assets/eventmodeling-NTZA5JFV-5jbe4A5P.js +0 -1
  654. package/studio/web/assets/flowDiagram-A5DVABFB-Dp9Ezlow.js +0 -1
  655. package/studio/web/assets/index-aSt5tY-L.js +0 -824
  656. package/studio/web/assets/index.lazy-B9jiPwT8.js +0 -2
  657. package/studio/web/assets/notifications-CUoYgU98.js +0 -1
  658. package/studio/web/assets/railroad-abnf-HS5TGJTU-Bc0Qi0WH.js +0 -1
  659. package/studio/web/assets/railroad-ebnf-LZEXJU2U-G8rVVZ2C.js +0 -1
  660. package/studio/web/assets/railroad-peg-WCYAUIDC-CrehKBhC.js +0 -1
  661. package/studio/web/assets/stateDiagram-v2-4QOOHH4V-D4tuw9Su.js +0 -1
  662. package/studio/web/assets/status-D7Xn5ePA.js +0 -61
  663. package/studio/web/assets/swimlanesDiagram-VK2B7HYN-XOhmNEvq.js +0 -8
  664. package/studio/web/assets/vendor-core-RCcadM3e.js +0 -73
  665. package/studio/web/assets/vendor-datadog-BRv-mOv1.js +0 -6
  666. package/studio/web/assets/vendor-tanstack-BiFWSB3W.js +0 -1
  667. package/studio/web/assets/x-B9o9hsep.js +0 -1
  668. /package/studio/web/assets/{sizeCapture-X5ZJPWSS-B0uUizjq.js → sizeCapture-INFHLROL-B0uUizjq.js} +0 -0
@@ -0,0 +1,343 @@
1
+ 'use strict';
2
+
3
+ // Operations against system.hdb_oidc_trust — the trust policies for OIDC trusted publishing (#2171).
4
+ //
5
+ // A policy lets an external CI run authenticate as a Harper user without holding any Harper
6
+ // credential, so these are super_user only. Following components/secretOperations.ts, super_user is
7
+ // enforced in-handler as well as via requiredPermissions: a role's `operations` allowlist can
8
+ // otherwise delegate an SU-only operation (see the gate-2 bypass in utility/operation_authorization.ts).
9
+ //
10
+ // Rows reach peers through normal system-table replication; these operations deliberately do not
11
+ // call replicateOperation, which would double-apply on top of it.
12
+
13
+ import Joi from 'joi';
14
+ import { databases } from '../../../resources/databases.ts';
15
+ import * as terms from '../../../utility/hdbTerms.ts';
16
+ import { ClientError, hdbErrors } from '../../../utility/errors/hdbError.ts';
17
+ import { validateBySchema } from '../../../validation/validationWrapper.ts';
18
+ import { loggerWithTag } from '../../../utility/logging/logger.ts';
19
+ import { getUsersWithRolesCache } from '../../user.ts';
20
+ import { validateClaimConstraintShape } from './claims.ts';
21
+ import { normalizeIssuer } from './jwks.ts';
22
+ import { profileForIssuer } from './providers/index.ts';
23
+ import { validateOperations } from '../../../utility/operationPermissions.ts';
24
+ import type { OidcTrustPolicy } from './types.ts';
25
+
26
+ const { HTTP_STATUS_CODES } = hdbErrors;
27
+ const OIDC_TRUST_TABLE = terms.SYSTEM_TABLE_NAMES.OIDC_TRUST_TABLE_NAME;
28
+ // Same tag as tokenExchange: an ignored row and the exchange that ignored it belong in one stream.
29
+ const logger = loggerWithTag('oidc-trust');
30
+
31
+ const POLICY_ID = Joi.string()
32
+ .min(1)
33
+ .max(128)
34
+ .pattern(/^[\w.-]+$/)
35
+ .required()
36
+ .messages({ 'string.pattern.base': "'id' may contain only letters, numbers, '_', '-', and '.'" });
37
+
38
+ function requireSuperUser(req: any): void {
39
+ if (!req?.hdb_user?.role?.permission?.super_user) {
40
+ throw new ClientError(
41
+ `Operation '${req?.operation}' is restricted to super_user roles`,
42
+ HTTP_STATUS_CODES.FORBIDDEN
43
+ );
44
+ }
45
+ }
46
+
47
+ function validate(validation: any): void {
48
+ if (validation) throw new ClientError(validation.message);
49
+ }
50
+
51
+ /**
52
+ * A typo would otherwise fail closed at request time, in CI, with nothing to point at — so it is
53
+ * caught here, where the reader is the administrator who wrote it. Delegates to the same helper
54
+ * add_role/alter_role use, so group names resolve identically rather than through a second
55
+ * definition that could drift.
56
+ */
57
+ function assertOperationsAreKnown(operations: string[]): void {
58
+ const invalidOperation = validateOperations(operations);
59
+ if (invalidOperation != null) {
60
+ throw new ClientError(`operations contains '${invalidOperation}', which is not a Harper operation`);
61
+ }
62
+ }
63
+
64
+ /**
65
+ * The audience is matched by exact string equality at verification time (`jwt.verify`), and the CLI
66
+ * asks its provider for a token whose audience is `normalizeTarget(target)` — which supplies `:9925`
67
+ * when no port was written, and a trailing slash. So `audience=https://my-instance.example.com`, the
68
+ * natural reading of "the instance URL the CI client targets", stores a policy that can never match
69
+ * anything; the exchange then refuses with the same opaque message it gives every other failure,
70
+ * leaving the operator nothing to look at, in CI. Caught here instead, where the reader is the
71
+ * administrator who wrote it — the same bargain assertOperationsAreKnown makes.
72
+ *
73
+ * Rejected rather than rewritten: silently canonicalizing a value whose whole job is to be compared
74
+ * byte-for-byte is worse than refusing it, and it would also have to run after the profile's
75
+ * shared-audience guard to avoid disarming it. Stating the requirement keeps this independent of
76
+ * normalizeTarget's exact spelling rules, which live in the CLI; a unit test pins the two together.
77
+ *
78
+ * Only http(s) URLs are shaped this way. An issuer-specific audience (an `api://` identifier, a bare
79
+ * GUID) is not ours to constrain, so anything that is not an http(s) URL passes untouched.
80
+ */
81
+ function assertAudienceIsCanonical(audience: string): void {
82
+ let url: URL;
83
+ try {
84
+ url = new URL(audience);
85
+ } catch {
86
+ return;
87
+ }
88
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') return;
89
+
90
+ // `url.port` is empty for a default port, so consult the raw authority — with any userinfo
91
+ // removed first, since that colon is not a port.
92
+ const authority = audience.slice(audience.indexOf('://') + 3).split(/[/?#]/)[0];
93
+ const hasExplicitPort = !!url.port || authority.slice(authority.lastIndexOf('@') + 1).includes(':');
94
+ if (hasExplicitPort && audience.endsWith('/')) return;
95
+
96
+ throw new ClientError(
97
+ `'audience' must be the exact string the CI client requests its token for, which includes an ` +
98
+ `explicit port and a trailing slash (for example 'https://my-instance.example.com:9925/'). ` +
99
+ `'${audience}' is missing ${!hasExplicitPort ? 'a port' : 'a trailing slash'}, and the match is ` +
100
+ `byte-for-byte, so the policy could never authenticate.`
101
+ );
102
+ }
103
+
104
+ function trustTable() {
105
+ const table = (databases as any).system?.[OIDC_TRUST_TABLE];
106
+ if (!table) {
107
+ throw new ClientError(
108
+ `OIDC trust policies are not initialized on this node (system.${OIDC_TRUST_TABLE} missing). ` +
109
+ `Run upgrade or restart the server to provision the table.`
110
+ );
111
+ }
112
+ return table;
113
+ }
114
+
115
+ /**
116
+ * Rebuild a plain record from a stored row's known attributes. Never spread rows — RecordObject
117
+ * prototype fields don't survive a spread reliably (see DESIGN.md).
118
+ */
119
+ function toRecord(row: any, problem?: string): OidcTrustPolicy & Record<string, unknown> {
120
+ return {
121
+ id: row.id,
122
+ issuer: row.issuer,
123
+ audience: row.audience,
124
+ claims: row.claims ?? {},
125
+ user: row.user,
126
+ operations: row.operations ?? null,
127
+ // Reported as stored rather than coerced. `row.enabled !== false` would render the string
128
+ // 'false' — one of the shapes the exchange refuses — as `enabled: true`, telling the operator
129
+ // a dead trust is live. Absent still means enabled, which is the documented default.
130
+ enabled: row.enabled === undefined ? true : row.enabled,
131
+ // Present only on a row the exchange will refuse, so a listing says why the trust is dead
132
+ // instead of leaving a per-attempt log line as the only signal. Shape problems are set here;
133
+ // listOidcTrust adds the ones that depend on state outside the row (a missing or inactive user).
134
+ ...(problem ? { invalid_reason: problem } : {}),
135
+ description: row.description ?? null,
136
+ updated_by: row.updated_by ?? null,
137
+ __createdtime__: row.__createdtime__,
138
+ __updatedtime__: row.__updatedtime__,
139
+ } as any;
140
+ }
141
+
142
+ /**
143
+ * The policy set is small and administrator-managed, so a scan beats maintaining an index — and
144
+ * sorting by id keeps both the listing and the exchange's match order deterministic rather than
145
+ * dependent on an index's iteration order.
146
+ */
147
+ async function readPolicies(
148
+ includeDisabled: boolean,
149
+ issuer?: string,
150
+ forExchange = false
151
+ ): Promise<OidcTrustPolicy[]> {
152
+ const table = trustTable();
153
+ const policies: OidcTrustPolicy[] = [];
154
+ for await (const row of table.search([])) {
155
+ if (!includeDisabled && row.enabled === false) continue;
156
+ if (issuer !== undefined && row.issuer !== issuer) continue;
157
+ // Validated on BOTH paths, always against the RAW row — normalizing first is precisely what
158
+ // hides the shapes that fail open (see storedPolicyProblem). The two paths then differ in what
159
+ // they do with the answer: the exchange refuses the row, while a listing reports it. A listing
160
+ // that silently skipped a refused policy, or that showed it as healthy, would leave the
161
+ // operator's belief that the trust works corroborated by the very command they ran to check.
162
+ const problem = storedPolicyProblem(row);
163
+ if (forExchange) {
164
+ if (problem) {
165
+ logger.warn?.(`Ignoring trust policy '${row.id}': ${problem}`);
166
+ continue;
167
+ }
168
+ }
169
+ policies.push(toRecord(row, problem));
170
+ }
171
+ return policies.sort((a, b) => String(a.id).localeCompare(String(b.id)));
172
+ }
173
+
174
+ /**
175
+ * Why a stored row must not be honored, or undefined if it is usable.
176
+ *
177
+ * add_oidc_trust enforces all of this at write time, but a row can reach the table another way —
178
+ * replication from a node predating a check, a restored backup, a direct write to the system table —
179
+ * so the exchange re-runs the same validators rather than trusting that every row was validated when
180
+ * written. Two shapes in particular fail OPEN if merely normalized instead of rejected:
181
+ *
182
+ * operations: 'deploy_component' — a scalar rather than an array. hasOperationScope tests
183
+ * Array.isArray, so the scope is silently dropped and the token is minted UNSCOPED, carrying the
184
+ * policy user's entire role. A malformed narrowing must never widen.
185
+ * enabled: 'false' — a string. `row.enabled !== false` is true for it, so a policy
186
+ * an operator meant to disable keeps minting tokens.
187
+ *
188
+ * Shares validateOperations and validateClaimConstraintShape with the add path deliberately: two
189
+ * implementations of "is this row valid" is how the write path and the read path drift apart.
190
+ */
191
+ export function storedPolicyProblem(row: any): string | undefined {
192
+ if (row.enabled !== undefined && typeof row.enabled !== 'boolean') {
193
+ return `'enabled' is a ${typeof row.enabled}, not a boolean`;
194
+ }
195
+ if (row.operations != null) {
196
+ if (!Array.isArray(row.operations)) return `'operations' is a ${typeof row.operations}, not an array`;
197
+ const invalidOperation = validateOperations(row.operations);
198
+ if (invalidOperation != null) return `operations contains '${invalidOperation}', which is not a Harper operation`;
199
+ }
200
+ try {
201
+ validateClaimConstraintShape(row.claims);
202
+ } catch (error) {
203
+ return (error as Error).message;
204
+ }
205
+ return undefined;
206
+ }
207
+
208
+ /**
209
+ * The policies the exchange will consider, narrowed to one issuer.
210
+ *
211
+ * Filtered inside the scan rather than by the caller: the exchange is unauthenticated and reaches
212
+ * here having done nothing but `jwt.decode`, so an anonymous caller presenting any syntactically
213
+ * valid JWT would otherwise drive a `toRecord()` allocation for every stored policy before anything
214
+ * has been verified. The scan itself stays — the table is administrator-sized, and an index here
215
+ * would buy little (see readPolicies) — but non-matching rows now cost nothing beyond the compare.
216
+ *
217
+ * A missing table yields no policies rather than throwing. On a node where the upgrade directive has
218
+ * not run, trustTable()'s descriptive ClientError would surface to an anonymous caller as a 400 with
219
+ * a body unlike the uniform 401 every other rejection returns, which both leaks node state and
220
+ * breaks the single-message property. The SU-only add/list/drop handlers still get that error, where
221
+ * it is the useful thing to say.
222
+ */
223
+ export function loadEnabledPolicies(issuer: string): Promise<OidcTrustPolicy[]> {
224
+ if (!(databases as any).system?.[OIDC_TRUST_TABLE]) return Promise.resolve([]);
225
+ return readPolicies(false, issuer, true);
226
+ }
227
+
228
+ /**
229
+ * Creates or replaces a trust policy.
230
+ *
231
+ * Replace rather than merge: a partial update to a claim set is how an over-broad policy gets
232
+ * created by accident, and the whole point of `claims` is that every constraint in it was written
233
+ * deliberately.
234
+ */
235
+ export async function addOidcTrust(req: any) {
236
+ requireSuperUser(req);
237
+ validate(
238
+ validateBySchema(
239
+ req,
240
+ Joi.object({
241
+ id: POLICY_ID,
242
+ issuer: Joi.string().min(1).max(512).required(),
243
+ audience: Joi.string().min(1).max(512).required(),
244
+ claims: Joi.object().min(1).required(),
245
+ user: Joi.string().min(1).max(512).required(),
246
+ operations: Joi.array().items(Joi.string().min(1)).min(1).max(100).unique(),
247
+ // `.strict()` — Joi coerces by default, but validateBySchema keeps only `result.error`
248
+ // and discards the converted value, so `"false"` would validate cleanly and then be
249
+ // stored as the string it arrived as. `req.enabled !== false` is true for that string,
250
+ // which silently leaves a policy an operator meant to disable still minting tokens.
251
+ // A revocation control has to fail closed, so reject the string outright.
252
+ enabled: Joi.boolean().strict(),
253
+ description: Joi.string().allow('').max(1024),
254
+ }).unknown(true)
255
+ )
256
+ );
257
+
258
+ const issuer = normalizeIssuer(req.issuer);
259
+ // Issuer-specific rules live in the provider profile; an unregistered issuer gets the strict
260
+ // generic profile rather than a permissive default. Each throws ClientError naming the problem.
261
+ const profile = profileForIssuer(issuer);
262
+ // On the RAW audience, before the canonical-form check below. GitHub's shared-audience guard
263
+ // matches `https://github.com/<owner>`, and a canonicalized form of that would no longer match
264
+ // the regex — checking the other way round would silently disarm it.
265
+ profile.assertAudienceIsSpecific(req.audience);
266
+ assertAudienceIsCanonical(req.audience);
267
+ if (req.operations) assertOperationsAreKnown(req.operations);
268
+ validateClaimConstraintShape(req.claims);
269
+ profile.assertPolicyIsSpecific(req.claims);
270
+
271
+ // Resolve the target user now: a policy pointing at a user that does not exist would fail only at
272
+ // exchange time, in CI, with nothing to point at. Read the users cache directly rather than
273
+ // findAndValidateUser — with validatePassword false, that returns a bare `{ username }` for an
274
+ // unknown user instead of failing, so it cannot answer "does this user exist".
275
+ const users = await getUsersWithRolesCache();
276
+ const targetUser = users?.get(req.user);
277
+ if (!targetUser) {
278
+ throw new ClientError(`No such user '${req.user}'; create the user before granting it to a workflow`);
279
+ }
280
+ if (targetUser.active === false) {
281
+ throw new ClientError(`User '${req.user}' is inactive; a policy naming it could never authenticate`);
282
+ }
283
+
284
+ const table = trustTable();
285
+ await table.put({
286
+ id: req.id,
287
+ issuer,
288
+ audience: req.audience,
289
+ claims: req.claims,
290
+ user: req.user,
291
+ operations: req.operations ?? null,
292
+ enabled: req.enabled !== false,
293
+ description: req.description ?? null,
294
+ updated_by: req.hdb_user?.username ?? null,
295
+ });
296
+
297
+ const result: Record<string, unknown> = { message: `Successfully set OIDC trust policy '${req.id}'` };
298
+ // Not an error — an admin may genuinely want this — but a policy that hands super_user to a
299
+ // workflow deserves to be said out loud rather than discovered later.
300
+ if (targetUser.role?.permission?.super_user) {
301
+ result.warning =
302
+ `Policy '${req.id}' authenticates as '${req.user}', which is a super_user. Any run matching this ` +
303
+ `policy gains full administrative access; consider a user whose role grants only the operations CI needs.`;
304
+ }
305
+ return result;
306
+ }
307
+
308
+ export async function listOidcTrust(req: any) {
309
+ requireSuperUser(req);
310
+ const policies = await readPolicies(true);
311
+
312
+ // The exchange also refuses a well-formed row whose user has since been deleted or deactivated
313
+ // (tokenExchange resolves it before spending the token), with the same opaque 401 — so without
314
+ // this the listing would still say the trust is fine for the most mundane arrival of all: someone
315
+ // deletes or deactivates the CI user and every deploy starts failing.
316
+ //
317
+ // Annotated here rather than in readPolicies, and deliberately: this is one cache read for the
318
+ // whole listing on an SU-only path, where doing it per row in readPolicies would put a user lookup
319
+ // on the unauthenticated exchange path, which already resolves the user itself at the right moment.
320
+ // A shape problem already reported wins, since it is the more fundamental complaint.
321
+ const users = await getUsersWithRolesCache();
322
+ for (const policy of policies as any[]) {
323
+ if (policy.invalid_reason) continue;
324
+ const user = users?.get(policy.user);
325
+ if (!user) policy.invalid_reason = `names user '${policy.user}', which does not exist`;
326
+ else if (user.active === false) policy.invalid_reason = `names inactive user '${policy.user}'`;
327
+ }
328
+
329
+ return { policies };
330
+ }
331
+
332
+ export async function dropOidcTrust(req: any) {
333
+ requireSuperUser(req);
334
+ validate(validateBySchema(req, Joi.object({ id: POLICY_ID }).unknown(true)));
335
+
336
+ const table = trustTable();
337
+ const row = await table.get(req.id);
338
+ if (!row) {
339
+ throw new ClientError(`No OIDC trust policy found with id '${req.id}'`, HTTP_STATUS_CODES.NOT_FOUND);
340
+ }
341
+ await table.delete(req.id);
342
+ return { message: `Successfully dropped OIDC trust policy '${req.id}'` };
343
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Types for OIDC trusted publishing (#2171).
3
+ */
4
+
5
+ /** One accepted value, or a set of them. */
6
+ export type ClaimConstraint = string | string[];
7
+
8
+ /**
9
+ * A stored trust policy. Matching one lets an external CI run act as `user` without holding any
10
+ * Harper credential, so `claims` is validated at write time rather than trusted as written — see
11
+ * validateClaimConstraintShape (claims.ts) and the profile's assertPolicyIsSpecific for the
12
+ * structural requirements, and addOidcTrust for the rest.
13
+ */
14
+ export interface OidcTrustPolicy {
15
+ id: string;
16
+ /** Expected `iss`, and the base for OIDC discovery. */
17
+ issuer: string;
18
+ /** Expected `aud`. Must identify this instance — see SHARED_DEFAULT_AUDIENCE. */
19
+ audience: string;
20
+ claims: Record<string, ClaimConstraint>;
21
+ /** The exchanged token authenticates as this user, whose role is the least-privilege boundary. */
22
+ user: string;
23
+ /**
24
+ * Optional narrowing of that boundary, enforced on the **operations API and SQL** paths (the
25
+ * verifyPerms / verifyPermsAST gate): the minted token may invoke only these operations, even
26
+ * where the role allows more. Never widens — an operation the role forbids stays forbidden.
27
+ *
28
+ * NOT enforced on the application REST/GraphQL resource path, which authorizes through the
29
+ * table-level checkPermission and does not consult this scope — so a scoped operation token still
30
+ * carries the role's full CRUD there. Extending the scope to the resource path is a follow-up on
31
+ * the same surface as the GraphQL-bypasses-ops-allowlist gap (CORE-3061); until then, scope a
32
+ * policy's `user` to a role that is itself least-privilege for the data the token can reach.
33
+ */
34
+ operations?: string[];
35
+ /** Defaults to true; false keeps the policy for reference without honoring it. */
36
+ enabled?: boolean;
37
+ description?: string;
38
+ }
39
+
40
+ /** A verified token's payload, plus the entries the profile's normalizeClaims derives. */
41
+ export type TokenClaims = Record<string, unknown>;
@@ -27,10 +27,14 @@ import { extractCertificateChain, extractRevocationUrls, bufferToPem } from './v
27
27
  import { getCachedCertificateVerificationConfig } from './verificationConfig.ts';
28
28
  import { verifyOCSP } from './ocspVerification.ts';
29
29
  import { verifyCRL } from './crlVerification.ts';
30
- import type { PeerCertificate, CertificateVerificationResult } from './types.ts';
30
+ import { resolveTrustedIssuer } from './trustedIssuers.ts';
31
+ import type { PeerCertificate, CertificateVerificationResult, FailureMode } from './types.ts';
31
32
 
32
33
  const logger = loggerWithTag('cert-verification');
33
34
 
35
+ const warnedUnresolvedLeaves = new Set<string>();
36
+ const MAX_WARNED_LEAVES = 10_000;
37
+
34
38
  /**
35
39
  * Verify certificate revocation status using OCSP and/or CRL
36
40
  * @param peerCertificate - Peer certificate object from TLS connection
@@ -52,14 +56,32 @@ export async function verifyCertificate(
52
56
  return { valid: true, status: 'disabled', method: 'disabled' };
53
57
  }
54
58
 
59
+ // ahead of the chain check so an explicitly disabled control can never reject
60
+ if (config.crl.enabled === false && config.ocsp.enabled === false) {
61
+ logger.debug?.('Both CRL and OCSP disabled - verification disabled');
62
+ return { valid: true, status: 'disabled', method: 'disabled' };
63
+ }
64
+
55
65
  // Extract certificate chain
56
66
  const certChain = extractCertificateChain(peerCertificate);
57
67
  logger.trace?.(`Certificate chain length: ${certChain.length}`);
58
68
 
59
- // Check if we have sufficient chain for verification (need certificate and issuer)
60
- if (certChain.length < 2 || !certChain[0].issuer) {
61
- logger.debug?.('Certificate chain insufficient for revocation checking - need certificate and issuer');
62
- return { valid: true, status: 'no-issuer-cert', method: 'disabled' };
69
+ if (certChain.length === 0) {
70
+ return unresolvedIssuerResult(config.failureMode, peerCertificate, 'no certificate data');
71
+ }
72
+ // Revocation checking needs the issuer. The socket omits it on every resumed TLS session and on
73
+ // Node 26.8.0/26.8.1 (nodejs/node#65579); recover it from the CA set that authorized the client.
74
+ if (!certChain[0].issuer) {
75
+ const issuer = resolveTrustedIssuer(certChain[0].cert, peerCertificate.fingerprint256);
76
+ if (!issuer) {
77
+ return unresolvedIssuerResult(
78
+ config.failureMode,
79
+ peerCertificate,
80
+ 'issuer is neither in the presented chain nor among the configured certificate authorities'
81
+ );
82
+ }
83
+ logger.debug?.('Issuer certificate resolved from the configured certificate authorities');
84
+ certChain[0].issuer = issuer;
63
85
  }
64
86
 
65
87
  // Extract certificate revocation URLs in single parse operation
@@ -117,17 +139,36 @@ export async function verifyCertificate(
117
139
  logger.debug?.('Skipping OCSP - no responder URLs in certificate');
118
140
  }
119
141
 
120
- // All methods tried or skipped - determine failure handling
121
- // If both methods are explicitly disabled (not just unavailable), treat as disabled
122
- if (config.crl.enabled === false && config.ocsp.enabled === false) {
123
- logger.debug?.('Both CRL and OCSP disabled - verification disabled');
124
- return { valid: true, status: 'disabled', method: 'disabled' };
125
- }
126
-
127
- // Methods are enabled but unavailable - apply failure mode
142
+ // All methods tried or skipped - apply failure mode
128
143
  if (config.failureMode === 'fail-closed') {
129
144
  return { valid: false, status: 'no-verification-available', method: 'disabled' };
130
145
  }
131
146
 
132
147
  return { valid: true, status: 'verification-unavailable-allowed', method: 'disabled' };
133
148
  }
149
+
150
+ /**
151
+ * Revocation status cannot be established without the issuer, so the configured failure mode
152
+ * decides: refuse under fail-closed, allow under fail-open. Either way this is a security control
153
+ * not running, so it is logged at warn (once per certificate) rather than debug.
154
+ */
155
+ function unresolvedIssuerResult(
156
+ failureMode: FailureMode | undefined,
157
+ peerCertificate: PeerCertificate,
158
+ reason: string
159
+ ): CertificateVerificationResult {
160
+ const valid = failureMode !== 'fail-closed';
161
+ const leafKey = peerCertificate.fingerprint256 ?? peerCertificate.subject?.CN ?? '';
162
+ if (!warnedUnresolvedLeaves.has(leafKey)) {
163
+ if (warnedUnresolvedLeaves.size >= MAX_WARNED_LEAVES) warnedUnresolvedLeaves.clear();
164
+ warnedUnresolvedLeaves.add(leafKey);
165
+ logger.warn?.(
166
+ `Cannot check revocation status for client certificate ${peerCertificate.subject?.CN ?? 'unknown'}: ${reason}; ${
167
+ valid ? 'allowing connection (fail-open)' : 'rejecting connection (fail-closed)'
168
+ }`
169
+ );
170
+ } else {
171
+ logger.debug?.(`Cannot check revocation status for ${peerCertificate.subject?.CN ?? 'unknown'}: ${reason}`);
172
+ }
173
+ return { valid, status: 'no-issuer-cert', method: 'disabled' };
174
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Resolves a client certificate's issuer from Harper's own trusted certificate authorities.
3
+ *
4
+ * Node completes a peer chain from the trust store only through the listener's default TLS
5
+ * context; Harper's client CAs live on the SNI contexts built by createTLSSelector, so whenever the
6
+ * client-sent chain is unavailable (every resumed TLS session; Node 26.8.0/26.8.1 on every
7
+ * connection, nodejs/node#65579) getPeerCertificate(true) exposes the leaf alone. The CA set that
8
+ * authorized the connection is the same set published here, so the issuer is recoverable from it
9
+ * unless it is an intermediate the client sent but Harper does not trust directly.
10
+ */
11
+
12
+ import { X509Certificate, createHash } from 'node:crypto';
13
+
14
+ const PEM_CERTIFICATE_PATTERN =
15
+ /-----BEGIN (?:TRUSTED |X509 )?CERTIFICATE-----[\s\S]*?-----END (?:TRUSTED |X509 )?CERTIFICATE-----/g;
16
+ const MAX_RESOLVED_LEAVES = 10_000;
17
+
18
+ let trustedAuthorities: X509Certificate[] = [];
19
+ let publishedAuthorityPems = '';
20
+ let resolvedIssuers = new Map<string, Buffer | null>();
21
+
22
+ /**
23
+ * Publish the current trusted authority set (PEM strings, each possibly a bundle of several
24
+ * certificates). Replaces the previous generation atomically and drops its resolution cache,
25
+ * unless the set is unchanged. Unparseable certificates are skipped so one bad record cannot
26
+ * disable resolution for the rest; this never throws, because it runs inside the TLS selector's
27
+ * publication step.
28
+ */
29
+ export function publishTrustedAuthorities(authorityPems: Iterable<unknown>): void {
30
+ const pems = Array.from(authorityPems).filter((pem): pem is string => typeof pem === 'string');
31
+ const joined = pems.join('\n');
32
+ if (joined === publishedAuthorityPems) return;
33
+ publishedAuthorityPems = joined;
34
+ const parsed: X509Certificate[] = [];
35
+ for (const pem of pems) {
36
+ for (const block of pem.match(PEM_CERTIFICATE_PATTERN) ?? []) {
37
+ try {
38
+ parsed.push(new X509Certificate(block));
39
+ } catch {}
40
+ }
41
+ }
42
+ trustedAuthorities = parsed;
43
+ resolvedIssuers = new Map();
44
+ }
45
+
46
+ /**
47
+ * Find the trusted authority that issued `leafDer`: subject/AKI match plus a signature check, so a
48
+ * same-named authority with a different key never counts, and a certificate is never its own
49
+ * issuer. Returns the issuer's DER, or undefined.
50
+ */
51
+ export function resolveTrustedIssuer(leafDer: Buffer, fingerprint256?: string): Buffer | undefined {
52
+ if (trustedAuthorities.length === 0) return undefined;
53
+ const key = fingerprint256 ?? createHash('sha256').update(leafDer).digest('hex');
54
+ const cached = resolvedIssuers.get(key);
55
+ if (cached !== undefined) return cached ?? undefined;
56
+
57
+ let issuer: Buffer | null = null;
58
+ try {
59
+ const leaf = new X509Certificate(leafDer);
60
+ for (const authority of trustedAuthorities) {
61
+ try {
62
+ if (
63
+ authority.fingerprint256 !== leaf.fingerprint256 &&
64
+ leaf.checkIssued(authority) &&
65
+ leaf.verify(authority.publicKey)
66
+ ) {
67
+ issuer = authority.raw;
68
+ break;
69
+ }
70
+ } catch {}
71
+ }
72
+ } catch {}
73
+ if (resolvedIssuers.size >= MAX_RESOLVED_LEAVES) resolvedIssuers.clear();
74
+ resolvedIssuers.set(key, issuer);
75
+ return issuer ?? undefined;
76
+ }
@@ -17,6 +17,7 @@ export interface PeerCertificate {
17
17
  [key: string]: any;
18
18
  };
19
19
  raw?: Buffer;
20
+ fingerprint256?: string;
20
21
  issuerCertificate?: PeerCertificate;
21
22
  }
22
23
 
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Provenance for a credential minted from a workload identity exchange (#2171) rather than from a
3
+ * password.
4
+ *
5
+ * The exchange's whole guarantee is that CI holds nothing durable: a one-hour operation token, no
6
+ * refresh token, nothing on disk to leak. That guarantee is only as strong as the paths that turn
7
+ * one credential into another. `create_authentication_tokens` is such a path and does not look like
8
+ * one: it is in `NO_AUTH_OPERATIONS`, but `serverHandlers.js` special-cases it so a call with no
9
+ * username/password authenticates by Bearer token instead — so an exchanged token is accepted there
10
+ * as if it were a password, honors a caller-supplied `expires_in` verbatim, and returns a 30-day
11
+ * refresh token. That converts a minutes-long leak into a month-long one, which is the exact
12
+ * exposure this feature exists to remove.
13
+ *
14
+ * A scope (operationScope.ts) cannot carry this weight. A trust policy names `operations` only when
15
+ * the operator opts in, so the ordinary exchanged token is UNSCOPED and a scope check finds nothing
16
+ * to deny — the common case would sail through a scope-only guard. Provenance is therefore recorded
17
+ * independently of scope, on every exchanged token.
18
+ *
19
+ * Like the scope, it lives under two names depending on the carrier: the claim `workload_identity`
20
+ * on a JWT payload, and `fromWorkloadIdentity` on an in-memory principal (validateToken lifts the
21
+ * claim across). And like the scope, every path that produces a credential or a principal has to
22
+ * carry it forward — impersonation included, or a workload token launders its provenance by
23
+ * impersonating and then mints freely.
24
+ */
25
+
26
+ /** The JWT claim name. Signed with the rest of the payload, so it cannot be stripped in transit. */
27
+ export const WORKLOAD_IDENTITY_CLAIM = 'workload_identity';
28
+
29
+ /** Stamps a token payload as workload-identity provenance. Returns the payload. */
30
+ export function markTokenAsWorkloadIdentity<T extends object>(payload: T): T {
31
+ (payload as any)[WORKLOAD_IDENTITY_CLAIM] = true;
32
+ return payload;
33
+ }
34
+
35
+ /** Lifts the claim from a verified token onto a user principal. Returns the user. */
36
+ export function attachWorkloadIdentityToUser<T extends object>(user: T, claim: unknown): T {
37
+ if (claim === true) (user as any).fromWorkloadIdentity = true;
38
+ return user;
39
+ }
40
+
41
+ /**
42
+ * True when this principal authenticated with a workload-identity token. Checked strictly against
43
+ * `true` so a forged string or object on a user record cannot widen it.
44
+ */
45
+ export function isWorkloadIdentityPrincipal(user: unknown): boolean {
46
+ return (user as any)?.fromWorkloadIdentity === true;
47
+ }
@@ -0,0 +1,22 @@
1
+ import { ClientError } from '../utility/errors/hdbError.ts';
2
+
3
+ // Explicit provenance prevents internal faults with a 4xx status from being deferred as rejected credentials.
4
+ const CREDENTIAL_REJECTION = Symbol('harper.credentialRejection');
5
+
6
+ export function markCredentialRejection<E extends object>(error: E): E {
7
+ Object.defineProperty(error, CREDENTIAL_REJECTION, {
8
+ value: true,
9
+ enumerable: false,
10
+ configurable: true,
11
+ writable: false,
12
+ });
13
+ return error;
14
+ }
15
+
16
+ export function credentialRejectionError(message: string, statusCode: number): ClientError {
17
+ return markCredentialRejection(new ClientError(message, statusCode));
18
+ }
19
+
20
+ export function isCredentialRejection(error: unknown): boolean {
21
+ return (error as Record<symbol, unknown> | null | undefined)?.[CREDENTIAL_REJECTION] === true;
22
+ }