@abloatai/ablo 0.34.1 → 0.35.0
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/AGENTS.md +2 -1
- package/CHANGELOG.md +674 -5
- package/README.md +39 -22
- package/dist/BaseSyncedStore.d.ts +152 -44
- package/dist/BaseSyncedStore.js +300 -184
- package/dist/Database.d.ts +9 -24
- package/dist/Database.js +37 -22
- package/dist/InstanceCache.d.ts +25 -4
- package/dist/InstanceCache.js +48 -15
- package/dist/LazyReferenceCollection.d.ts +3 -3
- package/dist/LazyReferenceCollection.js +4 -4
- package/dist/Model.d.ts +6 -6
- package/dist/Model.js +10 -10
- package/dist/ModelRegistry.d.ts +4 -4
- package/dist/ModelRegistry.js +3 -3
- package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
- package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
- package/dist/SyncClient.d.ts +42 -32
- package/dist/SyncClient.js +166 -110
- package/dist/ai-sdk/coordinatedTool.d.ts +2 -2
- package/dist/ai-sdk/coordinatedTool.js +1 -1
- package/dist/ai-sdk/coordinationContext.d.ts +2 -2
- package/dist/ai-sdk/coordinationContext.js +1 -1
- package/dist/ai-sdk/wrap.d.ts +3 -3
- package/dist/ai-sdk/wrap.js +2 -2
- package/dist/auth/index.d.ts +1 -156
- package/dist/auth/index.js +8 -301
- package/dist/cli.cjs +3344 -1073
- package/dist/client/Ablo.d.ts +42 -287
- package/dist/client/Ablo.js +118 -963
- package/dist/client/abloClient.d.ts +309 -0
- package/dist/client/abloClient.js +13 -0
- package/dist/client/clientPrelude.d.ts +52 -0
- package/dist/client/clientPrelude.js +60 -0
- package/dist/client/consoleLogger.d.ts +2 -2
- package/dist/client/coreClient.d.ts +60 -0
- package/dist/client/coreClient.js +118 -0
- package/dist/client/createInternalComponents.d.ts +4 -4
- package/dist/client/createInternalComponents.js +9 -8
- package/dist/client/createModelProxy.d.ts +78 -373
- package/dist/client/createModelProxy.js +114 -86
- package/dist/client/humans.d.ts +48 -0
- package/dist/client/humans.js +52 -0
- package/dist/client/modelRegistration.d.ts +1 -1
- package/dist/client/modelRegistration.js +9 -9
- package/dist/client/options.d.ts +73 -17
- package/dist/client/reactiveEngine.d.ts +48 -0
- package/dist/client/reactiveEngine.js +910 -0
- package/dist/client/resourceTypes.d.ts +9 -250
- package/dist/client/resourceTypes.js +8 -5
- package/dist/client/schemaConfig.d.ts +4 -4
- package/dist/client/schemaConfig.js +6 -2
- package/dist/client/validateAbloOptions.d.ts +3 -2
- package/dist/client/validateAbloOptions.js +1 -1
- package/dist/client/wsMutationExecutor.d.ts +3 -3
- package/dist/client/wsMutationExecutor.js +3 -3
- package/dist/context.d.ts +9 -9
- package/dist/context.js +10 -9
- package/dist/coordination/ClaimLog.d.ts +26 -0
- package/dist/coordination/ClaimLog.js +32 -0
- package/dist/coordination/index.d.ts +1 -15
- package/dist/coordination/index.js +8 -31
- package/dist/core/DatabaseManager.js +1 -1
- package/dist/core/QueryView.d.ts +1 -1
- package/dist/core/QueryView.js +1 -1
- package/dist/core/StoreManager.d.ts +4 -23
- package/dist/core/StoreManager.js +5 -55
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +2 -2
- package/dist/core/storeContract.d.ts +2 -2
- package/dist/docs/catalog.d.ts +72 -0
- package/dist/docs/catalog.js +227 -0
- package/dist/docs/index.d.ts +10 -0
- package/dist/docs/index.js +10 -0
- package/dist/environment.d.ts +1 -40
- package/dist/environment.js +8 -37
- package/dist/index.d.ts +40 -34
- package/dist/index.js +26 -20
- package/dist/interfaces/index.d.ts +44 -134
- package/dist/keys/index.d.ts +1 -77
- package/dist/keys/index.js +8 -190
- package/dist/mutators/{RecordingTransaction.d.ts → RecordingMutation.d.ts} +4 -4
- package/dist/mutators/{RecordingTransaction.js → RecordingMutation.js} +2 -2
- package/dist/mutators/Transaction.d.ts +1 -1
- package/dist/mutators/Transaction.js +1 -1
- package/dist/mutators/UndoManager.d.ts +6 -6
- package/dist/mutators/UndoManager.js +5 -5
- package/dist/mutators/defineMutators.d.ts +3 -3
- package/dist/mutators/defineMutators.js +1 -1
- package/dist/mutators/inverseOp.js +2 -2
- package/dist/mutators/mutateActions.d.ts +3 -3
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +1 -1
- package/dist/mutators/undoApply.d.ts +1 -1
- package/dist/mutators/undoApply.js +1 -1
- package/dist/policy/index.d.ts +2 -2
- package/dist/policy/index.js +1 -1
- package/dist/query/client.d.ts +2 -2
- package/dist/query/client.js +4 -4
- package/dist/query/types.d.ts +6 -41
- package/dist/query/types.js +2 -2
- package/dist/react/AbloProvider.d.ts +6 -8
- package/dist/react/AbloProvider.js +5 -7
- package/dist/react/context.d.ts +1 -1
- package/dist/react/context.js +1 -1
- package/dist/react/index.d.ts +5 -5
- package/dist/react/index.js +3 -3
- package/dist/react/internalContext.d.ts +1 -1
- package/dist/react/useAblo.d.ts +3 -3
- package/dist/react/useAblo.js +1 -1
- package/dist/react/useCurrentUserId.js +1 -1
- package/dist/react/useErrorListener.js +1 -1
- package/dist/react/useMutationFailureListener.d.ts +2 -2
- package/dist/react/useMutationFailureListener.js +1 -1
- package/dist/react/useMutators.d.ts +3 -3
- package/dist/react/useMutators.js +3 -3
- package/dist/react/useUndoScope.d.ts +5 -5
- package/dist/react/useUndoScope.js +1 -1
- package/dist/schema/coordination.d.ts +69 -10
- package/dist/schema/coordination.js +86 -9
- package/dist/schema/ddl.js +2 -2
- package/dist/schema/diff.d.ts +1 -1
- package/dist/schema/generate.js +1 -1
- package/dist/schema/index.d.ts +10 -10
- package/dist/schema/index.js +18 -18
- package/dist/schema/queries.d.ts +27 -27
- package/dist/schema/queries.js +23 -23
- package/dist/schema/select.d.ts +3 -3
- package/dist/schema/select.js +3 -3
- package/dist/schema/serialize.d.ts +15 -6
- package/dist/schema/serialize.js +17 -3
- package/dist/schema/sugar.d.ts +6 -7
- package/dist/schema/sugar.js +9 -12
- package/dist/schema/syncDeltaRow.d.ts +4 -152
- package/dist/schema/syncDeltaRow.js +4 -105
- package/dist/server/adapter.d.ts +18 -1
- package/dist/server/commit.d.ts +10 -16
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +1 -1
- package/dist/source/adapters/drizzle.d.ts +1 -1
- package/dist/source/adapters/drizzle.js +2 -2
- package/dist/source/adapters/kysely.d.ts +1 -1
- package/dist/source/adapters/kysely.js +1 -1
- package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
- package/dist/source/adapters/kyselyMutationCore.js +2 -2
- package/dist/source/adapters/memory.js +1 -1
- package/dist/source/adapters/prisma.d.ts +8 -3
- package/dist/source/adapters/prisma.js +1 -1
- package/dist/source/connector.js +1 -1
- package/dist/source/connectorProtocol.d.ts +2 -8
- package/dist/source/connectorProtocol.js +3 -2
- package/dist/source/contract.d.ts +29 -17
- package/dist/source/contract.js +27 -22
- package/dist/source/factory.d.ts +1 -1
- package/dist/source/footprint.d.ts +111 -0
- package/dist/source/footprint.js +0 -0
- package/dist/source/idempotency.js +2 -2
- package/dist/source/index.d.ts +1 -0
- package/dist/source/index.js +3 -0
- package/dist/source/next.d.ts +1 -1
- package/dist/source/signing.d.ts +9 -2
- package/dist/source/signing.js +4 -1
- package/dist/source/types.d.ts +6 -4
- package/dist/source/types.js +1 -1
- package/dist/stores/ObjectStore.d.ts +1 -1
- package/dist/stores/SyncActionStore.d.ts +1 -1
- package/dist/stores/SyncActionStore.js +2 -10
- package/dist/stores/syncAction.d.ts +26 -0
- package/dist/stores/syncAction.js +16 -0
- package/dist/surface.d.ts +3 -3
- package/dist/surface.js +6 -4
- package/dist/sync/BootstrapFetcher.d.ts +123 -6
- package/dist/sync/BootstrapFetcher.js +492 -66
- package/dist/sync/ConnectionManager.d.ts +6 -198
- package/dist/sync/ConnectionManager.js +6 -677
- package/dist/sync/OnDemandLoader.d.ts +2 -2
- package/dist/sync/OnDemandLoader.js +60 -21
- package/dist/sync/SubscriptionManager.d.ts +13 -2
- package/dist/sync/SubscriptionManager.js +23 -5
- package/dist/sync/SyncWebSocket.d.ts +27 -510
- package/dist/sync/SyncWebSocket.js +76 -954
- package/dist/sync/awaitClaimGrant.d.ts +4 -44
- package/dist/sync/awaitClaimGrant.js +4 -109
- package/dist/sync/commitFrames.d.ts +6 -40
- package/dist/sync/commitFrames.js +6 -97
- package/dist/sync/contextPorts.d.ts +18 -0
- package/dist/sync/contextPorts.js +31 -0
- package/dist/sync/createClaimStream.d.ts +5 -49
- package/dist/sync/createClaimStream.js +5 -469
- package/dist/sync/createPresenceStream.d.ts +26 -4
- package/dist/sync/createPresenceStream.js +28 -20
- package/dist/sync/createSnapshot.d.ts +2 -2
- package/dist/sync/createSnapshot.js +1 -1
- package/dist/sync/credentialLifecycle.d.ts +5 -173
- package/dist/sync/credentialLifecycle.js +5 -320
- package/dist/sync/deltaPipeline.d.ts +1 -1
- package/dist/sync/participants.d.ts +5 -4
- package/dist/sync/participants.js +29 -22
- package/dist/sync/schemaDrift.d.ts +55 -0
- package/dist/sync/schemaDrift.js +53 -0
- package/dist/sync/schemas.d.ts +21 -32
- package/dist/sync/schemas.js +26 -17
- package/dist/sync/syncPlan.d.ts +3 -3
- package/dist/sync/wsFrameHandlers.d.ts +6 -114
- package/dist/sync/wsFrameHandlers.js +6 -392
- package/dist/testing/fixtures/bootstrap.d.ts +1 -1
- package/dist/testing/fixtures/deltas.d.ts +1 -1
- package/dist/testing/fixtures/httpResponses.d.ts +70 -0
- package/dist/testing/fixtures/httpResponses.js +90 -0
- package/dist/testing/fixtures/models.js +1 -1
- package/dist/testing/helpers/wait.js +1 -1
- package/dist/testing/mocks/MockMutationExecutor.d.ts +2 -2
- package/dist/testing/mocks/MockMutationExecutor.js +8 -14
- package/dist/testing/mocks/MockSyncContext.d.ts +11 -11
- package/dist/testing/mocks/MockSyncContext.js +10 -9
- package/dist/testing/mocks/MockSyncStore.js +1 -1
- package/dist/testing/mocks/MockWebSocket.d.ts +2 -2
- package/dist/transaction/ablo.d.ts +88 -0
- package/dist/transaction/ablo.js +33 -0
- package/dist/{client/auth.d.ts → transaction/auth/apiKey.d.ts} +43 -8
- package/dist/{client/auth.js → transaction/auth/apiKey.js} +19 -0
- package/dist/transaction/auth/bootstrapScope.d.ts +15 -0
- package/dist/transaction/auth/bootstrapScope.js +1 -0
- package/dist/transaction/auth/capability.d.ts +177 -0
- package/dist/transaction/auth/capability.js +199 -0
- package/dist/{auth → transaction/auth}/credentialSource.d.ts +8 -1
- package/dist/{client → transaction/auth}/identity.d.ts +8 -7
- package/dist/{client → transaction/auth}/identity.js +1 -1
- package/dist/transaction/auth/index.d.ts +162 -0
- package/dist/transaction/auth/index.js +304 -0
- package/dist/{auth → transaction/auth}/schemas.d.ts +1 -1
- package/dist/{auth → transaction/auth}/schemas.js +13 -13
- package/dist/{client → transaction/auth}/sessionMint.d.ts +8 -8
- package/dist/{client → transaction/auth}/sessionMint.js +4 -7
- package/dist/transaction/coordination/awaitClaimGrant.d.ts +49 -0
- package/dist/transaction/coordination/awaitClaimGrant.js +112 -0
- package/dist/transaction/coordination/claimMeta.d.ts +49 -0
- package/dist/transaction/coordination/claimMeta.js +52 -0
- package/dist/transaction/coordination/createClaimStream.d.ts +64 -0
- package/dist/transaction/coordination/createClaimStream.js +475 -0
- package/dist/transaction/coordination/events.d.ts +74 -0
- package/dist/transaction/coordination/events.js +7 -0
- package/dist/transaction/coordination/index.d.ts +19 -0
- package/dist/transaction/coordination/index.js +44 -0
- package/dist/transaction/coordination/locator.d.ts +83 -0
- package/dist/transaction/coordination/locator.js +82 -0
- package/dist/transaction/coordination/schema.d.ts +1473 -0
- package/dist/{coordination → transaction/coordination}/schema.js +490 -55
- package/dist/transaction/coordination/targetConflict.d.ts +2 -0
- package/dist/transaction/coordination/targetConflict.js +103 -0
- package/dist/{coordination → transaction/coordination}/trace.d.ts +7 -18
- package/dist/{coordination → transaction/coordination}/trace.js +18 -25
- package/dist/transaction/durableWrites.d.ts +62 -0
- package/dist/{client → transaction}/durableWrites.js +28 -3
- package/dist/transaction/environment.d.ts +105 -0
- package/dist/transaction/environment.js +108 -0
- package/dist/{errorCodes.d.ts → transaction/errorCodes.d.ts} +11 -11
- package/dist/{errorCodes.js → transaction/errorCodes.js} +35 -12
- package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
- package/dist/{errors.js → transaction/errors.js} +85 -16
- package/dist/transaction/index.d.ts +20 -0
- package/dist/transaction/index.js +20 -0
- package/dist/transaction/keys/index.d.ts +87 -0
- package/dist/transaction/keys/index.js +207 -0
- package/dist/transaction/log/syncDeltaRow.d.ts +158 -0
- package/dist/transaction/log/syncDeltaRow.js +95 -0
- package/dist/{sync/syncPosition.d.ts → transaction/logPosition.d.ts} +22 -8
- package/dist/{sync/syncPosition.js → transaction/logPosition.js} +15 -6
- package/dist/transaction/logger.d.ts +16 -0
- package/dist/transaction/logger.js +7 -0
- package/dist/transaction/observability.d.ts +53 -0
- package/dist/transaction/observability.js +19 -0
- package/dist/transaction/plugin.d.ts +192 -0
- package/dist/transaction/plugin.js +87 -0
- package/dist/{policy → transaction/policy}/types.d.ts +3 -3
- package/dist/{policy → transaction/policy}/types.js +2 -0
- package/dist/transaction/resources/httpResources.d.ts +266 -0
- package/dist/transaction/resources/httpResources.js +7 -0
- package/dist/transaction/resources/modelOperations.d.ts +319 -0
- package/dist/transaction/resources/modelOperations.js +12 -0
- package/dist/transaction/resources/mutationOptions.d.ts +66 -0
- package/dist/transaction/resources/mutationOptions.js +9 -0
- package/dist/transaction/resources/where.d.ts +85 -0
- package/dist/transaction/resources/where.js +70 -0
- package/dist/{client → transaction/resources}/writeOptionsSchema.d.ts +2 -6
- package/dist/{client → transaction/resources}/writeOptionsSchema.js +9 -5
- package/dist/{schema → transaction/schema}/field.d.ts +5 -5
- package/dist/{schema → transaction/schema}/field.js +5 -5
- package/dist/transaction/schema/loadStrategy.d.ts +45 -0
- package/dist/transaction/schema/loadStrategy.js +46 -0
- package/dist/{schema → transaction/schema}/model.d.ts +50 -35
- package/dist/{schema → transaction/schema}/model.js +30 -20
- package/dist/transaction/schema/openapi.d.ts +57 -0
- package/dist/transaction/schema/openapi.js +340 -0
- package/dist/{schema → transaction/schema}/relation.d.ts +14 -14
- package/dist/{schema → transaction/schema}/relation.js +7 -7
- package/dist/{schema → transaction/schema}/residency.d.ts +0 -9
- package/dist/{schema → transaction/schema}/residency.js +0 -5
- package/dist/{schema → transaction/schema}/roles.d.ts +5 -5
- package/dist/{schema → transaction/schema}/roles.js +5 -5
- package/dist/{schema → transaction/schema}/schema.d.ts +12 -10
- package/dist/{schema → transaction/schema}/schema.js +4 -3
- package/dist/{schema → transaction/schema}/tenancy.d.ts +1 -1
- package/dist/{schema → transaction/schema}/tenancy.js +7 -4
- package/dist/transaction/transactionLayer.d.ts +82 -0
- package/dist/transaction/transactionLayer.js +24 -0
- package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.d.ts +4 -5
- package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.js +9 -13
- package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.d.ts +9 -2
- package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.js +5 -9
- package/dist/{transactions/durableWriteStore.d.ts → transaction/transactions/settlement/pendingWrite.d.ts} +10 -36
- package/dist/transaction/transactions/settlement/pendingWrite.js +20 -0
- package/dist/transaction/transport/commitFrames.d.ts +90 -0
- package/dist/transaction/transport/commitFrames.js +134 -0
- package/dist/transaction/transport/connectionManager.d.ts +215 -0
- package/dist/transaction/transport/connectionManager.js +673 -0
- package/dist/transaction/transport/credentialLifecycle.d.ts +177 -0
- package/dist/transaction/transport/credentialLifecycle.js +324 -0
- package/dist/{sync → transaction/transport}/heartbeat.d.ts +3 -1
- package/dist/{sync → transaction/transport}/heartbeat.js +6 -4
- package/dist/{client → transaction/transport}/httpClient.d.ts +59 -16
- package/dist/{client → transaction/transport}/httpClient.js +5 -5
- package/dist/transaction/transport/httpOptions.d.ts +33 -0
- package/dist/transaction/transport/httpOptions.js +12 -0
- package/dist/{client → transaction/transport}/httpTransport.js +171 -85
- package/dist/{sync/NetworkProbe.d.ts → transaction/transport/networkProbe.d.ts} +7 -4
- package/dist/{sync/NetworkProbe.js → transaction/transport/networkProbe.js} +14 -13
- package/dist/transaction/transport/wsFrameHandlers.d.ts +128 -0
- package/dist/transaction/transport/wsFrameHandlers.js +429 -0
- package/dist/transaction/transport/wsTransport.d.ts +576 -0
- package/dist/transaction/transport/wsTransport.js +1017 -0
- package/dist/transaction/types/assertExact.d.ts +17 -0
- package/dist/transaction/types/assertExact.js +1 -0
- package/dist/{types → transaction/types}/global.d.ts +17 -2
- package/dist/{types → transaction/types}/global.js +2 -1
- package/dist/{types → transaction/types}/index.d.ts +14 -46
- package/dist/{types → transaction/types}/index.js +7 -16
- package/dist/{types → transaction/types}/streams.d.ts +63 -45
- package/dist/{utils → transaction/utils}/json.d.ts +18 -0
- package/dist/transaction/utils/json.js +276 -0
- package/dist/transaction/wire/accountResponses.d.ts +351 -0
- package/dist/transaction/wire/accountResponses.js +255 -0
- package/dist/transaction/wire/auth.d.ts +49 -0
- package/dist/transaction/wire/auth.js +57 -0
- package/dist/transaction/wire/claimEvent.d.ts +76 -0
- package/dist/transaction/wire/claimEvent.js +73 -0
- package/dist/transaction/wire/claims.d.ts +463 -0
- package/dist/transaction/wire/claims.js +229 -0
- package/dist/{wire → transaction/wire}/commit.d.ts +125 -193
- package/dist/{wire → transaction/wire}/commit.js +68 -47
- package/dist/{wire → transaction/wire}/delta.d.ts +66 -17
- package/dist/{wire → transaction/wire}/delta.js +37 -13
- package/dist/transaction/wire/errorEnvelope.d.ts +72 -0
- package/dist/{wire → transaction/wire}/errorEnvelope.js +36 -5
- package/dist/transaction/wire/feedCursor.d.ts +60 -0
- package/dist/transaction/wire/feedCursor.js +82 -0
- package/dist/transaction/wire/feedEvent.d.ts +177 -0
- package/dist/transaction/wire/feedEvent.js +39 -0
- package/dist/transaction/wire/frames.d.ts +194 -0
- package/dist/transaction/wire/frames.js +50 -0
- package/dist/transaction/wire/inboundFrames.d.ts +552 -0
- package/dist/transaction/wire/inboundFrames.js +116 -0
- package/dist/transaction/wire/index.d.ts +50 -0
- package/dist/transaction/wire/index.js +74 -0
- package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
- package/dist/transaction/wire/listEnvelope.js +42 -0
- package/dist/transaction/wire/modelResponses.d.ts +85 -0
- package/dist/transaction/wire/modelResponses.js +43 -0
- package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +79 -38
- package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +110 -59
- package/dist/transactions/{TransactionStore.d.ts → mutations/MutationStore.d.ts} +8 -8
- package/dist/transactions/{TransactionStore.js → mutations/MutationStore.js} +2 -2
- package/dist/transactions/{coalesceRules.d.ts → mutations/coalesceRules.d.ts} +10 -10
- package/dist/transactions/{coalesceRules.js → mutations/coalesceRules.js} +1 -1
- package/dist/transactions/mutations/commitLatency.d.ts +52 -0
- package/dist/transactions/mutations/commitLatency.js +130 -0
- package/dist/transactions/{commitOutboxStore.d.ts → mutations/commitOutboxStore.d.ts} +1 -5
- package/dist/transactions/{commitOutboxStore.js → mutations/commitOutboxStore.js} +1 -1
- package/dist/transactions/{commitPayload.d.ts → mutations/commitPayload.d.ts} +16 -15
- package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +12 -12
- package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +11 -11
- package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +7 -7
- package/dist/transactions/mutations/durableWriteStore.d.ts +14 -0
- package/dist/transactions/mutations/durableWriteStore.js +12 -0
- package/dist/transactions/{optimisticApply.d.ts → mutations/optimisticApply.d.ts} +7 -7
- package/dist/transactions/{replayValidation.d.ts → mutations/replayValidation.d.ts} +3 -3
- package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +4 -3
- package/dist/utils/mobxSetup.d.ts +1 -1
- package/dist/utils/mobxSetup.js +5 -2
- package/dist/webhooks/events.d.ts +2 -2
- package/dist/wire/index.d.ts +1 -34
- package/dist/wire/index.js +8 -49
- package/docs/agent-messaging.md +3 -3
- package/docs/agents.md +19 -12
- package/docs/api-keys.md +8 -4
- package/docs/api.md +22 -18
- package/docs/audit.md +2 -0
- package/docs/cli.md +31 -3
- package/docs/client-behavior.md +8 -6
- package/docs/concurrency-convention.md +30 -24
- package/docs/coordination.md +48 -38
- package/docs/data-sources.md +3 -1
- package/docs/debugging.md +5 -3
- package/docs/deployment.md +267 -0
- package/docs/examples/agent-human.md +49 -42
- package/docs/examples/ai-sdk-tool.md +69 -44
- package/docs/examples/existing-python-backend.md +8 -6
- package/docs/examples/nextjs.md +129 -47
- package/docs/examples/scoped-agent.md +45 -44
- package/docs/examples/server-agent.md +46 -26
- package/docs/groups.md +32 -29
- package/docs/guarantees.md +4 -2
- package/docs/how-it-works.md +9 -7
- package/docs/idempotency.md +126 -0
- package/docs/identity.md +58 -54
- package/docs/index.md +172 -86
- package/docs/integration-guide.md +17 -16
- package/docs/interaction-model.md +6 -4
- package/docs/mcp.md +41 -16
- package/docs/migration.md +63 -5
- package/docs/operating-on-your-database.md +3 -1
- package/docs/projects.md +2 -0
- package/docs/quickstart.md +22 -5
- package/docs/react.md +12 -10
- package/docs/schema-contract.md +5 -3
- package/docs/session-settings.md +108 -0
- package/docs/sessions.md +3 -1
- package/docs/webhooks.md +3 -1
- package/llms.txt +47 -17
- package/package.json +10 -8
- package/dist/agent/Agent.d.ts +0 -366
- package/dist/agent/Agent.js +0 -514
- package/dist/agent/index.d.ts +0 -115
- package/dist/agent/index.js +0 -128
- package/dist/agent/session.d.ts +0 -93
- package/dist/agent/session.js +0 -149
- package/dist/agent/types.d.ts +0 -68
- package/dist/agent/types.js +0 -9
- package/dist/client/durableWrites.d.ts +0 -21
- package/dist/coordination/schema.d.ts +0 -722
- package/dist/schema/openapi.d.ts +0 -29
- package/dist/schema/openapi.js +0 -124
- package/dist/transactions/durableWriteStore.js +0 -30
- package/dist/utils/json.js +0 -88
- package/dist/wire/errorEnvelope.d.ts +0 -55
- package/dist/wire/frames.d.ts +0 -197
- package/dist/wire/frames.js +0 -49
- package/dist/wire/listEnvelope.js +0 -18
- /package/dist/{client → transaction/auth}/credentialEndpoint.d.ts +0 -0
- /package/dist/{client → transaction/auth}/credentialEndpoint.js +0 -0
- /package/dist/{auth → transaction/auth}/credentialPolicy.d.ts +0 -0
- /package/dist/{auth → transaction/auth}/credentialPolicy.js +0 -0
- /package/dist/{auth → transaction/auth}/credentialSource.js +0 -0
- /package/dist/{client → transaction/auth}/hostedEndpoints.d.ts +0 -0
- /package/dist/{client → transaction/auth}/hostedEndpoints.js +0 -0
- /package/dist/{client → transaction/coordination}/claimHeartbeatLoop.d.ts +0 -0
- /package/dist/{client → transaction/coordination}/claimHeartbeatLoop.js +0 -0
- /package/dist/{client → transaction}/persistence.d.ts +0 -0
- /package/dist/{client → transaction}/persistence.js +0 -0
- /package/dist/{client → transaction/resources}/functionalUpdate.d.ts +0 -0
- /package/dist/{client → transaction/resources}/functionalUpdate.js +0 -0
- /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.d.ts +0 -0
- /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.js +0 -0
- /package/dist/{client → transaction/transport}/httpTransport.d.ts +0 -0
- /package/dist/{types → transaction/types}/modelData.d.ts +0 -0
- /package/dist/{types → transaction/types}/modelData.js +0 -0
- /package/dist/{types → transaction/types}/participant.d.ts +0 -0
- /package/dist/{types → transaction/types}/participant.js +0 -0
- /package/dist/{types → transaction/types}/streams.js +0 -0
- /package/dist/{utils → transaction/utils}/asyncIterator.d.ts +0 -0
- /package/dist/{utils → transaction/utils}/asyncIterator.js +0 -0
- /package/dist/{utils → transaction/utils}/duration.d.ts +0 -0
- /package/dist/{utils → transaction/utils}/duration.js +0 -0
- /package/dist/{wire → transaction/wire}/bootstrapReason.d.ts +0 -0
- /package/dist/{wire → transaction/wire}/bootstrapReason.js +0 -0
- /package/dist/{wire → transaction/wire}/protocol.d.ts +0 -0
- /package/dist/{wire → transaction/wire}/protocol.js +0 -0
- /package/dist/{wire → transaction/wire}/protocolVersion.d.ts +0 -0
- /package/dist/{wire → transaction/wire}/protocolVersion.js +0 -0
- /package/dist/transactions/{UnconfirmedWrites.d.ts → mutations/UnconfirmedWrites.d.ts} +0 -0
- /package/dist/transactions/{UnconfirmedWrites.js → mutations/UnconfirmedWrites.js} +0 -0
- /package/dist/transactions/{optimisticApply.js → mutations/optimisticApply.js} +0 -0
|
@@ -37,7 +37,7 @@ import { z } from 'zod';
|
|
|
37
37
|
* error documentation and returned on the `Ablo-Version` response header, so a
|
|
38
38
|
* consumer can detect when its expected contract has drifted from the server's.
|
|
39
39
|
*/
|
|
40
|
-
export const ERROR_CONTRACT_VERSION = '2026-07-
|
|
40
|
+
export const ERROR_CONTRACT_VERSION = '2026-07-21';
|
|
41
41
|
/**
|
|
42
42
|
* A closed classification of how a failure can be recovered from — a level above
|
|
43
43
|
* the raw {@link ErrorCode}. Where a code says what went wrong, a recovery class
|
|
@@ -136,6 +136,7 @@ export const ERROR_CODES = {
|
|
|
136
136
|
database_role_unreadable: wire('permission', 403, false, 'Ablo could not introspect the database role it connects with, so it cannot verify that row-level security is enforced.'),
|
|
137
137
|
database_tables_unforced_rls: wire('permission', 403, false, 'Some synced tables do not have `FORCE ROW LEVEL SECURITY` applied, so the table owner can bypass row isolation. Run `ALTER TABLE ... FORCE ROW LEVEL SECURITY` on each synced table.'),
|
|
138
138
|
database_host_not_allowed: wire('permission', 403, false, "The database host resolves to a private, loopback, or link-local address, which Ablo's servers will not connect to. Use a publicly resolvable host."),
|
|
139
|
+
connected_database_unreachable: wire('tenant', 503, false, 'Ablo could not reach the database connected to this environment: it refused the credentials on file, or did not answer at all. A database often changes after it is connected — a password is rotated, an instance is replaced — while the connection goes on pointing at what used to be there. The error names the host it tried. If the password changed, `ablo connect rotate` re-keys the roles and re-registers them; if the database itself was replaced, `ablo connect apply` sets up the new one and `ablo connect register` hands it over. Run either with a key for this environment.'),
|
|
139
140
|
// Older spellings of the `database_*` codes above, still sent by some servers
|
|
140
141
|
// and kept so they classify identically. Prefer the `database_*` codes.
|
|
141
142
|
byo_role_cannot_enforce_rls: wire('permission', 403, false, 'The direct Postgres connector role cannot enforce row-level security.'),
|
|
@@ -152,8 +153,21 @@ export const ERROR_CODES = {
|
|
|
152
153
|
claim_lost: wire('claim', 409, false, 'The claim held on this row was lost before the write could apply. Re-acquire the claim and retry.'),
|
|
153
154
|
fence_token_stale: wire('claim', 409, false, 'This write carried a fencing token below the row’s current high-water: a later holder claimed the row, wrote, and moved on while this claim was lapsed, so applying the write would silently overwrite their work. The claim is gone — re-claim the row and retry from the current state.'),
|
|
154
155
|
entity_claimed: wire('claim', 409, false, 'This row is currently claimed by another participant, so the write was blocked. Queue behind the holder with `ablo.<model>.claim`, or wait for the claim to clear.'),
|
|
155
|
-
|
|
156
|
+
// A claim payload that cannot be parsed is a malformed request, not
|
|
157
|
+
// contention — it is filed with `malformed_subscription` below rather than
|
|
158
|
+
// with the 409s above, so the claim category stays purely about a target
|
|
159
|
+
// being held. This is the code for a claim that fails to name its target,
|
|
160
|
+
// over either transport.
|
|
161
|
+
malformed_claim: wire('validation', 400, false, 'The claim payload could not be parsed. A claim must name the model and the entity it targets; check the payload shape and resend.'),
|
|
156
162
|
malformed_subscription: wire('validation', 400, false, 'The `update_subscription` payload was malformed; expected `{ syncGroups: string[] }`.'),
|
|
163
|
+
// The counterpart to the two above, pointing the other way: those are a
|
|
164
|
+
// client sending the server something it cannot read, this is the server
|
|
165
|
+
// sending the client something it cannot read. One code covers both
|
|
166
|
+
// transports — a mis-shaped socket frame and a mis-shaped HTTP body are the
|
|
167
|
+
// same failure, and the message says which arrived. Not retryable: it means
|
|
168
|
+
// the two sides are running different versions of the protocol, and waiting
|
|
169
|
+
// does not change that.
|
|
170
|
+
malformed_response: wire('transport', 502, false, 'The server sent a message this client could not read, so it was declined whole rather than applied in part. Nothing was changed locally. This normally means the client and the server are running different versions; upgrading the client resolves it.'),
|
|
157
171
|
model_claimed: wire('claim', 409, false, 'Another participant holds a claim on this row. Read `claim.state` to see who holds it, or queue behind them with a claim of your own.'),
|
|
158
172
|
model_claimed_timeout: wire('claim', 409, false, 'Another participant held a claim on this row and did not release it in time. Retry, or read `claim.state` to see who holds it.'),
|
|
159
173
|
model_claim_not_configured: client('claim', 'Claiming requires the collaboration runtime, which the standard Ablo({ schema, apiKey }) client wires up for every model automatically — there is no per-model claim configuration to add. This appears only when a model proxy is constructed directly without that runtime (an internal/advanced path).'),
|
|
@@ -176,6 +190,7 @@ export const ERROR_CODES = {
|
|
|
176
190
|
idempotency_key_too_long: wire('validation', 400, false, 'The supplied `Idempotency-Key` exceeds the maximum length. Use a shorter key — a UUID works well.'),
|
|
177
191
|
// ── validation (400 / 422) ─────────────────────────────────────────
|
|
178
192
|
write_options_invalid: client('validation', 'The write options (`idempotencyKey` / `label` / `wait` / `readAt` / `onStale` / `claim`) failed validation against the write-options schema.'),
|
|
193
|
+
write_payload_invalid: client('validation', 'A write payload contained a value that cannot be represented safely as JSON. Use plain objects, arrays, finite numbers, strings, booleans, null, or valid dates.'),
|
|
179
194
|
source_operation_id_required: client('validation', 'A data-source operation arrived without the entity `id` it targets.'),
|
|
180
195
|
source_adapter_misconfigured: client('validation', 'The data-source ORM adapter could not map a schema model onto the backing client — the client exposes no matching delegate or model. Check that the adapter and schema agree on model names.'),
|
|
181
196
|
// The server validates every incoming data-source event before appending it
|
|
@@ -186,7 +201,6 @@ export const ERROR_CODES = {
|
|
|
186
201
|
duration_invalid: client('validation', 'A duration value was not a number of seconds or a "500ms" | "30s" | "3m" | "24h" string.'),
|
|
187
202
|
schema_definition_invalid: client('validation', 'A schema definition value was invalid (bad column identifier, non-finite backfill, or unsupported schema-JSON version).'),
|
|
188
203
|
cli_invalid_arguments: client('validation', 'The CLI was invoked with an unknown flag or a malformed flag value.'),
|
|
189
|
-
turn_validation_failed: wire('validation', 422, false, 'The agent turn payload failed server-side validation and was not applied.'),
|
|
190
204
|
commit_operation_required: wire('validation', 400, false, 'A commit must carry `operation` or `operations`.'),
|
|
191
205
|
// Both commit transports — the WebSocket `commit` frame and the HTTP
|
|
192
206
|
// `/v1/commits` endpoint — validate every operation and reject the whole batch
|
|
@@ -251,10 +265,15 @@ export const ERROR_CODES = {
|
|
|
251
265
|
claim_wait_aborted: wire('claim', 409, true, 'The wait for this claim lease was aborted before the lease was granted.'),
|
|
252
266
|
claim_wait_poll_interval_required: client('claim', 'Waiting on a claim requires a poll interval, and none was provided.'),
|
|
253
267
|
grant_timeout: wire('claim', 504, true, 'The wait for a capability grant timed out before one arrived. Retry the request.'),
|
|
254
|
-
slide_intent_missing_deck_id: wire('claim', 400, false, 'This slide claim is missing the id of the deck it belongs to.'),
|
|
255
|
-
slide_intent_unknown_sibling: wire('claim', 400, false, 'This slide claim references a sibling slide that does not exist in the deck.'),
|
|
256
268
|
// ── bootstrap (transport) ──────────────────────────────────────────
|
|
257
269
|
bootstrap_fetch_timeout: wire('bootstrap', 504, true, 'The initial bootstrap fetch timed out before the server responded. Retry shortly.'),
|
|
270
|
+
// Deliberate cancellation, never a failure of the network. It is what the
|
|
271
|
+
// client hands to `abort()` so the layer above can tell "we stopped this on
|
|
272
|
+
// purpose" apart from "the transfer died" — the two are indistinguishable
|
|
273
|
+
// from a bare abort, and retrying the first re-issues requests that were just
|
|
274
|
+
// killed. Non-retryable by construction: whoever cancelled it either has a
|
|
275
|
+
// newer request in flight or has already given up.
|
|
276
|
+
bootstrap_cancelled: client('bootstrap', 'This bootstrap request was cancelled before it finished, because a newer one replaced it or the bootstrap it belonged to had already failed. It is not retried on its own.'),
|
|
258
277
|
bootstrap_offline: wire('bootstrap', 503, true, 'Bootstrap could not run because the client is offline. It can proceed once the network returns.'),
|
|
259
278
|
bootstrap_offline_no_cache: wire('bootstrap', 503, false, 'The client is offline and no cached snapshot is available to start from, so there is no data to load until the network returns.'),
|
|
260
279
|
bootstrap_response_invalid: wire('bootstrap', 502, true, 'The bootstrap response could not be parsed. Retrying may succeed.'),
|
|
@@ -294,8 +313,6 @@ export const ERROR_CODES = {
|
|
|
294
313
|
// fail closed, so the request was rejected rather than admitted unchecked. It
|
|
295
314
|
// is retryable: the next attempt re-probes the backend.
|
|
296
315
|
rate_limiter_unavailable: wire('server', 503, true, 'The rate-limiter backend is unavailable and this endpoint is configured to fail closed; retry shortly.'),
|
|
297
|
-
turn_open_failed: wire('server', 500, true, 'The agent turn could not be opened on the server. It is safe to retry.'),
|
|
298
|
-
turn_close_failed: wire('server', 500, true, 'The agent turn could not be closed cleanly on the server. It is safe to retry the close.'),
|
|
299
316
|
// ── client-only invariants (never serialized) ──────────────────────
|
|
300
317
|
invalid_options: client('client', 'The Ablo client was constructed with invalid or incomplete options.'),
|
|
301
318
|
no_ablo_provider: client('client', 'An Ablo hook was used outside of an Ablo provider.'),
|
|
@@ -345,12 +362,14 @@ export const ERROR_CODES = {
|
|
|
345
362
|
forbidden: wire('permission', 403, false, 'The caller lacks permission for this operation.'),
|
|
346
363
|
source_api_key_unresolved: wire('auth', 401, false, 'The API key presented for this data source could not be resolved to a known key. Check the key and its environment.'),
|
|
347
364
|
capability_auth_disabled: wire('server', 503, false, 'Capability authentication is disabled on this server.'),
|
|
365
|
+
capability_rotation_unavailable: wire('server', 500, false, 'This capability could not be rotated, because the environment it belongs to could not be read from it. It is unchanged and still works. Create a replacement capability and retire this one.'),
|
|
348
366
|
provisioner_unavailable: wire('server', 503, false, 'This deployment has no database provisioner configured, so tables cannot be created here.'),
|
|
349
367
|
invalid_model: wire('validation', 400, false, 'The model name in the request is not a valid model identifier.'),
|
|
350
368
|
invalid_id: wire('validation', 400, false, 'The id in the request is not a valid identifier.'),
|
|
351
369
|
unknown_model: wire('tenant', 400, false, 'Named a model the server does not know. Run `ablo push` (or keep `ablo dev` running) to upload `ablo/schema.ts` — the server keeps its own copy of the schema.'),
|
|
352
370
|
model_not_tenant_scoped: wire('tenant', 400, false, 'This model is not tenant-scoped, so it cannot be queried through the tenant-scoped read path.'),
|
|
353
371
|
source_tenancy_not_enforced: wire('tenant', 400, false, "This model is scoped by its connected data source (`policy: { by: 'source' }`), so its tenant is resolved from the source registration rather than a row column. Enforcing that resolution requires the write-through connect path, which is not enabled on this plane yet — so the model cannot be served through the tenant-scoped read or bootstrap path without risking a cross-tenant read. If this model lives on a log plane, scope it with `by: 'column'` or `by: 'parent'` instead."),
|
|
372
|
+
user_scope_not_enforced: wire('tenant', 400, false, "Rows in this model belong to one person rather than to the whole organization, and that boundary is kept where the rows are stored. This plane is currently served from its log, which carries the organization and the project on every row but not the owner — so the boundary cannot be applied here, and serving the read would show one member another member's private records. It was declined whole and nothing was returned. Serve the plane from its tables, or read with a credential that acts for the organization rather than for a person."),
|
|
354
373
|
model_not_provisioned: wire('tenant', 409, false, "This model is in the plane's registered schema, but its table has not been provisioned yet. Registering a schema with `ablo push` records the model; a plane's physical tables are created separately, out of band, so a model can appear in the schema before its table exists. Provision the plane's tables, then retry the read."),
|
|
355
374
|
schema_table_invalid: wire('schema', 500, false, "The model's table identifier is invalid."),
|
|
356
375
|
schema_scope_invalid: wire('schema', 500, false, "The model's scope predicate could not be built."),
|
|
@@ -367,6 +386,7 @@ export const ERROR_CODES = {
|
|
|
367
386
|
protocol_version_unsupported: wire('transport', 426, false, 'The client sync-protocol version is outside the range this server supports — upgrade the SDK (or the server was rolled back mid-fleet).'),
|
|
368
387
|
database_unreachable: wire('validation', 400, false, "Ablo could not reach this database to check that it can stream replication. The connection string may be wrong, the host may not be reachable from Ablo's servers, or the credentials may not be accepted."),
|
|
369
388
|
database_not_replication_ready: wire('validation', 400, false, 'This database is not set up for logical replication yet. Every failing item — wal_level, the publication, the replication grant, a replica identity — is listed in the error details with its exact fix. `ablo connect` prints the one-time setup; `ablo connect check` verifies it.'),
|
|
389
|
+
database_already_connected: wire('conflict', 409, false, 'This database is already connected to another environment in your organization. Ablo streams a database from one environment at a time, so connecting it to a second one would leave the two reading the same change stream, and the newer connection would take the stream over from the older. Give this environment a database of its own — on a branching provider a branch of the same database is the usual answer, and it is what sandbox is for. If you meant to move the connection rather than add one, disconnect it from the environment that holds it with `ablo connect deregister` first.'),
|
|
370
390
|
replication_publication_drift: wire('validation', 400, false, 'Your schema maps to tables that are not members of the replication publication, so their changes silently never stream and the source looks frozen. The missing tables and the exact `ALTER PUBLICATION … ADD TABLE …` to add them are in the error details — Ablo never alters your database for you.'),
|
|
371
391
|
query_unknown_relation: wire('validation', 400, false, 'The query references a relation the model does not define. Check the relation name against the schema.'),
|
|
372
392
|
query_relation_target_unknown: wire('schema', 500, false, 'A relation in the query targets a model the schema does not define.'),
|
|
@@ -384,16 +404,19 @@ export const ERROR_CODES = {
|
|
|
384
404
|
usage_invalid: wire('validation', 400, false, 'The usage request was invalid.'),
|
|
385
405
|
invalid_request: wire('validation', 400, false, 'The request parameters were invalid.'),
|
|
386
406
|
capability_not_found: wire('not_found', 404, false, 'No capability exists with the given id.'),
|
|
407
|
+
claim_not_found: wire('not_found', 404, false, 'No claim of yours exists with the given id. It was released, it expired, or it was never acquired on this plane.'),
|
|
387
408
|
invalid_participant_kind: wire('validation', 400, false, 'The participant kind is not one the server recognizes.'),
|
|
388
409
|
invalid_sync_group: wire('validation', 400, false, 'Sync groups must be `default` or `<namespace>:<id>`.'),
|
|
389
410
|
narrow_scope_required: wire('validation', 400, false, 'This request requires a scope narrowed to specific resources; the presented scope is too broad.'),
|
|
390
411
|
wide_scope_forbidden: wire('permission', 403, false, 'This caller may not use a wide scope. Request a scope narrowed to the resources you need.'),
|
|
391
412
|
capability_required: wire('auth', 401, false, 'This operation requires a capability, and none was presented.'),
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
413
|
+
// A row in an ordered collection can be created at a position stated relative
|
|
414
|
+
// to its neighbours ("before this one"), so the position has to be resolved
|
|
415
|
+
// against the parent before the row lands. These are the two ways that request
|
|
416
|
+
// can fail to describe a real place: no parent to resolve against, and a
|
|
417
|
+
// neighbour that is not in it.
|
|
418
|
+
position_missing_parent: wire('validation', 400, false, 'This row gives a position but not the parent it belongs to, so the position cannot be resolved. Send the parent id alongside the position.'),
|
|
419
|
+
position_unknown_sibling: wire('validation', 400, false, 'This row is positioned relative to another row that is not in the same parent. Check that the neighbouring row id is correct and still present.'),
|
|
397
420
|
schema_too_large: wire('validation', 413, false, 'The submitted schema exceeds the maximum size.'),
|
|
398
421
|
request_too_large: wire('validation', 413, false, 'The request body exceeds the maximum size.'),
|
|
399
422
|
invalid_schema: wire('validation', 400, false, 'The submitted schema could not be parsed.'),
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Both work on every subclass.
|
|
16
16
|
*/
|
|
17
|
+
import { z } from 'zod';
|
|
17
18
|
import type { ErrorCode } from './errorCodes.js';
|
|
18
19
|
import { type WireClaimSummary, type ModelClaim, type ModelTarget, type ParticipantKind } from './coordination/schema.js';
|
|
19
20
|
export type { ErrorCode, WireErrorCode, ErrorCategory, ErrorCodeSpec, RecoveryClass } from './errorCodes.js';
|
|
@@ -274,7 +275,7 @@ export declare function claimedError(target: {
|
|
|
274
275
|
* narrow an existing capability into, one that would pass on retry.
|
|
275
276
|
*/
|
|
276
277
|
export interface RequiredCapability {
|
|
277
|
-
/** The operation or capability scope, for example `"
|
|
278
|
+
/** The operation or capability scope, for example `"report.update"` or
|
|
278
279
|
* `"subscribe"`. */
|
|
279
280
|
readonly scope: string;
|
|
280
281
|
/** The concrete constraints the capability must satisfy — for example
|
|
@@ -314,19 +315,19 @@ export declare class CapabilityError extends AbloPermissionError {
|
|
|
314
315
|
* user should be sent to sign in again rather than offered a generic retry.
|
|
315
316
|
*
|
|
316
317
|
* It extends {@link AbloAuthenticationError}, so it is caught both by code using
|
|
317
|
-
* the {@link
|
|
318
|
+
* the {@link AbloSessionError.isSessionError} check and by code that catches the
|
|
318
319
|
* authentication category in general.
|
|
319
320
|
*/
|
|
320
|
-
export declare class
|
|
321
|
+
export declare class AbloSessionError extends AbloAuthenticationError {
|
|
321
322
|
readonly isSessionError = true;
|
|
322
323
|
readonly statusCode: number;
|
|
323
324
|
constructor(message: string, statusCode?: number);
|
|
324
325
|
/**
|
|
325
|
-
* Returns true when a value is a {@link
|
|
326
|
+
* Returns true when a value is a {@link AbloSessionError}, or any error-like
|
|
326
327
|
* object that reports itself as a session error through an `isSessionError`
|
|
327
328
|
* flag.
|
|
328
329
|
*/
|
|
329
|
-
static isSessionError(error: unknown): error is
|
|
330
|
+
static isSessionError(error: unknown): error is AbloSessionError;
|
|
330
331
|
/**
|
|
331
332
|
* Determines whether an HTTP response means the login session has expired and
|
|
332
333
|
* the user should sign in again. When the body carries a structured Ablo error
|
|
@@ -336,7 +337,17 @@ export declare class SyncSessionError extends AbloAuthenticationError {
|
|
|
336
337
|
static isSessionErrorResponse(status: number, body?: string): boolean;
|
|
337
338
|
}
|
|
338
339
|
/**
|
|
339
|
-
*
|
|
340
|
+
* @deprecated Renamed to {@link AbloSessionError} — the one engine-named class
|
|
341
|
+
* in the Ablo* hierarchy, brought in line with the family. Same class, same
|
|
342
|
+
* `instanceof` identity. Removed in 0.36.0.
|
|
343
|
+
*/
|
|
344
|
+
export declare const SyncSessionError: typeof AbloSessionError;
|
|
345
|
+
/**
|
|
346
|
+
* @deprecated Renamed to {@link AbloSessionError}. Removed in 0.36.0.
|
|
347
|
+
*/
|
|
348
|
+
export type SyncSessionError = AbloSessionError;
|
|
349
|
+
/**
|
|
350
|
+
* The WebSocket-close counterpart to {@link AbloSessionError.isSessionErrorResponse}:
|
|
340
351
|
* returns true for close reasons that mean the short-lived access credential
|
|
341
352
|
* (`ek_` or `rk_`) has expired. The server closes such sockets with code 4001
|
|
342
353
|
* and reason `'credential_expired'`. Because the credential is re-mintable from
|
|
@@ -345,6 +356,24 @@ export declare class SyncSessionError extends AbloAuthenticationError {
|
|
|
345
356
|
* reason, such as a revoked key or a genuinely lost login, stays terminal.
|
|
346
357
|
*/
|
|
347
358
|
export declare function isAccessCredentialExpiryCloseReason(reason: string): boolean;
|
|
359
|
+
/**
|
|
360
|
+
* The one definition of the {@link RequiredCapability} wire shape. Every
|
|
361
|
+
* boundary that carries a denial's capability detail — the error body parsed
|
|
362
|
+
* here, and the rejected commit receipt in `wire/commit.ts` — composes this
|
|
363
|
+
* schema rather than restating the fields, so a new member cannot reach one
|
|
364
|
+
* boundary and miss the other.
|
|
365
|
+
*
|
|
366
|
+
* Unknown keys pass through: the server may describe a capability in more
|
|
367
|
+
* detail than this build knows, and dropping those keys would leave a caller
|
|
368
|
+
* unable to act on a denial it could otherwise satisfy.
|
|
369
|
+
*/
|
|
370
|
+
export declare const requiredCapabilityWireSchema: z.ZodObject<{
|
|
371
|
+
scope: z.ZodString;
|
|
372
|
+
constraints: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodString]>>>;
|
|
373
|
+
issuer: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
|
|
374
|
+
ttlSeconds: z.ZodPreprocess<z.ZodOptional<z.ZodNumber>>;
|
|
375
|
+
nonce: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
|
|
376
|
+
}, z.core.$loose>;
|
|
348
377
|
/**
|
|
349
378
|
* Coerces any thrown value into an {@link AbloError}, so a consumer never catches
|
|
350
379
|
* an untyped error from the SDK. An error that is already an {@link AbloError}
|
|
@@ -377,14 +406,9 @@ export declare function errorFromWire(message: string, opts?: {
|
|
|
377
406
|
requestId?: string;
|
|
378
407
|
requiredCapability?: RequiredCapability;
|
|
379
408
|
claims?: readonly ClaimErrorClaim[];
|
|
409
|
+
/** Everything the producer attached beyond the envelope's own fields. */
|
|
410
|
+
details?: Readonly<Record<string, unknown>>;
|
|
380
411
|
}): AbloError;
|
|
381
|
-
/**
|
|
382
|
-
* Translates an HTTP response into the appropriate typed {@link AbloError}. This
|
|
383
|
-
* is the single mapping every request path routes a non-2xx response through, so
|
|
384
|
-
* the error a consumer sees is always the right subclass. After extracting the
|
|
385
|
-
* code and message from the response body, it delegates the class selection to
|
|
386
|
-
* {@link errorFromWire}, the same logic the frame transports use.
|
|
387
|
-
*/
|
|
388
412
|
export declare function translateHttpError(status: number, body: unknown, requestId?: string): AbloError;
|
|
389
413
|
/**
|
|
390
414
|
* Reports whether an HTTP error body carries a code that {@link translateHttpError}
|
|
@@ -335,27 +335,27 @@ export class CapabilityError extends AbloPermissionError {
|
|
|
335
335
|
* user should be sent to sign in again rather than offered a generic retry.
|
|
336
336
|
*
|
|
337
337
|
* It extends {@link AbloAuthenticationError}, so it is caught both by code using
|
|
338
|
-
* the {@link
|
|
338
|
+
* the {@link AbloSessionError.isSessionError} check and by code that catches the
|
|
339
339
|
* authentication category in general.
|
|
340
340
|
*/
|
|
341
|
-
export class
|
|
341
|
+
export class AbloSessionError extends AbloAuthenticationError {
|
|
342
342
|
isSessionError = true;
|
|
343
343
|
statusCode;
|
|
344
344
|
constructor(message, statusCode = 401) {
|
|
345
345
|
super(message, { httpStatus: statusCode, code: 'session_expired' });
|
|
346
|
-
this.name = '
|
|
346
|
+
this.name = 'AbloSessionError';
|
|
347
347
|
this.statusCode = statusCode;
|
|
348
348
|
if (Error.captureStackTrace) {
|
|
349
|
-
Error.captureStackTrace(this,
|
|
349
|
+
Error.captureStackTrace(this, AbloSessionError);
|
|
350
350
|
}
|
|
351
351
|
}
|
|
352
352
|
/**
|
|
353
|
-
* Returns true when a value is a {@link
|
|
353
|
+
* Returns true when a value is a {@link AbloSessionError}, or any error-like
|
|
354
354
|
* object that reports itself as a session error through an `isSessionError`
|
|
355
355
|
* flag.
|
|
356
356
|
*/
|
|
357
357
|
static isSessionError(error) {
|
|
358
|
-
if (error instanceof
|
|
358
|
+
if (error instanceof AbloSessionError) {
|
|
359
359
|
return true;
|
|
360
360
|
}
|
|
361
361
|
if (error && typeof error === 'object' && 'isSessionError' in error) {
|
|
@@ -392,7 +392,13 @@ export class SyncSessionError extends AbloAuthenticationError {
|
|
|
392
392
|
}
|
|
393
393
|
}
|
|
394
394
|
/**
|
|
395
|
-
*
|
|
395
|
+
* @deprecated Renamed to {@link AbloSessionError} — the one engine-named class
|
|
396
|
+
* in the Ablo* hierarchy, brought in line with the family. Same class, same
|
|
397
|
+
* `instanceof` identity. Removed in 0.36.0.
|
|
398
|
+
*/
|
|
399
|
+
export const SyncSessionError = AbloSessionError;
|
|
400
|
+
/**
|
|
401
|
+
* The WebSocket-close counterpart to {@link AbloSessionError.isSessionErrorResponse}:
|
|
396
402
|
* returns true for close reasons that mean the short-lived access credential
|
|
397
403
|
* (`ek_` or `rk_`) has expired. The server closes such sockets with code 4001
|
|
398
404
|
* and reason `'credential_expired'`. Because the credential is re-mintable from
|
|
@@ -405,7 +411,18 @@ export function isAccessCredentialExpiryCloseReason(reason) {
|
|
|
405
411
|
}
|
|
406
412
|
// ── HTTP → class mapping ──────────────────────────────────────────────
|
|
407
413
|
const OptionalWireStringSchema = z.preprocess((value) => (typeof value === 'string' ? value : undefined), z.string().optional());
|
|
408
|
-
|
|
414
|
+
/**
|
|
415
|
+
* The one definition of the {@link RequiredCapability} wire shape. Every
|
|
416
|
+
* boundary that carries a denial's capability detail — the error body parsed
|
|
417
|
+
* here, and the rejected commit receipt in `wire/commit.ts` — composes this
|
|
418
|
+
* schema rather than restating the fields, so a new member cannot reach one
|
|
419
|
+
* boundary and miss the other.
|
|
420
|
+
*
|
|
421
|
+
* Unknown keys pass through: the server may describe a capability in more
|
|
422
|
+
* detail than this build knows, and dropping those keys would leave a caller
|
|
423
|
+
* unable to act on a denial it could otherwise satisfy.
|
|
424
|
+
*/
|
|
425
|
+
export const requiredCapabilityWireSchema = z
|
|
409
426
|
.object({
|
|
410
427
|
scope: z.string(),
|
|
411
428
|
constraints: z
|
|
@@ -416,19 +433,19 @@ const RequiredCapabilityWireSchema = z
|
|
|
416
433
|
.preprocess((value) => (typeof value === 'number' ? value : undefined), z.number().optional()),
|
|
417
434
|
nonce: OptionalWireStringSchema,
|
|
418
435
|
})
|
|
419
|
-
.
|
|
436
|
+
.loose();
|
|
420
437
|
const NestedErrorShapeSchema = z
|
|
421
438
|
.object({
|
|
422
439
|
code: OptionalWireStringSchema,
|
|
423
440
|
message: OptionalWireStringSchema,
|
|
424
441
|
field: OptionalWireStringSchema,
|
|
425
|
-
requiredCapability:
|
|
442
|
+
requiredCapability: requiredCapabilityWireSchema.optional().catch(undefined),
|
|
426
443
|
heldBy: OptionalWireStringSchema,
|
|
427
444
|
policyReason: OptionalWireStringSchema,
|
|
428
445
|
heldByClaim: wireClaimSummarySchema.optional().catch(undefined),
|
|
429
446
|
claims: z.array(wireClaimSummarySchema).optional().catch(undefined),
|
|
430
447
|
})
|
|
431
|
-
.
|
|
448
|
+
.loose();
|
|
432
449
|
const ErrorFieldSchema = z
|
|
433
450
|
.preprocess((value) => typeof value === 'string' || (typeof value === 'object' && value !== null)
|
|
434
451
|
? value
|
|
@@ -442,13 +459,13 @@ const ErrorBodyShapeSchema = z
|
|
|
442
459
|
code: OptionalWireStringSchema,
|
|
443
460
|
reason: OptionalWireStringSchema,
|
|
444
461
|
message: OptionalWireStringSchema,
|
|
445
|
-
requiredCapability:
|
|
462
|
+
requiredCapability: requiredCapabilityWireSchema.optional().catch(undefined),
|
|
446
463
|
heldBy: OptionalWireStringSchema,
|
|
447
464
|
policyReason: OptionalWireStringSchema,
|
|
448
465
|
heldByClaim: wireClaimSummarySchema.optional().catch(undefined),
|
|
449
466
|
claims: z.array(wireClaimSummarySchema).optional().catch(undefined),
|
|
450
467
|
})
|
|
451
|
-
.
|
|
468
|
+
.loose();
|
|
452
469
|
function parseErrorBodyShape(body) {
|
|
453
470
|
if (typeof body !== 'object' || body === null)
|
|
454
471
|
return {};
|
|
@@ -489,7 +506,7 @@ export function toAbloError(err) {
|
|
|
489
506
|
* subclass, with its `code`, status, and retryability intact.
|
|
490
507
|
*/
|
|
491
508
|
export function errorFromWire(message, opts = {}) {
|
|
492
|
-
const { code, requestId, requiredCapability, claims } = opts;
|
|
509
|
+
const { code, requestId, requiredCapability, claims, details } = opts;
|
|
493
510
|
// Effective status: an explicit HTTP status wins; otherwise fall back to
|
|
494
511
|
// the code's canonical status from the registry (undefined for unknown /
|
|
495
512
|
// forward-compat codes, which then map to the base AbloError).
|
|
@@ -498,7 +515,12 @@ export function errorFromWire(message, opts = {}) {
|
|
|
498
515
|
// may send a code this SDK predates). Cast to ErrorCode here — the one
|
|
499
516
|
// sanctioned crossing — so internal producers stay statically checked.
|
|
500
517
|
const publicCode = (code === 'claim_conflict' ? 'claim_conflict' : code);
|
|
501
|
-
const baseOpts = {
|
|
518
|
+
const baseOpts = {
|
|
519
|
+
code: publicCode,
|
|
520
|
+
httpStatus,
|
|
521
|
+
requestId,
|
|
522
|
+
...(details && Object.keys(details).length > 0 ? { details } : {}),
|
|
523
|
+
};
|
|
502
524
|
// ── Code-first specials (transport-independent) ──────────────────────
|
|
503
525
|
// A scoped credential was denied — route through CapabilityError so callers
|
|
504
526
|
// can read `.requiredCapability` to attenuate-and-retry.
|
|
@@ -519,6 +541,14 @@ export function errorFromWire(message, opts = {}) {
|
|
|
519
541
|
if (code === 'stale_context') {
|
|
520
542
|
return new AbloStaleContextError(message, baseOpts);
|
|
521
543
|
}
|
|
544
|
+
// The database connected to the caller's environment could not be reached.
|
|
545
|
+
// It rides a 503, but the generic 5xx rule below would rebuild it as an
|
|
546
|
+
// `AbloServerError` — telling the reader Ablo is broken and to wait, when the
|
|
547
|
+
// remedy is on their side and the server already classified it as a
|
|
548
|
+
// connection failure. Keep the class the producer chose.
|
|
549
|
+
if (code === 'connected_database_unreachable') {
|
|
550
|
+
return new AbloConnectionError(message, baseOpts);
|
|
551
|
+
}
|
|
522
552
|
// ── Status-driven dispatch (HTTP parity) ─────────────────────────────
|
|
523
553
|
if (httpStatus === 401)
|
|
524
554
|
return new AbloAuthenticationError(message, baseOpts);
|
|
@@ -541,6 +571,38 @@ export function errorFromWire(message, opts = {}) {
|
|
|
541
571
|
* code and message from the response body, it delegates the class selection to
|
|
542
572
|
* {@link errorFromWire}, the same logic the frame transports use.
|
|
543
573
|
*/
|
|
574
|
+
/**
|
|
575
|
+
* The keys the error envelope spends on itself. {@link AbloError.toJSON} spreads
|
|
576
|
+
* `details` FLAT alongside them rather than nesting it, so everything here is
|
|
577
|
+
* the envelope and everything else was `details` — which is how
|
|
578
|
+
* {@link translateHttpError} puts it back.
|
|
579
|
+
*/
|
|
580
|
+
const ENVELOPE_KEYS = new Set([
|
|
581
|
+
'type',
|
|
582
|
+
'code',
|
|
583
|
+
'param',
|
|
584
|
+
'message',
|
|
585
|
+
'doc_url',
|
|
586
|
+
'request_id',
|
|
587
|
+
// Read into typed properties below, so they are not detail as well.
|
|
588
|
+
'error',
|
|
589
|
+
'reason',
|
|
590
|
+
'requiredCapability',
|
|
591
|
+
'claims',
|
|
592
|
+
'heldByClaim',
|
|
593
|
+
]);
|
|
594
|
+
/** The non-envelope remainder of an error body — what `details` was before it
|
|
595
|
+
* was spread. Empty when the producer attached nothing. */
|
|
596
|
+
function detailsFromBody(body) {
|
|
597
|
+
if (typeof body !== 'object' || body === null)
|
|
598
|
+
return undefined;
|
|
599
|
+
const rest = {};
|
|
600
|
+
for (const [key, value] of Object.entries(body)) {
|
|
601
|
+
if (!ENVELOPE_KEYS.has(key))
|
|
602
|
+
rest[key] = value;
|
|
603
|
+
}
|
|
604
|
+
return Object.keys(rest).length > 0 ? rest : undefined;
|
|
605
|
+
}
|
|
544
606
|
export function translateHttpError(status, body, requestId) {
|
|
545
607
|
const parsed = parseErrorBodyShape(body);
|
|
546
608
|
const nested = parsed.error != null && typeof parsed.error === 'object'
|
|
@@ -561,12 +623,19 @@ export function translateHttpError(status, body, requestId) {
|
|
|
561
623
|
: nested?.heldByClaim
|
|
562
624
|
? [nested.heldByClaim]
|
|
563
625
|
: undefined);
|
|
626
|
+
// The envelope carries `request_id`, so a caller that has only the body still
|
|
627
|
+
// gets the correlation id — without this it was dropped unless the caller
|
|
628
|
+
// happened to read the header and pass it in separately.
|
|
629
|
+
const bodyRequestId = typeof body === 'object' && body !== null && 'request_id' in body
|
|
630
|
+
? body.request_id
|
|
631
|
+
: undefined;
|
|
564
632
|
return errorFromWire(message, {
|
|
565
633
|
code,
|
|
566
634
|
httpStatus: status,
|
|
567
|
-
requestId,
|
|
635
|
+
requestId: requestId ?? (typeof bodyRequestId === 'string' ? bodyRequestId : undefined),
|
|
568
636
|
requiredCapability,
|
|
569
637
|
claims,
|
|
638
|
+
details: detailsFromBody(body),
|
|
570
639
|
});
|
|
571
640
|
}
|
|
572
641
|
/**
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Ablo settlement core (ADR 0013).
|
|
3
|
+
*
|
|
4
|
+
* The transaction layer that the reactive client is a consumer of, not the
|
|
5
|
+
* other way round. The root barrel is deliberate: it exports the seam —
|
|
6
|
+
* {@link TransactionLayer} — plus exactly the vocabulary its signatures
|
|
7
|
+
* reference and the error hierarchy callers catch. Everything else stays on
|
|
8
|
+
* subpaths; every addition here is a decision
|
|
9
|
+
* (docs/plans/transaction-layer-barrel-design.md).
|
|
10
|
+
*/
|
|
11
|
+
export type { TransactionLayer, ListQuery, CommitReceipt } from './transactionLayer.js';
|
|
12
|
+
export { Ablo } from './ablo.js';
|
|
13
|
+
export type { AbloHttpClient, AbloHttpClientOptions, HttpModelClient, } from './transport/httpClient.js';
|
|
14
|
+
export type { Delta, HeldClaim, HeldLease, ClaimTarget, ClaimLeaseOptions, } from './types/streams.js';
|
|
15
|
+
export type { ModelData } from './types/modelData.js';
|
|
16
|
+
export { LogPosition, logPositionSchema, parseLogPosition } from './logPosition.js';
|
|
17
|
+
export type { LogPositionSnapshot } from './logPosition.js';
|
|
18
|
+
export { AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloNotFoundError, AbloServerError, AbloStaleContextError, AbloContentionError, AbloClaimedError, AbloSessionError, toAbloError, } from './errors.js';
|
|
19
|
+
export * from './errorCodes.js';
|
|
20
|
+
export * from './environment.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Ablo settlement core (ADR 0013).
|
|
3
|
+
*
|
|
4
|
+
* The transaction layer that the reactive client is a consumer of, not the
|
|
5
|
+
* other way round. The root barrel is deliberate: it exports the seam —
|
|
6
|
+
* {@link TransactionLayer} — plus exactly the vocabulary its signatures
|
|
7
|
+
* reference and the error hierarchy callers catch. Everything else stays on
|
|
8
|
+
* subpaths; every addition here is a decision
|
|
9
|
+
* (docs/plans/transaction-layer-barrel-design.md).
|
|
10
|
+
*/
|
|
11
|
+
// The client entry point (ADR 0016). The bare import constructs the
|
|
12
|
+
// coordination layer over request/response transport; the reactive
|
|
13
|
+
// materialiser is the consumer package's entry point, layered above it.
|
|
14
|
+
export { Ablo } from './ablo.js';
|
|
15
|
+
export { LogPosition, logPositionSchema, parseLogPosition } from './logPosition.js';
|
|
16
|
+
// The error hierarchy callers catch.
|
|
17
|
+
export { AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloNotFoundError, AbloServerError, AbloStaleContextError, AbloContentionError, AbloClaimedError, AbloSessionError, toAbloError, } from './errors.js';
|
|
18
|
+
// Pre-seam leaf surfaces, kept for compatibility with the first extraction.
|
|
19
|
+
export * from './errorCodes.js';
|
|
20
|
+
export * from './environment.js';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Ablo API-key format: how keys are minted, hashed, and validated, in one
|
|
3
|
+
* place so every component that issues or checks a key agrees on the format.
|
|
4
|
+
*
|
|
5
|
+
* This module uses `node:crypto` and is therefore Node-only. It is published on
|
|
6
|
+
* the `@abloatai/ablo/keys` subpath and kept off the main browser-facing entry
|
|
7
|
+
* so a browser bundle never pulls in `node:crypto`.
|
|
8
|
+
*
|
|
9
|
+
* A key looks like `<sk|rk|ek|pk>_<live|test>_<30 base62 chars><6-char base62
|
|
10
|
+
* CRC32 checksum>`. The middle segment is the stable environment prefix, mapped
|
|
11
|
+
* on parse to `production` or `sandbox`. The recognizable prefix lets secret
|
|
12
|
+
* scanners spot a leaked key, and the trailing checksum lets the format reject a
|
|
13
|
+
* mistyped or forged key locally, without a database round-trip. Older keys
|
|
14
|
+
* (roughly a 43-character base64url body with no checksum) still validate by hash
|
|
15
|
+
* and parse here with `checksummed: false`.
|
|
16
|
+
*/
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
import { type KeyEnvironment } from '../environment.js';
|
|
19
|
+
export declare const API_KEY_KINDS: readonly ["secret", "restricted", "ephemeral", "publishable"];
|
|
20
|
+
export type ApiKeyKind = (typeof API_KEY_KINDS)[number];
|
|
21
|
+
export declare const API_KEY_ENVS: readonly ["production", "sandbox"];
|
|
22
|
+
export type ApiKeyEnv = KeyEnvironment;
|
|
23
|
+
/** A structurally-valid Ablo API key, parsed into its parts. */
|
|
24
|
+
export interface ParsedApiKey {
|
|
25
|
+
/** The original plaintext. */
|
|
26
|
+
raw: string;
|
|
27
|
+
kind: ApiKeyKind;
|
|
28
|
+
env: ApiKeyEnv;
|
|
29
|
+
/** The chars after `<prefix>_<env>_` (body + checksum for new keys). */
|
|
30
|
+
body: string;
|
|
31
|
+
/** True when this is the new checksummed format (36-char base62 body). */
|
|
32
|
+
checksummed: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The Zod schema for an Ablo API key. `parse` and `safeParse` return a typed
|
|
36
|
+
* {@link ParsedApiKey}. A checksummed-format key whose checksum does not match is
|
|
37
|
+
* rejected without any network call; an older key with no checksum parses with
|
|
38
|
+
* `checksummed: false` and is left for the server to validate by hash.
|
|
39
|
+
*/
|
|
40
|
+
export declare const apiKeySchema: z.ZodPipe<z.ZodString, z.ZodTransform<ParsedApiKey, string>>;
|
|
41
|
+
/** Parse + fully validate (incl. checksum). Returns null when invalid. */
|
|
42
|
+
export declare function parseApiKey(raw: string): ParsedApiKey | null;
|
|
43
|
+
/**
|
|
44
|
+
* Read the environment off a STORED display prefix (`keyPrefix`, the first 12
|
|
45
|
+
* chars — `rk_test_abcd`), rather than off a full plaintext key.
|
|
46
|
+
*
|
|
47
|
+
* A key row records its environment nowhere but its prefix, so this is how a
|
|
48
|
+
* server-side flow that only has the row — rotation, most importantly — recovers
|
|
49
|
+
* the credential's own mode. Returns null when the prefix is not a recognizable
|
|
50
|
+
* key spelling, so callers can fail closed rather than fall back to a default.
|
|
51
|
+
*/
|
|
52
|
+
export declare function environmentFromStoredKeyPrefix(prefix: string): KeyEnvironment | null;
|
|
53
|
+
/** True when the key uses the new checksummed format (regardless of validity). */
|
|
54
|
+
export declare function isChecksummedKey(raw: string): boolean;
|
|
55
|
+
/** Verify the embedded checksum. Meaningful only for checksummed-format keys. */
|
|
56
|
+
export declare function keyChecksumMatches(raw: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Mint a key: `<prefix>_<env>_<body><checksum>`. Returns the plaintext (shown
|
|
59
|
+
* once), its SHA-256 hash (persisted), and the 12-char display prefix.
|
|
60
|
+
*/
|
|
61
|
+
export declare function generateApiKey(env?: ApiKeyEnv, kind?: ApiKeyKind): {
|
|
62
|
+
plaintext: string;
|
|
63
|
+
hash: string;
|
|
64
|
+
prefix: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* The stable SHA-256 hex digest of a plaintext key, computed both when a key is
|
|
68
|
+
* minted and when one is looked up. A fast hash is the right choice here rather
|
|
69
|
+
* than a password hash like bcrypt: API keys are long random strings, so there is
|
|
70
|
+
* no dictionary of guesses to slow down.
|
|
71
|
+
*/
|
|
72
|
+
export declare function hashApiKey(plaintext: string): string;
|
|
73
|
+
/** `whsec_` label prefix per the Standard Webhooks spec (not part of the key material). */
|
|
74
|
+
export declare const WEBHOOK_SECRET_PREFIX = "whsec_";
|
|
75
|
+
/**
|
|
76
|
+
* Mints a webhook signing secret following the Standard Webhooks specification
|
|
77
|
+
* (https://www.standardwebhooks.com): a base64-encoded random key of 24–64 bytes,
|
|
78
|
+
* labelled with the `whsec_` prefix. This uses 32 bytes (256 bits), comfortably
|
|
79
|
+
* inside that range. Unlike an API key, a signing secret is not hashed at rest,
|
|
80
|
+
* because signing a request with {@link signAbloSourceRequest} needs the live
|
|
81
|
+
* value. It is therefore kept in a secret store, returned to the customer once at
|
|
82
|
+
* creation, and never shown again.
|
|
83
|
+
*/
|
|
84
|
+
export declare function generateWebhookSecret(): {
|
|
85
|
+
plaintext: string;
|
|
86
|
+
last4: string;
|
|
87
|
+
};
|