@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
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harperfast/harper",
|
|
3
3
|
"description": "Harper is an open-source Node.js performance platform that unifies database, cache, application, and messaging layers into one in-memory process.",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.3.0-beta.1",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://harper.fast",
|
|
7
7
|
"bugs": {
|
|
@@ -74,6 +74,8 @@
|
|
|
74
74
|
"test:unit:lmdb": "HARPER_STORAGE_ENGINE=lmdb npm run test:unit:resources && HARPER_STORAGE_ENGINE=lmdb npm run test:unit:apitests && HARPER_STORAGE_ENGINE=lmdb npm run test:unit:bin",
|
|
75
75
|
"test:unit:components": "mocha \"unitTests/components/**/*.js\"",
|
|
76
76
|
"test:unit:resources": "mocha \"unitTests/resources/**/*.js\" --exclude \"unitTests/resources/**/*.bench.js\"",
|
|
77
|
+
"test:unit:resources:core": "mocha \"unitTests/resources/**/*.js\" --exclude \"unitTests/resources/**/*.bench.js\" --exclude \"unitTests/resources/**/*{[Ii]ndex,[Hh]nsw,[Vv]ector}*.js\"",
|
|
78
|
+
"test:unit:resources:indexes": "mocha \"unitTests/resources/**/*{[Ii]ndex,[Hh]nsw,[Vv]ector}*.js\" --exclude \"unitTests/resources/**/*.bench.js\"",
|
|
77
79
|
"bench": "mocha \"unitTests/resources/caching-rocks-database.bench.js\"",
|
|
78
80
|
"test:unit:bin": "mocha \"unitTests/bin/**/*.js\"",
|
|
79
81
|
"test:unit:apitests": "node ./dist/bin/harper.js stop && mocha \"unitTests/apiTests/**/*-test.mjs\"",
|
|
@@ -84,6 +86,7 @@
|
|
|
84
86
|
"test:unit:utility": "mocha \"unitTests/utility/**/*.js\" --exclude \"unitTests/utility/logging/**/*\"",
|
|
85
87
|
"test:unit:server": "mocha \"unitTests/server/**/*.js\"",
|
|
86
88
|
"test:unit:config": "mocha \"unitTests/config/**/*.js\"",
|
|
89
|
+
"test:unit:windows": "node unitTests/windowsGate.mjs",
|
|
87
90
|
"test:unit:typestrip": "env NODE_OPTIONS=\"--conditions=typestrip\" npm run test:unit",
|
|
88
91
|
"test:unit:typestrip:all": "npm run test:unit:typestrip unitTests"
|
|
89
92
|
},
|
|
@@ -131,7 +134,7 @@
|
|
|
131
134
|
},
|
|
132
135
|
"devDependencies": {
|
|
133
136
|
"@harperfast/code-guidelines": "^0.1.2",
|
|
134
|
-
"@harperfast/integration-testing": "^0.
|
|
137
|
+
"@harperfast/integration-testing": "^1.0.0",
|
|
135
138
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
136
139
|
"@types/busboy": "^1.5.4",
|
|
137
140
|
"@types/fs-extra": "^11.0.4",
|
|
@@ -150,12 +153,16 @@
|
|
|
150
153
|
"chai": "^6.2.0",
|
|
151
154
|
"chai-as-promised": "^8.0.2",
|
|
152
155
|
"chai-integer": "^0.1.0",
|
|
153
|
-
"
|
|
156
|
+
"compression": "^1.8.1",
|
|
157
|
+
"compression-1.7": "npm:compression@1.7.4",
|
|
158
|
+
"eventsource": "^5.0.0",
|
|
154
159
|
"globals": "^17.0.0",
|
|
155
160
|
"intercept-stdout": "0.1.2",
|
|
156
161
|
"mkcert": "^3.2.0",
|
|
157
162
|
"mocha": "^11.7.5",
|
|
158
163
|
"mqtt": "^5.15.1",
|
|
164
|
+
"on-finished": "^2.4.1",
|
|
165
|
+
"on-headers": "^1.1.0",
|
|
159
166
|
"openai": "^7.0.0",
|
|
160
167
|
"oxlint": "^1.31.0",
|
|
161
168
|
"prettier": "~3.9.0",
|
|
@@ -172,7 +179,7 @@
|
|
|
172
179
|
},
|
|
173
180
|
"dependencies": {
|
|
174
181
|
"@aws-sdk/client-s3": "^3.1012.0",
|
|
175
|
-
"@aws-sdk/lib-storage": "3.
|
|
182
|
+
"@aws-sdk/lib-storage": "3.1116.0",
|
|
176
183
|
"@endo/static-module-record": "^1.1.2",
|
|
177
184
|
"@fastify/autoload": "^6.3.1",
|
|
178
185
|
"@fastify/compress": "^8.3.1",
|
|
@@ -190,7 +197,7 @@
|
|
|
190
197
|
"@turf/distance": "6.5.0",
|
|
191
198
|
"@turf/helpers": "6.5.0",
|
|
192
199
|
"@turf/length": "6.5.0",
|
|
193
|
-
"alasql": "4.
|
|
200
|
+
"alasql": "4.19.0",
|
|
194
201
|
"amaro": "^1.1.8",
|
|
195
202
|
"argon2": "0.45.1",
|
|
196
203
|
"asn1js": "3.0.10",
|
|
@@ -212,7 +219,7 @@
|
|
|
212
219
|
"human-readable-ids": "1.0.4",
|
|
213
220
|
"inquirer": "8.2.7",
|
|
214
221
|
"is-number": "7.0.0",
|
|
215
|
-
"joi": "17.13.
|
|
222
|
+
"joi": "17.13.6",
|
|
216
223
|
"json-bigint-fixes": "1.1.0",
|
|
217
224
|
"jsonata": "1.8.9",
|
|
218
225
|
"jsonwebtoken": "9.0.3",
|
|
@@ -230,7 +237,7 @@
|
|
|
230
237
|
"normalize-path": "^3.0.0",
|
|
231
238
|
"ora": "8.2.0",
|
|
232
239
|
"ordered-binary": "1.6.1",
|
|
233
|
-
"papaparse": "5.
|
|
240
|
+
"papaparse": "5.6.0",
|
|
234
241
|
"passport": "0.7.0",
|
|
235
242
|
"passport-http": "0.3.0",
|
|
236
243
|
"passport-local": "1.0.0",
|
|
@@ -261,6 +268,7 @@
|
|
|
261
268
|
}
|
|
262
269
|
},
|
|
263
270
|
"optionalDependencies": {
|
|
271
|
+
"@harperfast/hnsw": "0.3.0",
|
|
264
272
|
"bufferutil": "4.1.0",
|
|
265
273
|
"segfault-handler": "1.3.0",
|
|
266
274
|
"utf-8-validate": "5.0.10"
|
package/resources/DESIGN.md
CHANGED
|
@@ -12,23 +12,26 @@ See also: `../DESIGN.md` for cross-cutting non-obvious internals (RecordObject p
|
|
|
12
12
|
|
|
13
13
|
## File overview
|
|
14
14
|
|
|
15
|
-
| File
|
|
16
|
-
|
|
|
17
|
-
| `Resource.ts`
|
|
18
|
-
| `Table.ts`
|
|
19
|
-
| `Resources.ts`
|
|
20
|
-
| `RequestTarget.ts`
|
|
21
|
-
| `ResourceInterface.ts`
|
|
22
|
-
| `RecordEncoder.ts`
|
|
23
|
-
| `IterableEventQueue.ts`
|
|
24
|
-
| `transaction.ts`
|
|
25
|
-
| `auditStore.ts`
|
|
26
|
-
| `
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
15
|
+
| File | Purpose |
|
|
16
|
+
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `Resource.ts` | Base class; `transactional()` wrapper; method routing |
|
|
18
|
+
| `Table.ts` | Table-as-Resource implementation. Factory `makeTable()` returns a `TableResource` subclass per table. **See section markers below.** |
|
|
19
|
+
| `Resources.ts` | Registry mapping URL paths → Resource classes |
|
|
20
|
+
| `RequestTarget.ts` | Parses path/query into a structured target |
|
|
21
|
+
| `ResourceInterface.ts` | Type definitions (`Context`, `Record`, etc.) |
|
|
22
|
+
| `RecordEncoder.ts` | msgpack encoding + `entryMap` (record → storage entry) |
|
|
23
|
+
| `IterableEventQueue.ts` | Async iterable used for subscriptions and streaming responses |
|
|
24
|
+
| `transaction.ts` | Per-request transaction object stored in `contextStorage` |
|
|
25
|
+
| `auditStore.ts` | Append-only audit log records |
|
|
26
|
+
| `derivedIndexRuntime.ts` | Lock-elected, exact-cursor delivery of committed RocksDB log mutations to derived-index backends; chunked collection, flush cadence, rebuild phase, epoch fencing, shared readiness, lag policy. Design: root `DESIGN.md` § Derived-index runtime |
|
|
27
|
+
| `derivedIndexRegistry.ts` | Worker-local registration counts (which tables emit cache-eviction markers) and per-table write-admission checks for the lag policy |
|
|
28
|
+
| `recordLock.ts` | Exclusive record locks (harper#483): option contract, native key lock primitives (`lockAttemptKey`, `makeKeyLockHandle`, `acquireRecordKey`) |
|
|
29
|
+
| `nodeIdMapping.ts` | Maps node IDs ↔ timestamps for replication ordering |
|
|
30
|
+
| `openApi.ts` | Generates OpenAPI/JSON Schema from `@export` schemas |
|
|
31
|
+
| `defineTable.ts` | Code-first table authoring (`defineTable` + `types`) — a TS front-end to the canonical `table()` model |
|
|
32
|
+
| `defineResource.ts` | Per-method request contract (`defineResource` / `Resource.withSchema`, `t`, `schemaOf`) — typed handlers + edge validation |
|
|
33
|
+
| `jsonSchemaTypes.ts` | Shared `JsonSchemaFragment` IR + `attributeToFragment` projector (one vocabulary for validation/OpenAPI/MCP) |
|
|
34
|
+
| `analytics/` | Telemetry recording (separate from monitoring) |
|
|
32
35
|
|
|
33
36
|
---
|
|
34
37
|
|
|
@@ -57,53 +60,203 @@ Static methods are protocol entry points (each wrapped in `transactional()`); in
|
|
|
57
60
|
|
|
58
61
|
One giant `makeTable()` factory that returns a `TableResource extends Resource` class. The file is divided into the sections below; each is anchored by a `// #section: <name>` marker — grep for the marker (or use VS Code's go-to-symbol within the section) to land directly.
|
|
59
62
|
|
|
60
|
-
| Section marker | Contents
|
|
61
|
-
| -------------------------------- |
|
|
62
|
-
| `#section: setup-and-factory` | `makeTable(options)` entry, attribute parsing & primary-key detection, replication wiring, `class Updatable` (RecordObject prototype: `getUpdatedTime`, `getExpiresAt`, `addTo`, `subtractFrom`). Ends where `class TableResource` opens.
|
|
63
|
-
| `#section: static-config` | Static configuration properties: `name`, `primaryStore`, `auditStore`, `primaryKey`, `indices`, `audit`, `databasePath`, `attributes`, `replicate`, `sealed`, `splitSegments`, `getResidencyById`, `dbisDB`, `schemaDefined`, `expirationMS`.
|
|
64
|
-
| `#section: resource-registry` | `sourcedFrom()` (cache/source hierarchy — the largest static), `isCaching`, `shouldRevalidateEvents`, `getResource()`, `_updateResource`, `ensureLoaded()`.
|
|
65
|
-
| `#section: lifecycle-admin` | `getNewId()` (UUID / autoincrement / prefix / time-based strategies), `setTTLExpiration`, residency (`getResidencyRecord`, `setResidency`, `setResidencyById`, `getResidency`), `enableAuditing`, `coerceId`, `dropTable`.
|
|
66
|
-
| `#section: read-path` | `get()` overloads & impl.
|
|
67
|
-
| `#section: authz-hooks` | `allowRead`, `allowUpdate`, `allowCreate`, `allowDelete`.
|
|
68
|
-
| `#section: write-path-public` | `update()`, `save()`, `addTo()`, `subtractFrom()`, `getMetadata`, `getRecord`, `getChanges`, `_setChanges`, `setRecord`, `invalidate()`, `operation()`, `put()`, `create()`, `patch()`.
|
|
69
|
-
| `#section: write-path-internals` | **`_writeUpdate()` — the central write routine** (versioning, conflict resolution, audit, residency, replication metadata, blob orphan tracking). The `write.skipped` flag mentioned in `../DESIGN.md` is set in this method's early-return paths. Also `_writeInvalidate`, `_writeRelocate`, `_recordRelocate`, `evict()`, `lock()
|
|
70
|
-
|
|
|
71
|
-
| `#section:
|
|
72
|
-
| `#section:
|
|
73
|
-
| `#section:
|
|
74
|
-
| `#section:
|
|
75
|
-
|
|
|
63
|
+
| Section marker | Contents |
|
|
64
|
+
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
65
|
+
| `#section: setup-and-factory` | `makeTable(options)` entry, attribute parsing & primary-key detection, replication wiring, `class Updatable` (RecordObject prototype: `getUpdatedTime`, `getExpiresAt`, `addTo`, `subtractFrom`). Ends where `class TableResource` opens. |
|
|
66
|
+
| `#section: static-config` | Static configuration properties: `name`, `primaryStore`, `auditStore`, `primaryKey`, `indices`, `audit`, `databasePath`, `attributes`, `replicate`, `sealed`, `splitSegments`, `getResidencyById`, `dbisDB`, `schemaDefined`, `expirationMS`. |
|
|
67
|
+
| `#section: resource-registry` | `sourcedFrom()` (cache/source hierarchy — the largest static), `isCaching`, `shouldRevalidateEvents`, `getResource()`, `_updateResource`, `ensureLoaded()`. |
|
|
68
|
+
| `#section: lifecycle-admin` | `getNewId()` (UUID / autoincrement / prefix / time-based strategies), `setTTLExpiration`, residency (`getResidencyRecord`, `setResidency`, `setResidencyById`, `getResidency`), `enableAuditing`, `coerceId`, `dropTable`. |
|
|
69
|
+
| `#section: read-path` | `get()` overloads & impl. |
|
|
70
|
+
| `#section: authz-hooks` | `allowRead`, `allowUpdate`, `allowCreate`, `allowDelete`. |
|
|
71
|
+
| `#section: write-path-public` | `update()`, `save()`, `addTo()`, `subtractFrom()`, `getMetadata`, `getRecord`, `getChanges`, `_setChanges`, `setRecord`, `invalidate()`, `operation()`, `put()`, `create()`, `patch()`. |
|
|
72
|
+
| `#section: write-path-internals` | **`_writeUpdate()` — the central write routine** (versioning, conflict resolution, audit, residency, replication metadata, blob orphan tracking). The `write.skipped` flag mentioned in `../DESIGN.md` is set in this method's early-return paths. Also `_writeInvalidate`, `_writeRelocate`, `_recordRelocate`, `evict()`, `lock()`/`unlock()` (record locks — see `../DESIGN.md`), `delete()`, `_writeDelete`. |
|
|
73
|
+
| `isPlainOptions` | _(after the class)_ argument-position helper for `lock()` (distinguishes `lock(options)` from `lock(target, options)`) |
|
|
74
|
+
| `#section: search-query` | `search()` (the query engine — index selection, filter evaluation), `transformToOrderedSelect` (select-clause ordering), `transformEntryForSelect` (record → response shape). |
|
|
75
|
+
| `#section: pub-sub` | `subscribe()` (subscription request handling, replay, cursor management), `subscribeOnThisThread`, `doesExist()`, `publish()`, `_writePublish()`. |
|
|
76
|
+
| `#section: validation` | `validate(record, patch?)` — schema enforcement, computed attributes, attribute coercion. |
|
|
77
|
+
| `#section: stats-admin` | `getUpdatedTime`, `addAttributes`, `removeAttributes`, `getSize`, `getAuditSize`, `getStorageStats`, `getRecordCount`, `updatedAttributes` (schema diff machinery). |
|
|
78
|
+
| `#section: computed-history` | `setComputedAttribute`, `deleteHistory`, `getHistory` (generator), `getHistoryOfRecord`, `clear`, `cleanup`, `_readTxnForContext`. |
|
|
79
|
+
| _(after the class)_ | `getFromSource()` — cache miss → source load (see `../DESIGN.md` for the resolve-before-commit timing trap); local helpers (`coerceType`, `isDescendantId`, etc.). |
|
|
76
80
|
|
|
77
81
|
---
|
|
78
82
|
|
|
79
83
|
## "Where is X" cheat sheet
|
|
80
84
|
|
|
81
|
-
| Question
|
|
82
|
-
|
|
|
83
|
-
| How is a CRUD request authorized?
|
|
84
|
-
| Where does versioning / conflict resolution happen?
|
|
85
|
-
| How does `search()` choose an index?
|
|
86
|
-
| How are subscriptions replayed?
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
| How
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
| How
|
|
96
|
-
| How does
|
|
97
|
-
| How
|
|
98
|
-
|
|
|
99
|
-
| How
|
|
85
|
+
| Question | Where |
|
|
86
|
+
| ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
87
|
+
| How is a CRUD request authorized? | `Table.ts → #section: authz-hooks`; defaults in `Resource.ts` (`allowRead` etc.) |
|
|
88
|
+
| Where does versioning / conflict resolution happen? | `Table.ts → _writeUpdate` (`#section: write-path-internals`) |
|
|
89
|
+
| How does `search()` choose an index? | `Table.ts → search` (`#section: search-query`) |
|
|
90
|
+
| How are subscriptions replayed? | `Table.ts → subscribe` (`#section: pub-sub`) |
|
|
91
|
+
| Can a saved audit cursor still catch up, or has its history been pruned? | `auditStore.ts → getAuditFloor` — internal; there is deliberately no public accessor (harper#2458). **No resume path consumes it yet** — harper#2448 is to have `Table.subscribe` read it inside the resume, so the check and the replay cannot drift apart; until then a `startTime` below the floor is still silently truncated. Returns the database-scoped floor: a cursor below it must resync, and `Infinity` means the floor is unknown (fails closed). `cursor >= floor` means only that no prune that ran _with a floor recorded_ removed history _after_ the cursor (nothing is promised below the FLOOR — that history is what a prune takes; `[floor, cursor)` is below the cursor but still covered). Two things it cannot see: history a legacy prune removed _before_ the floor existed, which a clock rollback can leave the stamped starting floor below; and a `restore_backup`/checkpoint rollback, since it is not a generation check (harper#2451). See "Audit retention floor" below. |
|
|
92
|
+
| How is the response body shaped (select clause)? | `Table.ts → transformEntryForSelect` (`#section: search-query`) |
|
|
93
|
+
| Where is record-level TTL evaluated? | `Table.ts → setTTLExpiration` (`#section: lifecycle-admin`); `Updatable.getExpiresAt` (`#section: setup-and-factory`). Stored expiry metadata is resolved in the `_writeUpdate` commit closure: `options.expiresAt ?? context.expiresAt ?? (record @expiresAt field, if finite & ≥ 0) ?? table default`. This metadata drives read-hiding + the cleanup sweep. The `@expiresAt` attribute is authoritative for **direct** put/patch only; cache/source fills persist via `recordUpdater` and derive expiry from `sourceContext.expiresAt` (source freshness / table default), not the field. |
|
|
94
|
+
| Why does `search()` hide a row that's past its TTL but not yet swept? | `Table.ts → transformEntryForSelect` unconditionally treats `entry.expiresAt < Date.now()` as gone (lazy eviction on read) — correct for a SELECT, but a mutation locating rows to overwrite needs the opposite: pass `target.includeExpired = true` (read by the SQL engine's `runUpdate`/`runDelete` via `SqlEngineContext.includeExpiredRows`) to treat such a row as a live match, matching the leniency a direct by-id `put`/`patch` already has (they skip this check entirely, since `Resource.patch`'s static options don't request `ensureLoaded`). |
|
|
95
|
+
| How are residencies enforced (replication)? | `Table.ts → #section: lifecycle-admin` (residency block: `getResidencyRecord`, `setResidency`, `setResidencyById`, `getResidency`) |
|
|
96
|
+
| How is the RecordObject prototype applied? | `RecordEncoder.ts` (see `../DESIGN.md`) |
|
|
97
|
+
| Where is the per-request transaction stored? | `transaction.ts` + `contextStorage` (AsyncLocalStorage) |
|
|
98
|
+
| What is in `context.transaction` when no scope owns one? | Whatever the last table call left there. A completed scope leaves `RELEASED_TRANSACTION` (`DatabaseTransaction.ts`), which reads latest and no-ops on commit. The next table call finds no transaction and `Table.ts → txnForContext` installs an `ImmediateTransaction` in the slot. It reports `open === OPEN`, but `transaction()` and `Resource`'s dispatcher gate on `isJoinableScope` — OPEN _and_ staging its writes for a later commit — so they never join it and start their own scope instead (#2292); `txnForContext` keeps returning it for reads and for writes that reach no wrapper, and those commit per write. It is also the only transaction that opens its native handle inside its own `commit()` (its `getReadTxn` never opens one), which is why `commit()` re-reads `this.transaction` after its save loop (#2288). |
|
|
99
|
+
| How do I find a transaction that is holding write intents and is never reaped? | Three log surfaces, joined by the native transaction id (`longLivedTransactions.ts`, #2471). `runLongLivedTransactionSweep()` runs on the **main thread only** — rocksdb-js's registry is process-global, so one sweep sees every worker's handles — and names any handle open past `storage.longTransactionReportThreshold` (default `5m`, `0` disables all three), including handles no `DatabaseTransaction` owns. Changing the threshold clears the accrued backoff, so a handle already under observation is re-measured against the new value. `reportIfLongLived()` in each worker's monitor reports every link holding its own handle under that link's own id, adding `startedFrom`, the table, and the state keeping it alive (`source-apply`, `replay`, `commit-phase`, `active` when written in the current or preceding monitor tick), which is what the reap branches below it deliberately do not do. Attribution lines are capped at 10 per monitor tick; a summary names deferred holders, whose due backoff remains intact for a later tick. Attribution suppression is keyed on database path, native id, and handle-open time, so a reattached descriptor id cannot inherit its predecessor's backoff. The two stuck-commit logs (`checkOverloaded()` and `abandonCommitAfterDeadline()`) append holder candidates from **every** database, the commit's own first and then by age — the verification table is one process-global slot array, so a holder in another database parks this commit at the same rate — never filtered by age, because a coordinated retry can park on a transaction younger than itself. |
|
|
100
|
+
| How does a query opt out of a read snapshot? | Pass `snapshot: false` on the search request (e.g. `get_analytics`). `Table.ts → search` calls `txn.useReadTxn(snapshot === false)`; on RocksDB `DatabaseTransaction.getReadTxn` then builds the read txn with `{ disableSnapshot: true }` so a long scan reads latest without pinning a snapshot. No-op on LMDB (`LMDBTransaction.useReadTxn`). |
|
|
101
|
+
| How does a URL path map to a Resource? | `Resources.ts → getMatch` (exact/prefix fast path) then `matchParamRoute` (parameterised routes); see "Path routing" below |
|
|
102
|
+
| What do chained conditions (`a=ge=X&=le=Y`) mean over array values? | SAME-ELEMENT scoping: `prepareConditions` (`Table.ts → search`) collapses the chain into one range comparator (`gele`/`gtlt`/…) before execution, so the indexed path (per-element index entries, one range scan) and the unindexed path (`search.ts → attributeComparator`, per-element `some` over the collapsed predicate) agree. Repeating the attribute as two independent conditions is independently existential (different elements may satisfy different legs). Only a single `and`-chained leg is supported — `\|=` and a second `&=` are rejected. An indexed scan whose range spans more than one indexed value collapses to one result per record before paging (`search.ts → distinctRecords`, #2434), so `limit`/`offset` count records rather than index entries; element equality stays uncollapsed because `[indexedValue, primaryKey]` is already unique. Pinned by `unitTests/resources/query-array-scoping.test.js`; known gaps: chained-leg values are never type-coerced (#2433), an undeclared (untyped) indexed attribute holding an array still repeats per entry, error paths (#2435). |
|
|
103
|
+
| How does HNSW keep the graph connected on delete? | `indexes/HierarchicalNavigableSmallWorld.ts → index()` delete path: zero-degree orphans reindexed via `needsReindexing`; severed multi-node islands detected and reconnected by `repairSeveredNeighbors` (#1712) |
|
|
104
|
+
| How is a filter applied _during_ a vector search? | Predicate-aware traversal (#1241): `search.ts → executeConditions` composes companion AND conditions with request `vectorFilter` / `rowFilter` predicates into one `(primaryKey) => boolean` (`composeRecordFilter`) and passes it to `HierarchicalNavigableSmallWorld.search(cond, ctx, { filter })`. The filter gates result admission at layer 0 only (routing ignores it, ACORN-style); a visit budget (`filterExpansion`) bounds the under-filled/selective case. Very selective _condition_ filters are instead diverted to the exact brute-force path by the query planner's `estimateCountAsSort` ordering. |
|
|
105
|
+
| How does post-ordering resolve vector distances safely? | Each comparator owns its `Sort`, passes it directly to the custom-index resolver, and caches distances by that immutable per-query sort object. |
|
|
106
|
+
| How is application row filtering applied? | Authorization admission happens in the resource operation before query work. The legacy `allow*` hook, when armed by the protocol, is evaluated once with its historical receiver semantics; overriding it never changes its scope. An operation override may add indexed conditions and/or attach the JavaScript-only synchronous `target.rowFilter(record, context)`. `Table.search` composes it with query filters and rechecks the final materialized cache/source record. `SubscriptionRequest.rowFilter` covers full-row events; `eventFilter(event, context)` explicitly handles tombstones/messages/raw events. Prefer indexed conditions because an opaque predicate may inspect every admitted candidate and `limit` applies after filtering. |
|
|
107
|
+
|
|
108
|
+
**An audit record carries two clocks; never substitute one for the other (harper#2412 stage 0b).**
|
|
109
|
+
`AuditRecord.version` is the originating write's record version — LWW ordering in
|
|
110
|
+
`precedesExistingVersion`, `@updatedTime`, ETag/`Last-Modified`. Historical audit-only entries may
|
|
111
|
+
carry the surviving version instead. `AuditRecord.txnLogKey` is that
|
|
112
|
+
entry's key in the per-origin transaction log: write identity, the record→log lookup
|
|
113
|
+
(`auditStore.get(logKey, tableId, id, nodeId)`), and every resume cursor. On LMDB these have always
|
|
114
|
+
been distinct fields; on RocksDB the read surface used to overwrite `version` with the log key, and
|
|
115
|
+
`#2409`'s `recordVersion` alias is now absorbed back into `version`.
|
|
116
|
+
|
|
117
|
+
They hold the same value for every write whose record version is its own commit timestamp, which is
|
|
118
|
+
every ordinary local write, so a bug that confuses them stays invisible until a **source fill**
|
|
119
|
+
(`getFromSource`, core #2065): the record is stored at the source-reported version while its log
|
|
120
|
+
entry is keyed at the fill's commit. A RocksDB record stores its version in the existing word and,
|
|
121
|
+
when the clocks diverge, keeps its audit head in `additionalAuditRefs`; stage 2 can replace that
|
|
122
|
+
compatibility pointer with a dedicated log-key word.
|
|
123
|
+
|
|
124
|
+
Consequences worth knowing:
|
|
125
|
+
|
|
126
|
+
- **Identity is `(nodeId, log key)`, never a version.** `isAuditEntryWrite` (`auditStore.ts`) is the
|
|
127
|
+
single predicate; `removeAuditEntry`'s tombstone removal and `blob.ts`'s orphan sweep both gate on
|
|
128
|
+
it, and both retain rather than delete when identity is unknown. A version compare there would let
|
|
129
|
+
one write authorize destroying another's tombstone or blob.
|
|
130
|
+
- **A RocksDB applied write carries its own record version.** `TransactionWrite.recordVersion`, set from
|
|
131
|
+
`options.version` by every `_write*` builder and read in `save()` only when the transaction is
|
|
132
|
+
`sourceApply` or `isReplay`, is how a replication receiver stores the origin's version while the
|
|
133
|
+
transaction commits under the origin's log key — so a peer's copy of an origin's log stays in the
|
|
134
|
+
origin's clock. New audit entries persist that write version even when an out-of-order merge leaves
|
|
135
|
+
a newer record version in the primary store. `getAppliedWriteVersion` also bounds historical
|
|
136
|
+
overloaded values by `txnLogKey`. One frame can carry writes at different record versions, so this
|
|
137
|
+
cannot be a per-transaction value. Deprecated LMDB keeps its legacy transaction-version apply
|
|
138
|
+
behavior.
|
|
139
|
+
- **`additionalAuditRefs[].version` is a log key, not a version.** Every consumer follows it straight
|
|
140
|
+
into `auditStore.get` (`Table.ts`'s `auditRefsToVisit`). The list carries folded out-of-order
|
|
141
|
+
branches and, when a RocksDB record version differs from its log key, the record's own audit head.
|
|
142
|
+
Under stage 2 the stored reference field can be renamed; until then, "fixing" it to the record
|
|
143
|
+
version silently unaddresses the entry it points at.
|
|
144
|
+
- **Crash replay uses both.** `replayLogs` delimits transactions by `txnLogKey` (which is also what
|
|
145
|
+
`CorruptFrameStop.truncatedVersions` records) and replays each write at its stored `version`.
|
|
146
|
+
Stamping a replayed record at its log key would move its version forward and make a later
|
|
147
|
+
legitimate write look stale.
|
|
148
|
+
- **Compatibility surfaces still report `localTime` as the transaction timestamp.** Subscription,
|
|
149
|
+
history, and pro-to-core replication event shapes predate this internal name and remain unchanged;
|
|
150
|
+
no on-disk or on-wire identifier changes in this stage.
|
|
100
151
|
|
|
101
152
|
**QUERY admission uses the body projection.** `Resource.transactional` resolves an asynchronous HTTP QUERY body before resource resolution, recursively clones away client-supplied `checkPermission`, and copies the body's `select` onto the operation admission target before `allowRead`. After authorization, `Resource.query` transfers only the narrowed projection to the body target. This ensures a body-only relationship select is checked before `Table.search`; permission-control fields from QUERY data must never reach a search target.
|
|
102
153
|
|
|
103
154
|
**Async false-mode read gates preserve the streaming contract.** `Table.search` returns an `ExtendedIterable` carrying the internal `SEARCH_AUTHORIZATION` promise. Static `Resource.search` and `query` await that verdict before returning a response; on success the wrapper initializes the real search before the transaction settles so its normal read snapshot stays reserved until iteration completes. The marker follows supported iterable transforms and retains `selectApplied`/`getColumns`, so async or mapped delegation cannot turn a denial into a truncated successful response.
|
|
104
155
|
|
|
156
|
+
**Native query waits start on consumption.** A positive native `waitForIndexMilliseconds` preserves instance `Table.search`'s synchronous iterable result and normal `.map()`/`.concat()` composition. The custom-index adapter supplies a start gate: HNSW validates options and generation readiness synchronously, then waits for the first async pull before capturing its fixed coverage target. Zero-size pages start no native work. Count pages still materialize before returning.
|
|
157
|
+
|
|
158
|
+
Index waits use the ordinary transaction timeout; they do not renew it. The adapter reuses the range-scan snapshot guard, loads through the captured read handle, and checks predicate reads so expiration cannot silently switch to latest-state reads. Iterator closure aborts pending waits and skips late result materialization. OR/concatenated prefixes may stream before a later branch fails. Waiting queries do not publish a coverage header; clients must consume the stream and check its error records. HTTP first-item status deferral is tracked separately in Harper #2670.
|
|
159
|
+
|
|
105
160
|
**False-mode collection write gates stay per dispatch.** Built-in array PUT, query DELETE, and publish perform one request-scoped `allowUpdate`, `allowDelete`, or `allowCreate` verdict respectively. After query DELETE authorizes, it scans with a private cloned target whose permission check is disabled; the caller target stays untouched, and concurrent reads using it still run `allowRead`. Static publish overload routing marks the fresh per-dispatch resource receiver in `staticResourceDispatch.ts`, so copied targets and delayed delegation retain the `(target, message)` signature without putting reusable state on caller objects.
|
|
106
161
|
|
|
162
|
+
**Array PUT is a collection dispatch in both modes.** `Class.put(batch, context)` arrives with no target, so `transactional` synthesizes one — and the collection it inferred from the null id has to carry over onto it, or the resource resolves as a single record with a null primary key and the batch never fans out. Default (instance) mode then dispatches per element through `getResource`, and each element call must carry its own normalized target in the second position — minted by `elementTargetFactory` so the element's id and `isCollection === false` sit on top of the request's query and route metadata, with `checkPermission` deliberately omitted so a per-element dispatch cannot re-arm the verdict the collection receiver already gave. Each element gets its own object, because its id must not be visible to a sibling whose dispatch resolves later; the request's contribution is resolved once for the batch rather than deep-cloned per element, and nested metadata is shared rather than copied — not the outer collection target and not the context: `Table`'s back-compat `put(target, record)` shift only recognizes a target that is a `RequestTarget`, so a context there is taken for the record and staged as record data (harper#2000). A default-mode `put()` override consequently sees one call per element with that element's id and `isCollection === false`; a component that needs the whole array in one call belongs in `loadAsInstance === false` mode.
|
|
163
|
+
|
|
164
|
+
**A malformed element fails the whole batch, and never abandons a sibling write.** The dispatch loop starts each element's write as it goes, so an element that throws _synchronously_ — `null`, or an id the store rejects — aborts the loop with earlier writes already in flight. Those are settled before the batch rejects: otherwise a sibling that rejects afterwards has no handler and surfaces as an unhandled rejection. Any element that is not an object — `null`, `undefined`, or a primitive — is rejected _before_ anything is dispatched, so a malformed body cannot race a sibling's write and nothing needs unwinding. The nullish case alone is not enough: only a `Table`'s own key validation rejects a primitive later, so a plain `Resource`, or any `put()` override that writes onto the record it is handed, would otherwise be given one. For a failure raised once dispatch is underway the batch reports the **earliest-index** one, uniformly — the same rule whether that element's `getResource` resolved synchronously or asynchronously, so the reported error does not move with cache residency — and the surrounding transaction rolls every element back — array PUT is all-or-nothing, not per-element reporting. The up-front rejection names the offending index as a `ClientError`, so a malformed body cannot land as a 500 carrying an engine-generated `TypeError`. A resource class that implements no `put` answers 405 through `missingMethod` here, matching the single-record path rather than throwing a bare `TypeError`.
|
|
165
|
+
|
|
166
|
+
**The batch cannot settle while an element is outstanding.** `settleElements` — not `Promise.all` — closes the fan-out. `Promise.all` rejects the batch on the first failing element, which lets `transactional` unwind the transaction while a slower element is still resolving its resource; that element then stages its write against no live batch and commits on its own, leaving a _partially applied_ array PUT. It is only reachable once the async branch passes the target rather than the context — before that the late write failed for its own reasons and hid the hole — so the two fixes belong together. Every element has to stage or fail its write before the transaction may unwind. When several elements fail, the batch reports the **earliest-index** failure rather than whichever rejected first in wall-clock time, so the error a client sees does not move with scheduling. Only that one failure is reported: the framework does not attach a `cause` onto it, because the thrown value belongs to application code and may be a primitive, frozen, or a shared singleton that a per-request mutation would contaminate for every later request.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Audit retention floor
|
|
171
|
+
|
|
172
|
+
`Table.subscribe`'s `startTime` replay just begins wherever the audit log now begins, so a consumer
|
|
173
|
+
resuming below the retention horizon is silently handed a short replay. The floor is the primitive
|
|
174
|
+
that makes that detectable (harper#2447). It is internal, with deliberately no public accessor, and **nothing
|
|
175
|
+
consumes it yet**: harper#2448 is to put the check inside `Table.subscribe` itself — the same shape as
|
|
176
|
+
replication's `shouldForceBaseCopyForRetention`, and the only one where the floor cannot move between
|
|
177
|
+
being read and being acted on. Until then the short replay above is unchanged.
|
|
178
|
+
|
|
179
|
+
**The invariant: every path that prunes audit history raises the floor BEFORE removing anything.**
|
|
180
|
+
There are five, and the ordering is the whole guarantee — a floor written after the removal is lost
|
|
181
|
+
if the process dies in between, and the surviving lower floor then certifies a cursor whose history
|
|
182
|
+
is gone. Over-reporting (a floor covering more than the prune actually removed) costs a consumer one
|
|
183
|
+
unnecessary resync; under-reporting loses its data with no signal. So `raiseAuditFloor` is called
|
|
184
|
+
first and a throw from it is what stops the prune.
|
|
185
|
+
|
|
186
|
+
| Prune path | Engine |
|
|
187
|
+
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
188
|
+
| `scheduleAuditCleanup` retention loop (`auditStore.ts`) | LMDB |
|
|
189
|
+
| `scheduleAuditCleanup` → `purgeLogs` | RocksDB |
|
|
190
|
+
| `purgeAgedLogs` (boot/recovery, called from `replayLogs.ts`) | RocksDB |
|
|
191
|
+
| `Table.deleteHistory` | LMDB (`RocksTransactionLogStore.remove()` is a no-op, so it must NOT raise) |
|
|
192
|
+
| `delete_transaction_logs_before` whole-database branch (`ResourceBridge.ts`) | RocksDB |
|
|
193
|
+
|
|
194
|
+
Seven things that are easy to get wrong here:
|
|
195
|
+
|
|
196
|
+
- **The floor cannot be derived from the surviving log.** For four of the five paths the oldest
|
|
197
|
+
surviving entry would do, because they prune a database-wide time prefix. `Table.deleteHistory`
|
|
198
|
+
does not: it removes one table's entries out of a database-scoped log, so a sibling's entry
|
|
199
|
+
survives _below_ the newest entry it removed. Measured, LMDB: highest removed `…147.797`, oldest
|
|
200
|
+
surviving `…143.309` — a log-derived floor would have certified a cursor at `…145`.
|
|
201
|
+
- **The record's presence is the trust marker.** `Symbol.for('audit-floor')` is a different key from
|
|
202
|
+
`last-removed`, which is still live and still maintained by the LMDB retention loop (#2338 hardened
|
|
203
|
+
its write path and added tests for the retry-carry — do not remove it). They coexist because they
|
|
204
|
+
answer different questions: `last-removed` records where the LMDB loop got to, after the fact,
|
|
205
|
+
while the floor is written ahead of every one of the five prune paths and its commit is verified.
|
|
206
|
+
A value found under `last-removed` therefore cannot be told apart from one carrying those
|
|
207
|
+
guarantees, which is why the floor needs its own key rather than reusing it.
|
|
208
|
+
- **A store with no floor record is a store whose retention history we cannot account for.** That
|
|
209
|
+
includes the empty audit store an LMDB→RocksDB migration leaves behind, since `bin/copyDb.ts`
|
|
210
|
+
deliberately does not migrate it, and the audit-DBI-less result of a table-scoped backup taken
|
|
211
|
+
without `include_audit` — so `openAuditStore` stamps `max(Date.now(), newest retained key)` as a
|
|
212
|
+
one-time resync epoch. There is no permissive-baseline case: creating the audit DBI proves the
|
|
213
|
+
DBI was absent, not that the database is new.
|
|
214
|
+
- **That epoch is a guess, and it is recorded as one.** Its bound is surviving state, which cannot see
|
|
215
|
+
history a selective prune already removed: a legacy `deleteHistory` takes one table's entries out of
|
|
216
|
+
the shared log, so a table that held the newest entries can leave the newest _survivor_ older than
|
|
217
|
+
entries that are gone, and a clock rolled back between the two stamps a floor below them (#2458).
|
|
218
|
+
Refusing to stamp is worse — `AUDIT_FLOOR_UNKNOWN` is absorbing (`raiseAuditFloor` cannot lift it,
|
|
219
|
+
`establishAuditFloor` skips any existing record), so it would make every upgraded deployment fail
|
|
220
|
+
closed forever. So `establishAuditFloor` writes the epoch under `Symbol.for('audit-floor-bootstrap')`
|
|
221
|
+
first, then stamps the floor from what that record holds.
|
|
222
|
+
|
|
223
|
+
**The record's presence is the signal; comparing it against the floor is not.** A store carrying one
|
|
224
|
+
has an unverified pre-tracking window for as long as the record exists, however far the floor has
|
|
225
|
+
since moved — a prune raising the floor above the epoch certifies only what that prune removed, and
|
|
226
|
+
says nothing about history removed before tracking began, which may sit _above_ the epoch, since that
|
|
227
|
+
is precisely what the guess could not see. Worked example: a v4-era `deleteHistory` removes tableA up
|
|
228
|
+
to t=1000 while sibling tableB's newest survivor is 900; a rolled-back clock stamps bootstrap=900 and
|
|
229
|
+
floor=900; a later retention pass raises the floor to 950. A repair keyed on `floor > bootstrap` would
|
|
230
|
+
read 950 > 900, call it earned, and leave a consumer at cursor 970 certified over tableA's missing
|
|
231
|
+
950–1000. So the mark is retired by a database generation (#2451), never by a floor that climbed past
|
|
232
|
+
it; what the recorded _value_ is for is telling that repair how far the guess reached.
|
|
233
|
+
|
|
234
|
+
Two properties it does depend on. **Ordering:** the record is written first, so a crash between the
|
|
235
|
+
two writes leaves a record with no floor, which the next open retries because the early return tests
|
|
236
|
+
the _floor_. **Undecodable bytes are overwritten** rather than kept — unlike the floor, where a
|
|
237
|
+
present record may be a deliberate `AUDIT_FLOOR_UNKNOWN` and rewriting it would lower a floor.
|
|
238
|
+
Keeping torn bytes pinned the store to unknown _forever_: the resolver skipped the write because a
|
|
239
|
+
record existed, the read back failed identically on every later open, and no retry could succeed.
|
|
240
|
+
|
|
241
|
+
- **`getHistory` is not in the floor's time domain.** The floor is an audit-log key, which is what
|
|
242
|
+
`subscribe`'s events carry as `localTime`; `getHistory` reports each entry's origin `version` under
|
|
243
|
+
that same name, and a backdated or replicated write makes the two differ. A cursor saved from
|
|
244
|
+
`getHistory` cannot be compared against the floor.
|
|
245
|
+
- **On RocksDB the floor tracks the configured retention horizon, not retained reality.** Whole-log-file
|
|
246
|
+
purge granularity means the branch cannot know which entries a purge will drop, and the floor is
|
|
247
|
+
written first, so each pass advances it to `Date.now() - auditRetention/(1+priority²)` whether a
|
|
248
|
+
file was dropped or not. Entries below that horizon are often still on disk, and a cursor among
|
|
249
|
+
them is told to resync — conservative in the safe direction only. LMDB can see a single eligible
|
|
250
|
+
entry, so it raises off the first one it finds instead.
|
|
251
|
+
- **Untrustworthy metadata resolves to `Infinity`, not to a number.** A wrong-length record, or eight
|
|
252
|
+
bytes decoding to NaN/negative, must not become a floor: `cursor < NaN` is false, so a consumer
|
|
253
|
+
spelling the check that way would read corrupt metadata as safe.
|
|
254
|
+
- **A restore is outside what the floor can see.** `restore_backup` reinstalls the backup's floor
|
|
255
|
+
along with everything else, so a cursor from after the backup point reads as safe against it. The
|
|
256
|
+
audit floor is one of three carriers of resumable state a restore rolls back (record versions and
|
|
257
|
+
per-node `Symbol.for('seq')` records are the others), so this wants a database-level generation
|
|
258
|
+
rather than a fix in this one field — harper#2451.
|
|
259
|
+
|
|
107
260
|
---
|
|
108
261
|
|
|
109
262
|
## Path routing & parameterised routes
|
|
@@ -141,6 +294,20 @@ Tests: `../unitTests/resources/paramRoutes.test.js` (unit) and `../integrationTe
|
|
|
141
294
|
|
|
142
295
|
---
|
|
143
296
|
|
|
297
|
+
## Persisted relationship catalog
|
|
298
|
+
|
|
299
|
+
GraphQL `@relationship` attributes are live objects in component workers, but the operations API runs in a separate thread that does not load component schemas. `processGraphQLSchema` therefore records each relationship's target `database.table`, and `table()` persists a normalized, data-only relationship list on the table's primary catalog descriptor. The primary descriptor is deliberate: older Harper versions ignore the unknown field instead of loading a per-attribute row without the runtime table definition and silently returning `null`.
|
|
300
|
+
|
|
301
|
+
`getDatabases()` waits until the complete table catalog is loaded, then hydrates catalog-owned relationship attributes with a stable target-class snapshot and calls `updatedAttributes()` to rebuild resolvers. The list is authoritative only when the GraphQL authoring path explicitly supplies `schemaRelationshipsDefined`; admin and replication callers that omit it cannot erase component-owned metadata. An empty list removes catalog-owned relationships. Live schema relationships and same-name runtime attributes always win, and `@enumerable` is not persisted, so operations queries traverse relationships only when explicitly selected.
|
|
302
|
+
|
|
303
|
+
The primary-descriptor update shares the `update-attributes` serialization boundary with `dropTable()`, re-reads the row after locking, and refuses to replace a drop tombstone. Missing or malformed targets are skipped rather than installed without authorization metadata.
|
|
304
|
+
|
|
305
|
+
Only the GraphQL authoring path persists relationships. `defineTable()` resolves its relation targets through a lazy thunk so forward references and cycles work, and the target class is not resolvable at registration time — so code-first relationships remain worker-only, and the operations API still rejects them as unknown attributes. Tightening the operations API's object/nested `get_attributes` form to reject names it cannot resolve is NOT an option: `Table.transformEntryForSelect` projects undeclared JSON sub-objects through that same form, so `validation/searchValidator.ts` deliberately leaves it unchecked.
|
|
306
|
+
|
|
307
|
+
Tests: `../unitTests/resources/schemaMigrationFragility.test.js` (catalog round-trip and failure behavior) and `../integrationTests/apiTests/graphql.test.mjs` (operations API in both directions).
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
144
311
|
## Typed, discoverable resources (code-first schema + request contract)
|
|
145
312
|
|
|
146
313
|
Design record: the full RFC and its type-level design proofs live in the design PR (**HarperFast/harper#1503**); this section is the retained summary.
|