@harperfast/harper 5.2.13 → 5.3.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/mcpTools.ts +1 -1
- package/agent/session.ts +25 -14
- package/bin/cliOperations.ts +58 -9
- package/bin/copyDb.ts +282 -59
- package/bin/deploySetup.ts +16 -5
- package/bin/harper.ts +1 -1
- package/bin/help.ts +4 -1
- package/bin/lite.ts +4 -1
- package/bin/restart.ts +120 -4
- package/bin/run.ts +6 -11
- package/bin/upgrade.js +7 -3
- package/bin/workloadIdentity.ts +119 -0
- package/components/Application.ts +3436 -242
- package/components/ApplicationScope.ts +8 -0
- package/components/EntryHandler.ts +59 -39
- package/components/OptionsWatcher.ts +440 -98
- package/components/RuntimeModuleTracker.ts +38 -7
- package/components/Scope.ts +56 -15
- package/components/awaitRestart.ts +84 -0
- package/components/componentLoader.ts +381 -32
- package/components/componentPreparationLock.ts +16 -5
- package/components/deploymentOperations.ts +4 -1
- package/components/deploymentRecorder.ts +9 -2
- package/components/mcp/adapters/harperHttp.ts +4 -0
- package/components/mcp/listChanged.ts +4 -0
- package/components/mcp/toolRegistry.ts +2 -0
- package/components/mcp/tools/operations.ts +9 -0
- package/components/mcp/tools/schemas/operationDescriptions.ts +2 -2
- package/components/operations.js +537 -113
- package/components/operationsValidation.js +98 -3
- package/components/packageComponent.ts +25 -1
- package/components/requestRestart.ts +11 -0
- package/components/status/ComponentStatusRegistry.ts +59 -0
- package/config/RootConfigWatcher.ts +240 -40
- package/config/configReadRetry.ts +62 -0
- package/config/configUtils.ts +357 -48
- package/config/harperConfigEnvVars.ts +170 -27
- package/config/parseConfigFile.ts +34 -0
- package/config/readConfigFileSync.ts +44 -0
- package/config/watcherArming.ts +59 -0
- package/config-root.schema.json +33 -0
- package/dataLayer/blobBackup.ts +160 -50
- package/dataLayer/delete.ts +6 -1
- package/dataLayer/harperBridge/ResourceBridge.ts +80 -10
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
- package/dataLayer/hdbInfoController.ts +34 -1
- package/dataLayer/insert.ts +44 -1
- package/dataLayer/rocksdbBackup.ts +53 -10
- package/dataLayer/schema.ts +11 -1
- package/dataLayer/schemaDescribe.ts +8 -1
- package/dist/agent/mcpTools.js +1 -1
- package/dist/agent/mcpTools.js.map +1 -1
- package/dist/agent/session.d.ts +22 -0
- package/dist/agent/session.js +26 -15
- package/dist/agent/session.js.map +1 -1
- package/dist/bin/cliOperations.js +61 -9
- package/dist/bin/cliOperations.js.map +1 -1
- package/dist/bin/copyDb.d.ts +12 -1
- package/dist/bin/copyDb.js +248 -60
- package/dist/bin/copyDb.js.map +1 -1
- package/dist/bin/deploySetup.d.ts +2 -0
- package/dist/bin/deploySetup.js +11 -3
- package/dist/bin/deploySetup.js.map +1 -1
- package/dist/bin/harper.js +1 -1
- package/dist/bin/harper.js.map +1 -1
- package/dist/bin/help.js +4 -1
- package/dist/bin/help.js.map +1 -1
- package/dist/bin/lite.js +4 -1
- package/dist/bin/lite.js.map +1 -1
- package/dist/bin/restart.js +91 -6
- package/dist/bin/restart.js.map +1 -1
- package/dist/bin/run.js +4 -10
- package/dist/bin/run.js.map +1 -1
- package/dist/bin/upgrade.js +4 -3
- package/dist/bin/upgrade.js.map +1 -1
- package/dist/bin/workloadIdentity.d.ts +18 -0
- package/dist/bin/workloadIdentity.js +100 -0
- package/dist/bin/workloadIdentity.js.map +1 -0
- package/dist/components/Application.d.ts +235 -17
- package/dist/components/Application.js +3038 -238
- package/dist/components/Application.js.map +1 -1
- package/dist/components/ApplicationScope.d.ts +8 -0
- package/dist/components/ApplicationScope.js +7 -0
- package/dist/components/ApplicationScope.js.map +1 -1
- package/dist/components/EntryHandler.js +26 -10
- package/dist/components/EntryHandler.js.map +1 -1
- package/dist/components/OptionsWatcher.d.ts +4 -0
- package/dist/components/OptionsWatcher.js +440 -99
- package/dist/components/OptionsWatcher.js.map +1 -1
- package/dist/components/RuntimeModuleTracker.js +40 -6
- package/dist/components/RuntimeModuleTracker.js.map +1 -1
- package/dist/components/Scope.js +52 -13
- package/dist/components/Scope.js.map +1 -1
- package/dist/components/awaitRestart.d.ts +33 -0
- package/dist/components/awaitRestart.js +61 -0
- package/dist/components/awaitRestart.js.map +1 -0
- package/dist/components/componentLoader.d.ts +38 -1
- package/dist/components/componentLoader.js +313 -24
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/componentPreparationLock.d.ts +5 -0
- package/dist/components/componentPreparationLock.js +14 -6
- package/dist/components/componentPreparationLock.js.map +1 -1
- package/dist/components/deploymentOperations.js +4 -1
- package/dist/components/deploymentOperations.js.map +1 -1
- package/dist/components/deploymentRecorder.d.ts +4 -2
- package/dist/components/deploymentRecorder.js +1 -0
- package/dist/components/deploymentRecorder.js.map +1 -1
- package/dist/components/mcp/adapters/harperHttp.js +4 -0
- package/dist/components/mcp/adapters/harperHttp.js.map +1 -1
- package/dist/components/mcp/listChanged.js +5 -0
- package/dist/components/mcp/listChanged.js.map +1 -1
- package/dist/components/mcp/toolRegistry.d.ts +1 -0
- package/dist/components/mcp/toolRegistry.js.map +1 -1
- package/dist/components/mcp/tools/operations.d.ts +5 -0
- package/dist/components/mcp/tools/operations.js +9 -0
- package/dist/components/mcp/tools/operations.js.map +1 -1
- package/dist/components/mcp/tools/schemas/operationDescriptions.js +2 -2
- package/dist/components/mcp/tools/schemas/operationDescriptions.js.map +1 -1
- package/dist/components/operations.d.ts +28 -0
- package/dist/components/operations.js +476 -113
- package/dist/components/operations.js.map +1 -1
- package/dist/components/operationsValidation.js +97 -3
- package/dist/components/operationsValidation.js.map +1 -1
- package/dist/components/packageComponent.js +24 -0
- package/dist/components/packageComponent.js.map +1 -1
- package/dist/components/requestRestart.d.ts +1 -0
- package/dist/components/requestRestart.js +7 -0
- package/dist/components/requestRestart.js.map +1 -1
- package/dist/components/status/ComponentStatusRegistry.d.ts +0 -4
- package/dist/components/status/ComponentStatusRegistry.js +63 -0
- package/dist/components/status/ComponentStatusRegistry.js.map +1 -1
- package/dist/config/RootConfigWatcher.d.ts +9 -1
- package/dist/config/RootConfigWatcher.js +228 -37
- package/dist/config/RootConfigWatcher.js.map +1 -1
- package/dist/config/configReadRetry.d.ts +8 -0
- package/dist/config/configReadRetry.js +62 -0
- package/dist/config/configReadRetry.js.map +1 -0
- package/dist/config/configUtils.d.ts +11 -2
- package/dist/config/configUtils.js +304 -47
- package/dist/config/configUtils.js.map +1 -1
- package/dist/config/harperConfigEnvVars.d.ts +16 -0
- package/dist/config/harperConfigEnvVars.js +162 -25
- package/dist/config/harperConfigEnvVars.js.map +1 -1
- package/dist/config/parseConfigFile.d.ts +4 -0
- package/dist/config/parseConfigFile.js +35 -0
- package/dist/config/parseConfigFile.js.map +1 -0
- package/dist/config/readConfigFileSync.d.ts +1 -0
- package/dist/config/readConfigFileSync.js +47 -0
- package/dist/config/readConfigFileSync.js.map +1 -0
- package/dist/config/watcherArming.d.ts +15 -0
- package/dist/config/watcherArming.js +59 -0
- package/dist/config/watcherArming.js.map +1 -0
- package/dist/dataLayer/blobBackup.d.ts +49 -20
- package/dist/dataLayer/blobBackup.js +139 -50
- package/dist/dataLayer/blobBackup.js.map +1 -1
- package/dist/dataLayer/delete.js +1 -1
- package/dist/dataLayer/delete.js.map +1 -1
- package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +14 -1
- package/dist/dataLayer/harperBridge/ResourceBridge.js +72 -12
- package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
- package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.d.ts +3 -1
- package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
- package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js.map +1 -1
- package/dist/dataLayer/hdbInfoController.d.ts +10 -0
- package/dist/dataLayer/hdbInfoController.js +30 -1
- package/dist/dataLayer/hdbInfoController.js.map +1 -1
- package/dist/dataLayer/insert.d.ts +9 -1
- package/dist/dataLayer/insert.js +30 -0
- package/dist/dataLayer/insert.js.map +1 -1
- package/dist/dataLayer/rocksdbBackup.d.ts +2 -2
- package/dist/dataLayer/rocksdbBackup.js +45 -8
- package/dist/dataLayer/rocksdbBackup.js.map +1 -1
- package/dist/dataLayer/schema.js +8 -0
- package/dist/dataLayer/schema.js.map +1 -1
- package/dist/dataLayer/schemaDescribe.js +8 -1
- package/dist/dataLayer/schemaDescribe.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/json/systemSchema.json +55 -0
- package/dist/resources/DatabaseTransaction.d.ts +77 -0
- package/dist/resources/DatabaseTransaction.js +586 -54
- package/dist/resources/DatabaseTransaction.js.map +1 -1
- package/dist/resources/LMDBTransaction.d.ts +2 -1
- package/dist/resources/LMDBTransaction.js +43 -6
- package/dist/resources/LMDBTransaction.js.map +1 -1
- package/dist/resources/PrimaryRocksDatabase.d.ts +1 -0
- package/dist/resources/PrimaryRocksDatabase.js +49 -5
- package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
- package/dist/resources/RecordEncoder.d.ts +20 -0
- package/dist/resources/RecordEncoder.js +110 -9
- package/dist/resources/RecordEncoder.js.map +1 -1
- package/dist/resources/RequestTarget.d.ts +2 -0
- package/dist/resources/RequestTarget.js.map +1 -1
- package/dist/resources/Resource.js +117 -24
- package/dist/resources/Resource.js.map +1 -1
- package/dist/resources/ResourceInterface.d.ts +28 -1
- package/dist/resources/ResourceInterface.js.map +1 -1
- package/dist/resources/RocksIndexStore.d.ts +6 -1
- package/dist/resources/RocksIndexStore.js +24 -9
- package/dist/resources/RocksIndexStore.js.map +1 -1
- package/dist/resources/RocksTransactionLogStore.d.ts +24 -1
- package/dist/resources/RocksTransactionLogStore.js +160 -49
- package/dist/resources/RocksTransactionLogStore.js.map +1 -1
- package/dist/resources/Table.d.ts +165 -10
- package/dist/resources/Table.js +1805 -303
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/write.js +10 -3
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/auditStore.d.ts +181 -2
- package/dist/resources/auditStore.js +640 -29
- package/dist/resources/auditStore.js.map +1 -1
- package/dist/resources/blob.d.ts +129 -9
- package/dist/resources/blob.js +992 -114
- package/dist/resources/blob.js.map +1 -1
- package/dist/resources/branchDatabase.d.ts +48 -0
- package/dist/resources/branchDatabase.js +892 -0
- package/dist/resources/branchDatabase.js.map +1 -0
- package/dist/resources/crdt.js +50 -12
- package/dist/resources/crdt.js.map +1 -1
- package/dist/resources/dataLoader.js +3 -4
- package/dist/resources/dataLoader.js.map +1 -1
- package/dist/resources/databases.d.ts +157 -14
- package/dist/resources/databases.js +1462 -325
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/defineTable.d.ts +10 -2
- package/dist/resources/defineTable.js +9 -1
- package/dist/resources/defineTable.js.map +1 -1
- package/dist/resources/derivedIndexRegistry.d.ts +5 -0
- package/dist/resources/derivedIndexRegistry.js +68 -0
- package/dist/resources/derivedIndexRegistry.js.map +1 -0
- package/dist/resources/derivedIndexRuntime.d.ts +215 -0
- package/dist/resources/derivedIndexRuntime.js +2027 -0
- package/dist/resources/derivedIndexRuntime.js.map +1 -0
- package/dist/resources/graphql.d.ts +1 -1
- package/dist/resources/graphql.js +52 -16
- package/dist/resources/graphql.js.map +1 -1
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +103 -9
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +854 -41
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
- package/dist/resources/indexes/hnswDerivedIndex.d.ts +67 -0
- package/dist/resources/indexes/hnswDerivedIndex.js +464 -0
- package/dist/resources/indexes/hnswDerivedIndex.js.map +1 -0
- package/dist/resources/indexes/hnswPlaneBinding.d.ts +65 -0
- package/dist/resources/indexes/hnswPlaneBinding.js +91 -0
- package/dist/resources/indexes/hnswPlaneBinding.js.map +1 -0
- package/dist/resources/longLivedTransactions.d.ts +71 -0
- package/dist/resources/longLivedTransactions.js +358 -0
- package/dist/resources/longLivedTransactions.js.map +1 -0
- package/dist/resources/models/backendRegistry.d.ts +26 -0
- package/dist/resources/models/backendRegistry.js +60 -2
- package/dist/resources/models/backendRegistry.js.map +1 -1
- package/dist/resources/models/bootstrap.d.ts +33 -1
- package/dist/resources/models/bootstrap.js +416 -31
- package/dist/resources/models/bootstrap.js.map +1 -1
- package/dist/resources/nodeIdMapping.d.ts +5 -0
- package/dist/resources/nodeIdMapping.js +49 -0
- package/dist/resources/nodeIdMapping.js.map +1 -1
- package/dist/resources/recordLock.d.ts +123 -0
- package/dist/resources/recordLock.js +315 -0
- package/dist/resources/recordLock.js.map +1 -0
- package/dist/resources/recordLockCoordinator.d.ts +557 -0
- package/dist/resources/recordLockCoordinator.js +2565 -0
- package/dist/resources/recordLockCoordinator.js.map +1 -0
- package/dist/resources/replayLogs.d.ts +14 -1
- package/dist/resources/replayLogs.js +157 -24
- package/dist/resources/replayLogs.js.map +1 -1
- package/dist/resources/replayLogsGuards.d.ts +94 -7
- package/dist/resources/replayLogsGuards.js +111 -7
- package/dist/resources/replayLogsGuards.js.map +1 -1
- package/dist/resources/replicatedApplyFailure.d.ts +16 -0
- package/dist/resources/replicatedApplyFailure.js +63 -0
- package/dist/resources/replicatedApplyFailure.js.map +1 -0
- package/dist/resources/scheduler/scheduler.js +3 -3
- package/dist/resources/scheduler/scheduler.js.map +1 -1
- package/dist/resources/search.d.ts +10 -4
- package/dist/resources/search.js +283 -37
- package/dist/resources/search.js.map +1 -1
- package/dist/resources/tracked.d.ts +5 -1
- package/dist/resources/tracked.js +74 -23
- package/dist/resources/tracked.js.map +1 -1
- package/dist/resources/transactionBroadcast.d.ts +1 -1
- package/dist/resources/transactionBroadcast.js +2 -2
- package/dist/resources/transactionBroadcast.js.map +1 -1
- package/dist/security/auth.js +61 -30
- package/dist/security/auth.js.map +1 -1
- package/dist/security/authn/oidc/claims.d.ts +22 -0
- package/dist/security/authn/oidc/claims.js +71 -0
- package/dist/security/authn/oidc/claims.js.map +1 -0
- package/dist/security/authn/oidc/identityToken.d.ts +27 -0
- package/dist/security/authn/oidc/identityToken.js +111 -0
- package/dist/security/authn/oidc/identityToken.js.map +1 -0
- package/dist/security/authn/oidc/jwks.d.ts +25 -0
- package/dist/security/authn/oidc/jwks.js +261 -0
- package/dist/security/authn/oidc/jwks.js.map +1 -0
- package/dist/security/authn/oidc/providers/generic.d.ts +13 -0
- package/dist/security/authn/oidc/providers/generic.js +34 -0
- package/dist/security/authn/oidc/providers/generic.js.map +1 -0
- package/dist/security/authn/oidc/providers/githubActions.d.ts +11 -0
- package/dist/security/authn/oidc/providers/githubActions.js +129 -0
- package/dist/security/authn/oidc/providers/githubActions.js.map +1 -0
- package/dist/security/authn/oidc/providers/index.d.ts +37 -0
- package/dist/security/authn/oidc/providers/index.js +24 -0
- package/dist/security/authn/oidc/providers/index.js.map +1 -0
- package/dist/security/authn/oidc/tokenExchange.d.ts +12 -0
- package/dist/security/authn/oidc/tokenExchange.js +306 -0
- package/dist/security/authn/oidc/tokenExchange.js.map +1 -0
- package/dist/security/authn/oidc/trustPolicyOperations.d.ts +49 -0
- package/dist/security/authn/oidc/trustPolicyOperations.js +358 -0
- package/dist/security/authn/oidc/trustPolicyOperations.js.map +1 -0
- package/dist/security/authn/oidc/types.d.ts +38 -0
- package/dist/security/authn/oidc/types.js +6 -0
- package/dist/security/authn/oidc/types.js.map +1 -0
- package/dist/security/certificateVerification/index.js +40 -11
- package/dist/security/certificateVerification/index.js.map +1 -1
- package/dist/security/certificateVerification/trustedIssuers.d.ts +24 -0
- package/dist/security/certificateVerification/trustedIssuers.js +79 -0
- package/dist/security/certificateVerification/trustedIssuers.js.map +1 -0
- package/dist/security/certificateVerification/types.d.ts +1 -0
- package/dist/security/credentialProvenance.d.ts +35 -0
- package/dist/security/credentialProvenance.js +51 -0
- package/dist/security/credentialProvenance.js.map +1 -0
- package/dist/security/credentialRejection.d.ts +4 -0
- package/dist/security/credentialRejection.js +24 -0
- package/dist/security/credentialRejection.js.map +1 -0
- package/dist/security/deferredAuthentication.d.ts +36 -0
- package/dist/security/deferredAuthentication.js +70 -0
- package/dist/security/deferredAuthentication.js.map +1 -0
- package/dist/security/impersonation.d.ts +21 -0
- package/dist/security/impersonation.js +108 -9
- package/dist/security/impersonation.js.map +1 -1
- package/dist/security/jsLoader.d.ts +6 -0
- package/dist/security/jsLoader.js +77 -15
- package/dist/security/jsLoader.js.map +1 -1
- package/dist/security/keys.js +301 -71
- package/dist/security/keys.js.map +1 -1
- package/dist/security/operationScope.d.ts +21 -0
- package/dist/security/operationScope.js +36 -0
- package/dist/security/operationScope.js.map +1 -0
- package/dist/security/permissionsTranslator.js +21 -0
- package/dist/security/permissionsTranslator.js.map +1 -1
- package/dist/security/tokenAuthentication.d.ts +19 -1
- package/dist/security/tokenAuthentication.js +191 -10
- package/dist/security/tokenAuthentication.js.map +1 -1
- package/dist/security/user.js +4 -3
- package/dist/security/user.js.map +1 -1
- package/dist/server/DurableSubscriptionsSession.d.ts +2 -2
- package/dist/server/DurableSubscriptionsSession.js +67 -10
- package/dist/server/DurableSubscriptionsSession.js.map +1 -1
- package/dist/server/REST.js +106 -2
- package/dist/server/REST.js.map +1 -1
- package/dist/server/graphqlQuerying.js +4 -0
- package/dist/server/graphqlQuerying.js.map +1 -1
- package/dist/server/http.d.ts +16 -1
- package/dist/server/http.js +122 -17
- package/dist/server/http.js.map +1 -1
- package/dist/server/itc/serverHandlers.js +8 -1
- package/dist/server/itc/serverHandlers.js.map +1 -1
- package/dist/server/jobs/jobProcess.js +6 -2
- package/dist/server/jobs/jobProcess.js.map +1 -1
- package/dist/server/jobs/jobs.js +4 -1
- package/dist/server/jobs/jobs.js.map +1 -1
- package/dist/server/liveSubscriptionAuth.d.ts +26 -4
- package/dist/server/liveSubscriptionAuth.js +105 -39
- package/dist/server/liveSubscriptionAuth.js.map +1 -1
- package/dist/server/loadRootComponents.js +49 -10
- package/dist/server/loadRootComponents.js.map +1 -1
- package/dist/server/mqtt.d.ts +2 -0
- package/dist/server/mqtt.js +165 -30
- package/dist/server/mqtt.js.map +1 -1
- package/dist/server/nodeName.d.ts +2 -0
- package/dist/server/nodeName.js +107 -23
- package/dist/server/nodeName.js.map +1 -1
- package/dist/server/serverHelpers/Headers.d.ts +27 -0
- package/dist/server/serverHelpers/Headers.js +145 -1
- package/dist/server/serverHelpers/Headers.js.map +1 -1
- package/dist/server/serverHelpers/NodeAdapterResponse.d.ts +48 -0
- package/dist/server/serverHelpers/NodeAdapterResponse.js +220 -0
- package/dist/server/serverHelpers/NodeAdapterResponse.js.map +1 -0
- package/dist/server/serverHelpers/Request.d.ts +5 -10
- package/dist/server/serverHelpers/Request.js +38 -136
- package/dist/server/serverHelpers/Request.js.map +1 -1
- package/dist/server/serverHelpers/contentTypes.d.ts +11 -0
- package/dist/server/serverHelpers/contentTypes.js +221 -40
- package/dist/server/serverHelpers/contentTypes.js.map +1 -1
- package/dist/server/serverHelpers/deployValidationState.d.ts +3 -0
- package/dist/server/serverHelpers/deployValidationState.js +9 -19
- package/dist/server/serverHelpers/deployValidationState.js.map +1 -1
- package/dist/server/serverHelpers/operationAuthorizationState.d.ts +12 -0
- package/dist/server/serverHelpers/operationAuthorizationState.js +24 -2
- package/dist/server/serverHelpers/operationAuthorizationState.js.map +1 -1
- package/dist/server/serverHelpers/registeredOperations.d.ts +5 -4
- package/dist/server/serverHelpers/registeredOperations.js +74 -21
- package/dist/server/serverHelpers/registeredOperations.js.map +1 -1
- package/dist/server/serverHelpers/requestSanitization.d.ts +11 -0
- package/dist/server/serverHelpers/requestSanitization.js +20 -0
- package/dist/server/serverHelpers/requestSanitization.js.map +1 -0
- package/dist/server/serverHelpers/serverHandlers.js +6 -3
- package/dist/server/serverHelpers/serverHandlers.js.map +1 -1
- package/dist/server/serverHelpers/serverUtilities.d.ts +18 -0
- package/dist/server/serverHelpers/serverUtilities.js +178 -29
- package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
- package/dist/server/serverHelpers/sharedMessageEncoding.d.ts +67 -0
- package/dist/server/serverHelpers/sharedMessageEncoding.js +280 -0
- package/dist/server/serverHelpers/sharedMessageEncoding.js.map +1 -0
- package/dist/server/serverHelpers/uwsServer.js +19 -1
- package/dist/server/serverHelpers/uwsServer.js.map +1 -1
- package/dist/server/static.js +24 -28
- package/dist/server/static.js.map +1 -1
- package/dist/server/storageReclamation.d.ts +5 -0
- package/dist/server/storageReclamation.js +17 -1
- package/dist/server/storageReclamation.js.map +1 -1
- package/dist/server/threads/isolatedApplications.d.ts +47 -0
- package/dist/server/threads/isolatedApplications.js +171 -0
- package/dist/server/threads/isolatedApplications.js.map +1 -0
- package/dist/server/threads/itc.d.ts +7 -2
- package/dist/server/threads/itc.js +5 -1
- package/dist/server/threads/itc.js.map +1 -1
- package/dist/server/threads/logRotationTransport.d.ts +1 -0
- package/dist/server/threads/logRotationTransport.js +33 -0
- package/dist/server/threads/logRotationTransport.js.map +1 -0
- package/dist/server/threads/manageThreads.d.ts +83 -3
- package/dist/server/threads/manageThreads.js +769 -75
- package/dist/server/threads/manageThreads.js.map +1 -1
- package/dist/server/threads/socketRouter.d.ts +1 -0
- package/dist/server/threads/socketRouter.js +277 -31
- package/dist/server/threads/socketRouter.js.map +1 -1
- package/dist/server/threads/threadHeapMemory.d.ts +2 -0
- package/dist/server/threads/threadHeapMemory.js +31 -0
- package/dist/server/threads/threadHeapMemory.js.map +1 -0
- package/dist/server/threads/threadServer.js +76 -22
- package/dist/server/threads/threadServer.js.map +1 -1
- package/dist/sqlEngine/config.d.ts +1 -3
- package/dist/sqlEngine/config.js +19 -16
- package/dist/sqlEngine/config.js.map +1 -1
- package/dist/sqlTranslator/index.d.ts +1 -1
- package/dist/sqlTranslator/index.js +30 -7
- package/dist/sqlTranslator/index.js.map +1 -1
- package/dist/upgrade/directives/5-3-0.d.ts +7 -0
- package/dist/upgrade/directives/5-3-0.js +148 -0
- package/dist/upgrade/directives/5-3-0.js.map +1 -0
- package/dist/upgrade/directives/directivesController.js +2 -1
- package/dist/upgrade/directives/directivesController.js.map +1 -1
- package/dist/utility/OperationFunctionCaller.js +2 -1
- package/dist/utility/OperationFunctionCaller.js.map +1 -1
- package/dist/utility/common_utils.d.ts +16 -0
- package/dist/utility/common_utils.js +32 -6
- package/dist/utility/common_utils.js.map +1 -1
- package/dist/utility/componentNames.d.ts +8 -0
- package/dist/utility/componentNames.js +12 -1
- package/dist/utility/componentNames.js.map +1 -1
- package/dist/utility/environment/environmentManager.js +3 -6
- package/dist/utility/environment/environmentManager.js.map +1 -1
- package/dist/utility/environment/systemInformation.d.ts +1 -0
- package/dist/utility/environment/systemInformation.js +1 -0
- package/dist/utility/environment/systemInformation.js.map +1 -1
- package/dist/utility/errors/commonErrors.d.ts +2 -0
- package/dist/utility/errors/commonErrors.js +2 -0
- package/dist/utility/errors/commonErrors.js.map +1 -1
- package/dist/utility/errors/hdbError.d.ts +33 -0
- package/dist/utility/errors/hdbError.js +58 -1
- package/dist/utility/errors/hdbError.js.map +1 -1
- package/dist/utility/globalSchema.d.ts +18 -0
- package/dist/utility/hdbTerms.d.ts +18 -0
- package/dist/utility/hdbTerms.js +20 -2
- package/dist/utility/hdbTerms.js.map +1 -1
- package/dist/utility/logging/harper_logger.d.ts +2 -0
- package/dist/utility/logging/harper_logger.js +286 -30
- package/dist/utility/logging/harper_logger.js.map +1 -1
- package/dist/utility/logging/logGenerationCoordinator.d.ts +35 -0
- package/dist/utility/logging/logGenerationCoordinator.js +184 -0
- package/dist/utility/logging/logGenerationCoordinator.js.map +1 -0
- package/dist/utility/logging/logRotation.d.ts +46 -0
- package/dist/utility/logging/logRotation.js +365 -0
- package/dist/utility/logging/logRotation.js.map +1 -0
- package/dist/utility/logging/logRotator.d.ts +1 -1
- package/dist/utility/logging/logRotator.js +192 -85
- package/dist/utility/logging/logRotator.js.map +1 -1
- package/dist/utility/nodeIdentity.d.ts +9 -0
- package/dist/utility/nodeIdentity.js +58 -0
- package/dist/utility/nodeIdentity.js.map +1 -0
- package/dist/utility/npmUtilities.js +11 -7
- package/dist/utility/npmUtilities.js.map +1 -1
- package/dist/utility/operationPermissions.d.ts +3 -1
- package/dist/utility/operationPermissions.js +16 -1
- package/dist/utility/operationPermissions.js.map +1 -1
- package/dist/utility/operation_authorization.d.ts +10 -7
- package/dist/utility/operation_authorization.js +212 -41
- package/dist/utility/operation_authorization.js.map +1 -1
- package/dist/utility/watchPath.d.ts +29 -0
- package/dist/utility/watchPath.js +68 -0
- package/dist/utility/watchPath.js.map +1 -0
- package/dist/utility/watcherFallback.d.ts +41 -0
- package/dist/utility/watcherFallback.js +153 -0
- package/dist/utility/watcherFallback.js.map +1 -1
- package/dist/validation/configValidator.d.ts +12 -0
- package/dist/validation/configValidator.js +205 -75
- package/dist/validation/configValidator.js.map +1 -1
- package/dist/validation/installValidator.js +12 -0
- package/dist/validation/installValidator.js.map +1 -1
- package/dist/validation/validationWrapper.d.ts +11 -0
- package/dist/validation/validationWrapper.js +16 -3
- package/dist/validation/validationWrapper.js.map +1 -1
- package/index.ts +8 -0
- package/json/systemSchema.json +55 -0
- package/npm-shrinkwrap.json +286 -194
- package/package.json +15 -7
- package/resources/DESIGN.md +219 -52
- package/resources/DatabaseTransaction.ts +657 -52
- package/resources/LMDBTransaction.ts +46 -6
- package/resources/PrimaryRocksDatabase.ts +46 -7
- package/resources/RecordEncoder.ts +124 -9
- package/resources/RequestTarget.ts +2 -0
- package/resources/Resource.ts +114 -22
- package/resources/ResourceInterface.ts +31 -0
- package/resources/RocksIndexStore.ts +30 -9
- package/resources/RocksTransactionLogStore.ts +188 -51
- package/resources/Table.ts +1960 -301
- package/resources/analytics/write.ts +10 -3
- package/resources/auditStore.ts +647 -32
- package/resources/blob.ts +1029 -110
- package/resources/branchDatabase.ts +941 -0
- package/resources/crdt.ts +76 -12
- package/resources/dataLoader.ts +3 -4
- package/resources/databases.ts +1584 -320
- package/resources/defineTable.ts +18 -2
- package/resources/derivedIndexRegistry.ts +56 -0
- package/resources/derivedIndexRuntime.ts +2292 -0
- package/resources/graphql.ts +72 -17
- package/resources/indexes/HierarchicalNavigableSmallWorld.ts +911 -48
- package/resources/indexes/hnswDerivedIndex.ts +531 -0
- package/resources/indexes/hnswPlaneBinding.ts +174 -0
- package/resources/longLivedTransactions.ts +360 -0
- package/resources/models/backendRegistry.ts +84 -2
- package/resources/models/bootstrap.ts +473 -28
- package/resources/nodeIdMapping.ts +50 -0
- package/resources/recordLock.ts +419 -0
- package/resources/recordLockCoordinator.ts +3043 -0
- package/resources/replayLogs.ts +152 -26
- package/resources/replayLogsGuards.ts +171 -8
- package/resources/replicatedApplyFailure.ts +77 -0
- package/resources/scheduler/scheduler.ts +4 -4
- package/resources/search.ts +288 -46
- package/resources/tracked.ts +73 -22
- package/resources/transactionBroadcast.ts +3 -3
- package/security/auth.ts +68 -29
- package/security/authn/oidc/claims.ts +72 -0
- package/security/authn/oidc/identityToken.ts +129 -0
- package/security/authn/oidc/jwks.ts +260 -0
- package/security/authn/oidc/providers/generic.ts +40 -0
- package/security/authn/oidc/providers/githubActions.ts +137 -0
- package/security/authn/oidc/providers/index.ts +52 -0
- package/security/authn/oidc/tokenExchange.ts +300 -0
- package/security/authn/oidc/trustPolicyOperations.ts +343 -0
- package/security/authn/oidc/types.ts +41 -0
- package/security/certificateVerification/index.ts +54 -13
- package/security/certificateVerification/trustedIssuers.ts +76 -0
- package/security/certificateVerification/types.ts +1 -0
- package/security/credentialProvenance.ts +47 -0
- package/security/credentialRejection.ts +22 -0
- package/security/deferredAuthentication.ts +71 -0
- package/security/impersonation.ts +117 -12
- package/security/jsLoader.ts +83 -18
- package/security/keys.ts +298 -72
- package/security/operationScope.ts +33 -0
- package/security/permissionsTranslator.js +23 -0
- package/security/tokenAuthentication.ts +233 -12
- package/security/user.ts +4 -3
- package/server/DESIGN.md +194 -16
- package/server/DurableSubscriptionsSession.ts +71 -11
- package/server/REST.ts +115 -4
- package/server/graphqlQuerying.ts +4 -0
- package/server/http.ts +133 -20
- package/server/itc/serverHandlers.js +8 -1
- package/server/jobs/jobProcess.ts +8 -2
- package/server/jobs/jobs.ts +4 -1
- package/server/liveSubscriptionAuth.ts +129 -46
- package/server/loadRootComponents.js +50 -8
- package/server/mqtt.ts +179 -38
- package/server/nodeName.ts +103 -21
- package/server/serverHelpers/Headers.ts +135 -0
- package/server/serverHelpers/NodeAdapterResponse.ts +221 -0
- package/server/serverHelpers/Request.ts +33 -131
- package/server/serverHelpers/contentTypes.ts +217 -36
- package/server/serverHelpers/deployValidationState.ts +24 -13
- package/server/serverHelpers/operationAuthorizationState.ts +34 -3
- package/server/serverHelpers/registeredOperations.ts +79 -22
- package/server/serverHelpers/requestSanitization.ts +15 -0
- package/server/serverHelpers/serverHandlers.js +6 -3
- package/server/serverHelpers/serverUtilities.ts +232 -40
- package/server/serverHelpers/sharedMessageEncoding.ts +307 -0
- package/server/serverHelpers/uwsServer.ts +17 -2
- package/server/static.ts +23 -29
- package/server/storageReclamation.ts +15 -2
- package/server/threads/isolatedApplications.ts +157 -0
- package/server/threads/itc.js +11 -1
- package/server/threads/logRotationTransport.ts +40 -0
- package/server/threads/manageThreads.js +771 -66
- package/server/threads/socketRouter.ts +291 -30
- package/server/threads/threadHeapMemory.ts +26 -0
- package/server/threads/threadServer.js +73 -22
- package/sqlTranslator/index.ts +31 -8
- package/studio/web/assets/{Chat-4RrB5134.js → Chat-D3j-1yY1.js} +1 -1
- package/studio/web/assets/{FloatingChat-omlNMDcJ.js → FloatingChat-BxJGYcfB.js} +3 -3
- package/studio/web/assets/{apiToken-Bke3wvfZ.js → apiToken-CT55oWOe.js} +1 -1
- package/studio/web/assets/{applications-DvFDYJgK.js → applications-D9Ct9_vm.js} +1 -1
- package/studio/web/assets/{cssMode-C1vRa7zh.js → cssMode-DV8H7VwA.js} +1 -1
- package/studio/web/assets/{editor-3XRWEDWX.js → editor-uatc0unt.js} +1 -1
- package/studio/web/assets/{html-CTY5tdMr.js → html-Bm6D6paN.js} +1 -1
- package/studio/web/assets/{htmlMode-CG1vSD9t.js → htmlMode-CEn7tpLG.js} +1 -1
- package/studio/web/assets/{index-Dfpeofdu.js → index-BIXW6Pu4.js} +5 -5
- package/studio/web/assets/{index.lazy-B1VOIv-t.js → index.lazy-UI7L-Vrk.js} +1 -1
- package/studio/web/assets/{javascript-CJeJzGnI.js → javascript-CJ0G3AFZ.js} +1 -1
- package/studio/web/assets/{jsonMode-CYPBwM82.js → jsonMode-DQADAYEa.js} +1 -1
- package/studio/web/assets/{languageServices-IKH4GUHl.js → languageServices-CAQJXWcI.js} +1 -1
- package/studio/web/assets/{lspLanguageFeatures-BC8_gxKG.js → lspLanguageFeatures-CCQ8P5sY.js} +1 -1
- package/studio/web/assets/{notifications-BfKBpYcq.js → notifications-BbxTU6Aw.js} +1 -1
- package/studio/web/assets/{notifications-DFbArTfC.js → notifications-Cvb3P1lB.js} +1 -1
- package/studio/web/assets/{profile-Q4-T6c-S.js → profile-Yyb7gsvL.js} +1 -1
- package/studio/web/assets/{regions-CtkV0xje.js → regions-OgjGHlU5.js} +1 -1
- package/studio/web/assets/{register-1ZZuMsiA.js → register-6qwNEOY3.js} +2 -2
- package/studio/web/assets/{setComponentFile-ZWLcWv5X.js → setComponentFile-BilDMtgB.js} +1 -1
- package/studio/web/assets/{setup-DWprJyJy.js → setup-J6qJ7OIU.js} +2 -2
- package/studio/web/assets/{status--aNm8isn.js → status-0RWGcfyD.js} +1 -1
- package/studio/web/assets/{toggleHighContrast-Cq_lt3XD.js → toggleHighContrast-BIn-vErT.js} +1 -1
- package/studio/web/assets/{tsMode-pjgytARx.js → tsMode-DgUXku4d.js} +1 -1
- package/studio/web/assets/{typescript-Cdg0mqUh.js → typescript-C9orXcsM.js} +1 -1
- package/studio/web/assets/{useEntityRestURL-RZhaY8Rn.js → useEntityRestURL-BEoXXbUB.js} +1 -1
- package/studio/web/assets/{workers-BgoXIqQe.js → workers-JVzSDmgx.js} +1 -1
- package/studio/web/assets/{xml-BwSeDMiP.js → xml-Cq-S8S4X.js} +1 -1
- package/studio/web/assets/{yaml-DotCUG5l.js → yaml-sfoRdh1M.js} +1 -1
- package/studio/web/index.html +1 -1
- package/upgrade/directives/5-3-0.ts +132 -0
- package/upgrade/directives/directivesController.ts +2 -1
- package/utility/OperationFunctionCaller.ts +2 -1
- package/utility/common_utils.ts +30 -5
- package/utility/componentNames.ts +12 -0
- package/utility/environment/environmentManager.ts +3 -7
- package/utility/environment/systemInformation.ts +7 -0
- package/utility/errors/commonErrors.ts +4 -0
- package/utility/errors/hdbError.ts +57 -0
- package/utility/hdbTerms.ts +19 -0
- package/utility/logging/harper_logger.ts +278 -26
- package/utility/logging/logGenerationCoordinator.ts +196 -0
- package/utility/logging/logRotation.ts +367 -0
- package/utility/logging/logRotator.ts +213 -81
- package/utility/nodeIdentity.ts +45 -0
- package/utility/npmUtilities.ts +12 -8
- package/utility/operationPermissions.ts +18 -1
- package/utility/operation_authorization.ts +231 -42
- package/utility/watchPath.ts +63 -0
- package/utility/watcherFallback.ts +148 -0
- package/validation/configValidator.ts +215 -75
- package/validation/installValidator.ts +15 -0
- package/validation/validationWrapper.ts +18 -4
|
@@ -25,13 +25,26 @@
|
|
|
25
25
|
import type { Logger } from '../utility/logging/logger.ts';
|
|
26
26
|
import * as fs from 'fs-extra';
|
|
27
27
|
import * as path from 'node:path';
|
|
28
|
+
import { isMainThread } from 'node:worker_threads';
|
|
28
29
|
import * as crypto from 'node:crypto';
|
|
29
30
|
import { cloneDeep } from 'lodash';
|
|
30
31
|
import { getBackupDirPath } from './configHelpers.ts';
|
|
31
|
-
import { atomicWriteFile } from './configUtils.ts';
|
|
32
|
+
import { atomicWriteFile, renameWithRetry } from './configUtils.ts';
|
|
32
33
|
import * as hdbTerms from '../utility/hdbTerms.ts';
|
|
33
34
|
|
|
34
35
|
const STATE_FILE_NAME = '.harper-config-state.json';
|
|
36
|
+
// Staged beside the confirmed state while a config-file write is in flight, then renamed over it.
|
|
37
|
+
// Per-process, because every CLI invocation and worker runs this and one shared name would let one
|
|
38
|
+
// clear another's in-flight commit. See DESIGN.md, boot-path config persistence.
|
|
39
|
+
const PENDING_STATE_PREFIX = '.harper-config-state.pending.';
|
|
40
|
+
const PENDING_STATE_SUFFIX = '.json';
|
|
41
|
+
const pendingStateFileName = () => `${PENDING_STATE_PREFIX}${process.pid}${PENDING_STATE_SUFFIX}`;
|
|
42
|
+
// Recovery from a recycled pid only has to be eventual, and deleting a slow-but-live writer's
|
|
43
|
+
// sidecar is the worse error - it strands that writer's config file against an unpromoted state. So
|
|
44
|
+
// the age-out is far longer than a commit (three synchronous steps) could ever legitimately take:
|
|
45
|
+
// long enough that a stalled writer or clock skew between containers sharing a volume cannot reach
|
|
46
|
+
// it, short enough that leaked wreckage does not suspend drift detection indefinitely.
|
|
47
|
+
const PENDING_STATE_STALE_MS = 60 * 60 * 1000;
|
|
35
48
|
|
|
36
49
|
/**
|
|
37
50
|
* Get logger instance with tag - lazy loaded to avoid circular dependencies
|
|
@@ -546,15 +559,7 @@ function parseConfigEnvVar(envVarValue: string | undefined, envVarName: string):
|
|
|
546
559
|
function loadConfigState(rootPath: string): ConfigState {
|
|
547
560
|
const statePath = path.join(getBackupDirPath(rootPath), STATE_FILE_NAME);
|
|
548
561
|
|
|
549
|
-
if (!fs.existsSync(statePath))
|
|
550
|
-
return {
|
|
551
|
-
version: '1.0',
|
|
552
|
-
sources: {},
|
|
553
|
-
originalValues: {},
|
|
554
|
-
emptyScopeOriginals: {},
|
|
555
|
-
snapshots: {},
|
|
556
|
-
};
|
|
557
|
-
}
|
|
562
|
+
if (!fs.existsSync(statePath)) return freshConfigState();
|
|
558
563
|
|
|
559
564
|
try {
|
|
560
565
|
const state = fs.readJsonSync(statePath) as ConfigState;
|
|
@@ -573,20 +578,85 @@ function loadConfigState(rootPath: string): ConfigState {
|
|
|
573
578
|
// If state file is corrupted, start fresh
|
|
574
579
|
const logger = getLogger();
|
|
575
580
|
logger.warn(`Failed to load config state file, starting fresh: ${(error as Error).message}`);
|
|
576
|
-
return
|
|
577
|
-
version: '1.0',
|
|
578
|
-
sources: {},
|
|
579
|
-
originalValues: {},
|
|
580
|
-
emptyScopeOriginals: {},
|
|
581
|
-
snapshots: {},
|
|
582
|
-
};
|
|
581
|
+
return freshConfigState();
|
|
583
582
|
}
|
|
584
583
|
}
|
|
585
584
|
|
|
585
|
+
/**
|
|
586
|
+
* Clear a sidecar left by an interrupted commit, reporting whether one was there. The caller skips
|
|
587
|
+
* drift detection for that boot: it cannot tell a manual user edit from the write that was in
|
|
588
|
+
* flight, and calling it an edit hands those paths to 'user' for good.
|
|
589
|
+
*/
|
|
590
|
+
function takeInterruptedCommit(rootPath: string): boolean {
|
|
591
|
+
const backupDir = getBackupDirPath(rootPath);
|
|
592
|
+
let entries: string[];
|
|
593
|
+
try {
|
|
594
|
+
entries = fs.readdirSync(backupDir);
|
|
595
|
+
} catch {
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
let interrupted = false;
|
|
599
|
+
for (const entry of entries) {
|
|
600
|
+
if (!entry.startsWith(PENDING_STATE_PREFIX) || !entry.endsWith(PENDING_STATE_SUFFIX)) continue;
|
|
601
|
+
const pid = Number(entry.slice(PENDING_STATE_PREFIX.length, -PENDING_STATE_SUFFIX.length));
|
|
602
|
+
const entryPath = path.join(backupDir, entry);
|
|
603
|
+
if (pid !== process.pid && isProcessAlive(pid) && !isStale(entryPath)) {
|
|
604
|
+
// A live owner is mid-commit, so its sidecar is not wreckage to clear - but the pair it is
|
|
605
|
+
// halfway through is no more comparable than an interrupted one, so drift detection is off
|
|
606
|
+
// for this boot either way.
|
|
607
|
+
interrupted = true;
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
try {
|
|
611
|
+
fs.removeSync(entryPath);
|
|
612
|
+
} catch (error) {
|
|
613
|
+
// Keep drift detection on rather than disabling it every boot over a sidecar we cannot clear
|
|
614
|
+
getLogger().warn(`Could not remove an interrupted env config commit (${entry}): ${(error as Error).message}`);
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
interrupted = true;
|
|
618
|
+
}
|
|
619
|
+
if (interrupted) getLogger().warn('An env config commit was interrupted; skipping drift detection for this boot');
|
|
620
|
+
return interrupted;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
function isStale(entryPath: string): boolean {
|
|
624
|
+
try {
|
|
625
|
+
return Date.now() - fs.statSync(entryPath).mtimeMs > PENDING_STATE_STALE_MS;
|
|
626
|
+
} catch {
|
|
627
|
+
return false;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
function isProcessAlive(pid: number): boolean {
|
|
632
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
633
|
+
try {
|
|
634
|
+
process.kill(pid, 0);
|
|
635
|
+
return true;
|
|
636
|
+
} catch (error) {
|
|
637
|
+
return (error as NodeJS.ErrnoException).code === 'EPERM';
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
function freshConfigState(): ConfigState {
|
|
642
|
+
return {
|
|
643
|
+
version: '1.0',
|
|
644
|
+
sources: {},
|
|
645
|
+
originalValues: {},
|
|
646
|
+
emptyScopeOriginals: {},
|
|
647
|
+
snapshots: {},
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
586
651
|
/**
|
|
587
652
|
* Save configuration state to file
|
|
588
653
|
*/
|
|
589
|
-
function
|
|
654
|
+
function serializeConfigState(state: ConfigState): string {
|
|
655
|
+
return JSON.stringify(state, null, 2) + '\n';
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// Returns true when the file was rewritten, false when it already held this state.
|
|
659
|
+
function saveConfigState(rootPath: string, state: ConfigState): boolean {
|
|
590
660
|
const backupDir = getBackupDirPath(rootPath);
|
|
591
661
|
const statePath = path.join(backupDir, STATE_FILE_NAME);
|
|
592
662
|
|
|
@@ -595,7 +665,49 @@ function saveConfigState(rootPath: string, state: ConfigState): void {
|
|
|
595
665
|
|
|
596
666
|
// Atomic write: a torn state file resets to fresh on the next load, losing every
|
|
597
667
|
// restoration record — the blast radius is user config-file content
|
|
598
|
-
atomicWriteFile(statePath,
|
|
668
|
+
return atomicWriteFile(statePath, serializeConfigState(state), { skipIfUnchanged: true });
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
function configStateMatchesDisk(rootPath: string, state: ConfigState): boolean {
|
|
672
|
+
try {
|
|
673
|
+
const statePath = path.join(getBackupDirPath(rootPath), STATE_FILE_NAME);
|
|
674
|
+
return fs.readFileSync(statePath, 'utf8') === serializeConfigState(state);
|
|
675
|
+
} catch {
|
|
676
|
+
return false;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function stageConfigState(rootPath: string, state: ConfigState): boolean {
|
|
681
|
+
const backupDir = getBackupDirPath(rootPath);
|
|
682
|
+
fs.ensureDirSync(backupDir);
|
|
683
|
+
return atomicWriteFile(path.join(backupDir, pendingStateFileName()), serializeConfigState(state));
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// A rename, so an exhausted volume cannot refuse it and leave the config file described by nothing.
|
|
687
|
+
|
|
688
|
+
export function commitStagedConfigState(rootPath: string): boolean {
|
|
689
|
+
const backupDir = getBackupDirPath(rootPath);
|
|
690
|
+
const pendingPath = path.join(backupDir, pendingStateFileName());
|
|
691
|
+
try {
|
|
692
|
+
renameWithRetry(pendingPath, path.join(backupDir, STATE_FILE_NAME));
|
|
693
|
+
return true;
|
|
694
|
+
} catch (error) {
|
|
695
|
+
// Loud: the config file is already on disk, so the confirmed state now describes values it no
|
|
696
|
+
// longer has, and the next boot reads that difference as a manual user edit.
|
|
697
|
+
getLogger().error(`Could not promote the staged env config state at ${pendingPath}: ${(error as Error).message}`);
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Drops the staged state for a config-file write that did not happen; the confirmed record stays.
|
|
703
|
+
|
|
704
|
+
export function discardConfigState(rootPath: string): void {
|
|
705
|
+
const pendingPath = path.join(getBackupDirPath(rootPath), pendingStateFileName());
|
|
706
|
+
try {
|
|
707
|
+
fs.removeSync(pendingPath);
|
|
708
|
+
} catch (error) {
|
|
709
|
+
getLogger().warn(`Could not remove the staged env config state at ${pendingPath}: ${(error as Error).message}`);
|
|
710
|
+
}
|
|
599
711
|
}
|
|
600
712
|
|
|
601
713
|
/**
|
|
@@ -957,20 +1069,49 @@ export function applyRuntimeEnvConfig(
|
|
|
957
1069
|
rootPath: string,
|
|
958
1070
|
options: { isInstall?: boolean } = {}
|
|
959
1071
|
): ConfigObject {
|
|
1072
|
+
const { config, commitState } = prepareRuntimeEnvConfig(fileConfig, rootPath, options);
|
|
1073
|
+
commitState();
|
|
1074
|
+
return config;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
/**
|
|
1078
|
+
* Apply the env layers and hand the state writes back to the caller, so a caller that also persists
|
|
1079
|
+
* the merged config file can commit the pair as a unit (#847): saveState() stages the new state
|
|
1080
|
+
* beside the confirmed one, confirmConfigWritten() renames it over the confirmed one after the
|
|
1081
|
+
* config file lands, and discardConfigState() drops the staged copy if that write never happens.
|
|
1082
|
+
*/
|
|
1083
|
+
export function prepareRuntimeEnvConfig(
|
|
1084
|
+
fileConfig: ConfigObject,
|
|
1085
|
+
rootPath: string,
|
|
1086
|
+
options: { isInstall?: boolean } = {}
|
|
1087
|
+
): {
|
|
1088
|
+
config: ConfigObject;
|
|
1089
|
+
saveState: () => boolean;
|
|
1090
|
+
confirmConfigWritten: () => boolean;
|
|
1091
|
+
commitState: () => boolean;
|
|
1092
|
+
} {
|
|
960
1093
|
const defaultEnvValue = process.env.HARPER_DEFAULT_CONFIG;
|
|
961
1094
|
const configEnvValue = process.env.HARPER_CONFIG;
|
|
962
1095
|
const setEnvValue = process.env.HARPER_SET_CONFIG;
|
|
963
1096
|
|
|
964
|
-
// Load existing state
|
|
1097
|
+
// Load existing state. Only the main thread persists, so only the main thread has wreckage to
|
|
1098
|
+
// clear - and a worker shares its pid, so letting one scan would delete the main thread's
|
|
1099
|
+
// in-flight sidecar as if it were last boot's.
|
|
1100
|
+
const interruptedCommit = isMainThread && takeInterruptedCommit(rootPath);
|
|
965
1101
|
const state = loadConfigState(rootPath);
|
|
966
1102
|
|
|
967
1103
|
// No env vars set and no previous state, nothing to do
|
|
968
1104
|
if (!defaultEnvValue && !configEnvValue && !setEnvValue && Object.keys(state.snapshots).length === 0) {
|
|
969
|
-
return fileConfig;
|
|
1105
|
+
return { config: fileConfig, saveState: () => false, confirmConfigWritten: () => false, commitState: () => false };
|
|
970
1106
|
}
|
|
971
1107
|
|
|
972
|
-
// Detect drift (user manual edits) - only at runtime, not install
|
|
973
|
-
|
|
1108
|
+
// Detect drift (user manual edits) - only at runtime, not install, not on a boot that found an
|
|
1109
|
+
// interrupted commit (where a difference could equally be the write that was in flight), and only
|
|
1110
|
+
// on the main thread: a worker never owns the state, and one re-deriving inside the main thread's
|
|
1111
|
+
// commit window would call its half-written config file a user edit and drop the env-supplied
|
|
1112
|
+
// value for itself alone - serving different config than its siblings, with nothing on disk to
|
|
1113
|
+
// show why.
|
|
1114
|
+
if (!options.isInstall && !interruptedCommit && isMainThread) {
|
|
974
1115
|
const driftedPaths = detectConfigDrift(fileConfig, state);
|
|
975
1116
|
for (const path of driftedPaths) {
|
|
976
1117
|
state.sources[path] = 'user';
|
|
@@ -998,8 +1139,10 @@ export function applyRuntimeEnvConfig(
|
|
|
998
1139
|
processEnvVar(fileConfig, state, 'HARPER_CONFIG', 'HARPER_CONFIG', options);
|
|
999
1140
|
processEnvVar(fileConfig, state, 'HARPER_SET_CONFIG', 'HARPER_SET_CONFIG', options);
|
|
1000
1141
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1142
|
+
return {
|
|
1143
|
+
config: fileConfig,
|
|
1144
|
+
saveState: () => (configStateMatchesDisk(rootPath, state) ? false : stageConfigState(rootPath, state)),
|
|
1145
|
+
confirmConfigWritten: () => commitStagedConfigState(rootPath),
|
|
1146
|
+
commitState: () => saveConfigState(rootPath, state),
|
|
1147
|
+
};
|
|
1005
1148
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parse } from 'yaml';
|
|
2
|
+
|
|
3
|
+
// yaml's prettyErrors frames the offending source lines into `message`, and a config file holds
|
|
4
|
+
// credentials. Neither the cause nor the original stack is carried for the same reason.
|
|
5
|
+
export class ConfigParseError extends Error {
|
|
6
|
+
constructor(filePath: string, error: unknown) {
|
|
7
|
+
const { name, code, linePos } = (error ?? {}) as {
|
|
8
|
+
name?: string;
|
|
9
|
+
code?: string;
|
|
10
|
+
linePos?: { line: number; col: number }[];
|
|
11
|
+
};
|
|
12
|
+
const at = linePos?.[0] ? ` at line ${linePos[0].line}, column ${linePos[0].col}` : '';
|
|
13
|
+
super(`Unable to parse the Harper configuration file at ${filePath}: ${code ?? name ?? 'parse failure'}${at}`);
|
|
14
|
+
this.name = 'ConfigParseError';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function parseConfigFile(contents: string, filePath: string): any {
|
|
19
|
+
try {
|
|
20
|
+
// yaml routes warnings through `process.emitWarning` rather than a throw, so a framed
|
|
21
|
+
// warning would reach stderr with the config's own source lines in it, around this scrub.
|
|
22
|
+
return parse(contents, { logLevel: 'error' });
|
|
23
|
+
} catch (error) {
|
|
24
|
+
// Only yaml's own parse errors frame the source into `message`. Anything else is a fault in
|
|
25
|
+
// the parser, where the message is the whole of the debugging context.
|
|
26
|
+
if (!isYamlParseError(error)) throw error;
|
|
27
|
+
throw new ConfigParseError(filePath, error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isYamlParseError(error: unknown): boolean {
|
|
32
|
+
const { name, linePos } = (error ?? {}) as { name?: string; linePos?: unknown };
|
|
33
|
+
return linePos !== undefined || name === 'YAMLParseError';
|
|
34
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
// Why root config reads must not be async, and why this budget is shared rather than per call:
|
|
4
|
+
// see "Root config watchers must read synchronously" in DESIGN.md (harper#2191).
|
|
5
|
+
const READ_RETRY_BUDGET_MS = 500;
|
|
6
|
+
const READ_RETRY_INITIAL_DELAY_MS = 10;
|
|
7
|
+
const READ_RETRY_MAX_DELAY_MS = 100;
|
|
8
|
+
const readRetrySleepBuffer = new Int32Array(new SharedArrayBuffer(4));
|
|
9
|
+
const retryDeadlines = new Map<string, number>();
|
|
10
|
+
|
|
11
|
+
// A caller that already owns a retry ladder passes `waitForLock` false, so one lock costs one
|
|
12
|
+
// blocking window in total rather than one per rung.
|
|
13
|
+
export function readConfigFileSync(filePath: string, waitForLock: boolean = true): string {
|
|
14
|
+
let delayMs = READ_RETRY_INITIAL_DELAY_MS;
|
|
15
|
+
while (true) {
|
|
16
|
+
try {
|
|
17
|
+
const contents = readFileSync(filePath, 'utf-8');
|
|
18
|
+
retryDeadlines.delete(filePath);
|
|
19
|
+
return contents;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
const remainingBudgetMs = waitForLock && isSharingViolation(error) ? remainingRetryBudgetMs(filePath) : 0;
|
|
22
|
+
if (remainingBudgetMs <= 0) throw error;
|
|
23
|
+
Atomics.wait(readRetrySleepBuffer, 0, 0, Math.min(delayMs, remainingBudgetMs));
|
|
24
|
+
delayMs = Math.min(delayMs * 2, READ_RETRY_MAX_DELAY_MS);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isSharingViolation(error: unknown): boolean {
|
|
30
|
+
if (process.platform !== 'win32') return false;
|
|
31
|
+
const code = (error as { code?: string } | null)?.code;
|
|
32
|
+
return code === 'EPERM' || code === 'EACCES' || code === 'EBUSY';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function remainingRetryBudgetMs(filePath: string): number {
|
|
36
|
+
const now = performance.now();
|
|
37
|
+
let deadline = retryDeadlines.get(filePath);
|
|
38
|
+
// A deadline more than one budget past its expiry belongs to an earlier burst, not this one.
|
|
39
|
+
if (deadline === undefined || now - deadline > READ_RETRY_BUDGET_MS) {
|
|
40
|
+
deadline = now + READ_RETRY_BUDGET_MS;
|
|
41
|
+
retryDeadlines.set(filePath, deadline);
|
|
42
|
+
}
|
|
43
|
+
return deadline - now;
|
|
44
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// See DESIGN.md, "`ready` means the watcher is armed". Platform is a parameter so a test on any
|
|
2
|
+
// host can pin the darwin value, rather than only observing its own.
|
|
3
|
+
export function armGraceMs(platform: string = process.platform): number {
|
|
4
|
+
return platform === 'darwin' ? 20 : 0;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const ARM_GRACE_MS = armGraceMs();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The gate a config watcher opens when its chokidar watcher is really watching: the initial scan
|
|
11
|
+
* has finished *and* the platform's kernel-side warm-up has had its grace. Shared by
|
|
12
|
+
* `RootConfigWatcher` and `OptionsWatcher` because both read the config synchronously, which is
|
|
13
|
+
* what exposes the unarmed window in the first place.
|
|
14
|
+
*/
|
|
15
|
+
export class ArmGate {
|
|
16
|
+
#armed: boolean = false;
|
|
17
|
+
#timer: NodeJS.Timeout | undefined;
|
|
18
|
+
#graceMs: number;
|
|
19
|
+
|
|
20
|
+
// Taken as an argument, not read from the module constant, so the timer branch below is
|
|
21
|
+
// reachable from a host whose own platform has no grace — unit tests are ubuntu-only.
|
|
22
|
+
constructor(graceMs: number = ARM_GRACE_MS) {
|
|
23
|
+
this.#graceMs = graceMs;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get armed(): boolean {
|
|
27
|
+
return this.#armed;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Synchronous where the platform needs no grace, so a watcher with no warm-up to wait out
|
|
31
|
+
// keeps reading inside chokidar's own dispatch.
|
|
32
|
+
arm(onArmed: () => void): void {
|
|
33
|
+
if (this.#armed || this.#timer) return;
|
|
34
|
+
if (!this.#graceMs) {
|
|
35
|
+
this.#armed = true;
|
|
36
|
+
onArmed();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.#timer = setTimeout(() => {
|
|
40
|
+
this.#timer = undefined;
|
|
41
|
+
this.#armed = true;
|
|
42
|
+
onArmed();
|
|
43
|
+
}, this.#graceMs);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Drops a grace still counting down, for a watcher that is closing.
|
|
47
|
+
cancel(): void {
|
|
48
|
+
clearTimeout(this.#timer);
|
|
49
|
+
this.#timer = undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// A replacement watcher has its own scan and its own unarmed window, so the gate arms again
|
|
53
|
+
// with it: for a file that is *absent* when the replacement scans, chokidar reports `ready` and
|
|
54
|
+
// nothing else, and the arming re-read is the only thing that would notice.
|
|
55
|
+
reset(): void {
|
|
56
|
+
this.cancel();
|
|
57
|
+
this.#armed = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
package/config-root.schema.json
CHANGED
|
@@ -172,6 +172,10 @@
|
|
|
172
172
|
]
|
|
173
173
|
},
|
|
174
174
|
"maxHeapMemory": { "type": "number", "description": "Heap memory limit per thread (MB)." },
|
|
175
|
+
"maxIsolated": {
|
|
176
|
+
"type": "integer",
|
|
177
|
+
"description": "Most applications marked isolated that get a dedicated worker thread; the rest fail to load. Default 8."
|
|
178
|
+
},
|
|
175
179
|
"heapSnapshotNearLimit": { "type": "boolean", "description": "Take a heap snapshot when near the heap limit." },
|
|
176
180
|
"preload": {
|
|
177
181
|
"oneOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
|
|
@@ -519,6 +523,10 @@
|
|
|
519
523
|
"type": "string",
|
|
520
524
|
"description": "Max write queue time before rejecting (e.g. '45s')."
|
|
521
525
|
},
|
|
526
|
+
"longTransactionReportThreshold": {
|
|
527
|
+
"type": ["string", "number"],
|
|
528
|
+
"description": "How old a RocksDB transaction handle must be before it is reported in the log (e.g. '5m'). A handle this old can hold write intents that park other writers' commits and pin a read snapshot. Set to 0 to disable the reporting. Default: '5m'"
|
|
529
|
+
},
|
|
522
530
|
"noReadAhead": { "type": "boolean", "description": "Advise OS to not read ahead. Default: false" },
|
|
523
531
|
"randomAccessFields": {
|
|
524
532
|
"type": "boolean",
|
|
@@ -534,6 +542,31 @@
|
|
|
534
542
|
"oneOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
|
|
535
543
|
"description": "Path or array of paths for blob storage. Default: <rootPath>/blobs"
|
|
536
544
|
},
|
|
545
|
+
"blobs": {
|
|
546
|
+
"type": "object",
|
|
547
|
+
"description": "File-backed blob storage settings.",
|
|
548
|
+
"properties": {
|
|
549
|
+
"compression": {
|
|
550
|
+
"type": "object",
|
|
551
|
+
"description": "Opt-in compression for newly written file-backed blobs, keyed by content type: an exact type ('application/json'), a wildcard ('text/*'), or 'default'. Absent means no compression. Each entry is false (never compress the type) or an object { codec, threshold }: codec currently only 'deflate' (the default); threshold is the minimum content size in bytes to compress (default 8192). Matching precedence is exact type, then 'type/*', then 'default'. Types that are already compressed (application/gzip, application/zip, application/zstd, image/*, video/*, audio/*) ship as false and stay uncompressed unless explicitly overridden. Blobs streamed without a known size are not compressed, and a threshold below 8192 only affects streamed writes — buffers under 8KB are stored inline in the record (covered by record-level compression) and never reach blob files. Applies to new writes only; existing blob files are never rewritten.",
|
|
552
|
+
"propertyNames": { "pattern": "^([\\w.+-]+/(\\*|[\\w.+-]+)|default)$" },
|
|
553
|
+
"additionalProperties": {
|
|
554
|
+
"oneOf": [
|
|
555
|
+
{ "const": false },
|
|
556
|
+
{
|
|
557
|
+
"type": "object",
|
|
558
|
+
"properties": {
|
|
559
|
+
"codec": { "const": "deflate" },
|
|
560
|
+
"threshold": { "type": "number", "minimum": 0 }
|
|
561
|
+
},
|
|
562
|
+
"additionalProperties": false
|
|
563
|
+
}
|
|
564
|
+
]
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
"additionalProperties": false
|
|
569
|
+
},
|
|
537
570
|
"blobReadTimeout": {
|
|
538
571
|
"type": "number",
|
|
539
572
|
"description": "Max time (ms) a blob read will wait for an in-progress write to finish before failing with a 503, rather than holding the connection. Default: 20000"
|