@abloatai/ablo 0.35.0 → 0.37.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 -2
- package/CHANGELOG.md +71 -1929
- package/NOTICE +2 -2
- package/README.md +23 -532
- package/assets/banner.png +0 -0
- package/dist/auth.d.ts +2 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +2 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +3 -0
- package/dist/client.js.map +1 -0
- package/dist/coordination.d.ts +2 -0
- package/dist/coordination.d.ts.map +1 -0
- package/dist/coordination.js +2 -0
- package/dist/coordination.js.map +1 -0
- package/dist/index.d.ts +3 -112
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -161
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +4 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +3 -0
- package/dist/react.js.map +1 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +2 -0
- package/dist/schema.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -0
- package/dist/source-conformance.d.ts +2 -0
- package/dist/source-conformance.d.ts.map +1 -0
- package/dist/source-conformance.js +2 -0
- package/dist/source-conformance.js.map +1 -0
- package/dist/source-drizzle.d.ts +2 -0
- package/dist/source-drizzle.d.ts.map +1 -0
- package/dist/source-drizzle.js +2 -0
- package/dist/source-drizzle.js.map +1 -0
- package/dist/source-kysely.d.ts +2 -0
- package/dist/source-kysely.d.ts.map +1 -0
- package/dist/source-kysely.js +2 -0
- package/dist/source-kysely.js.map +1 -0
- package/dist/source-next.d.ts +2 -0
- package/dist/source-next.d.ts.map +1 -0
- package/dist/source-next.js +2 -0
- package/dist/source-next.js.map +1 -0
- package/dist/source.d.ts +2 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +2 -0
- package/dist/source.js.map +1 -0
- package/dist/wire.d.ts +2 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +2 -0
- package/dist/wire.js.map +1 -0
- package/docs/agents.md +2 -2
- package/docs/api-keys.md +13 -12
- package/docs/api.md +15 -53
- package/docs/audit.md +4 -3
- package/docs/cli.md +11 -11
- package/docs/client-behavior.md +9 -9
- package/docs/concurrency-convention.md +28 -42
- package/docs/coordination.md +228 -86
- package/docs/data-sources.md +5 -5
- package/docs/debugging.md +34 -12
- package/docs/deployment.md +8 -8
- package/docs/examples/agent-human.md +4 -4
- package/docs/examples/ai-sdk-tool.md +1 -1
- package/docs/examples/existing-python-backend.md +15 -4
- package/docs/examples/nextjs.md +27 -6
- package/docs/examples/scoped-agent.md +3 -3
- package/docs/examples/server-agent.md +2 -2
- package/docs/groups.md +57 -3
- package/docs/guarantees.md +37 -10
- package/docs/how-it-works.md +32 -8
- package/docs/idempotency.md +6 -6
- package/docs/identity.md +24 -24
- package/docs/index.md +8 -8
- package/docs/integration-guide.md +38 -16
- package/docs/internal/README.md +18 -0
- package/docs/internal/agent-fleet-coordination-design.md +171 -0
- package/docs/internal/agent-orchestration.md +58 -0
- package/docs/internal/commit-identifiers.md +91 -0
- package/docs/internal/concurrency-open-decisions.md +37 -0
- package/docs/internal/data-source-reverse-channel.md +150 -0
- package/docs/internal/per-field-conflict-detection.md +165 -0
- package/docs/internal/postgres-replication.md +64 -0
- package/docs/internal/serializable-schema.md +119 -0
- package/docs/internal/structure.md +32 -0
- package/docs/mcp.md +9 -9
- package/docs/migration.md +37 -18
- package/docs/projects.md +1 -1
- package/docs/quickstart.md +2 -2
- package/docs/react.md +24 -13
- package/docs/schema-contract.md +3 -3
- package/docs/sessions.md +91 -37
- package/docs/webhooks.md +9 -9
- package/examples/README.md +2 -2
- package/examples/data-source/README.md +1 -1
- package/examples/data-source/ablo-driver.ts +1 -1
- package/examples/data-source/customer-server.ts +1 -1
- package/examples/data-source/run.ts +1 -1
- package/examples/data-source/schema.ts +1 -1
- package/examples/quickstart.ts +2 -2
- package/llms.txt +12 -12
- package/package.json +64 -174
- package/dist/BaseSyncedStore.d.ts +0 -823
- package/dist/BaseSyncedStore.js +0 -1955
- package/dist/Database.d.ts +0 -335
- package/dist/Database.js +0 -1500
- package/dist/InstanceCache.d.ts +0 -233
- package/dist/InstanceCache.js +0 -1164
- package/dist/LazyReferenceCollection.d.ts +0 -177
- package/dist/LazyReferenceCollection.js +0 -461
- package/dist/Model.d.ts +0 -444
- package/dist/Model.js +0 -909
- package/dist/ModelRegistry.d.ts +0 -221
- package/dist/ModelRegistry.js +0 -537
- package/dist/NetworkMonitor.d.ts +0 -26
- package/dist/NetworkMonitor.js +0 -77
- package/dist/RuntimeContext.d.ts +0 -52
- package/dist/RuntimeContext.js +0 -80
- package/dist/SyncClient.d.ts +0 -551
- package/dist/SyncClient.js +0 -2199
- package/dist/adapters/alwaysOnline.d.ts +0 -14
- package/dist/adapters/alwaysOnline.js +0 -17
- package/dist/adapters/inMemoryStorage.d.ts +0 -31
- package/dist/adapters/inMemoryStorage.js +0 -110
- package/dist/ai-sdk/coordinatedTool.d.ts +0 -120
- package/dist/ai-sdk/coordinatedTool.js +0 -134
- package/dist/ai-sdk/coordinationContext.d.ts +0 -46
- package/dist/ai-sdk/coordinationContext.js +0 -106
- package/dist/ai-sdk/index.d.ts +0 -121
- package/dist/ai-sdk/index.js +0 -121
- package/dist/ai-sdk/wrap.d.ts +0 -65
- package/dist/ai-sdk/wrap.js +0 -39
- package/dist/auth/index.d.ts +0 -1
- package/dist/auth/index.js +0 -8
- package/dist/batching/index.d.ts +0 -55
- package/dist/batching/index.js +0 -147
- package/dist/cli.cjs +0 -288600
- package/dist/client/Ablo.d.ts +0 -231
- package/dist/client/Ablo.js +0 -149
- package/dist/client/abloClient.d.ts +0 -309
- package/dist/client/abloClient.js +0 -13
- package/dist/client/clientPrelude.d.ts +0 -52
- package/dist/client/clientPrelude.js +0 -60
- package/dist/client/consoleLogger.d.ts +0 -35
- package/dist/client/consoleLogger.js +0 -44
- package/dist/client/coreClient.d.ts +0 -60
- package/dist/client/coreClient.js +0 -118
- package/dist/client/createInternalComponents.d.ts +0 -46
- package/dist/client/createInternalComponents.js +0 -92
- package/dist/client/createModelProxy.d.ts +0 -228
- package/dist/client/createModelProxy.js +0 -818
- package/dist/client/humans.d.ts +0 -48
- package/dist/client/humans.js +0 -52
- package/dist/client/modelRegistration.d.ts +0 -10
- package/dist/client/modelRegistration.js +0 -312
- package/dist/client/options.d.ts +0 -461
- package/dist/client/options.js +0 -7
- package/dist/client/reactiveEngine.d.ts +0 -48
- package/dist/client/reactiveEngine.js +0 -910
- package/dist/client/resourceTypes.d.ts +0 -12
- package/dist/client/resourceTypes.js +0 -10
- package/dist/client/schemaConfig.d.ts +0 -44
- package/dist/client/schemaConfig.js +0 -185
- package/dist/client/validateAbloOptions.d.ts +0 -42
- package/dist/client/validateAbloOptions.js +0 -43
- package/dist/client/wsMutationExecutor.d.ts +0 -27
- package/dist/client/wsMutationExecutor.js +0 -72
- package/dist/context.d.ts +0 -29
- package/dist/context.js +0 -58
- package/dist/coordination/ClaimLog.d.ts +0 -26
- package/dist/coordination/ClaimLog.js +0 -32
- package/dist/coordination/index.d.ts +0 -1
- package/dist/coordination/index.js +0 -8
- package/dist/core/DatabaseManager.d.ts +0 -105
- package/dist/core/DatabaseManager.js +0 -387
- package/dist/core/QueryProcessor.d.ts +0 -75
- package/dist/core/QueryProcessor.js +0 -255
- package/dist/core/QueryView.d.ts +0 -79
- package/dist/core/QueryView.js +0 -218
- package/dist/core/StoreManager.d.ts +0 -112
- package/dist/core/StoreManager.js +0 -302
- package/dist/core/ViewRegistry.d.ts +0 -20
- package/dist/core/ViewRegistry.js +0 -55
- package/dist/core/index.d.ts +0 -33
- package/dist/core/index.js +0 -48
- package/dist/core/openIDBWithTimeout.d.ts +0 -65
- package/dist/core/openIDBWithTimeout.js +0 -153
- package/dist/core/queryUtils.d.ts +0 -45
- package/dist/core/queryUtils.js +0 -69
- package/dist/core/storeContract.d.ts +0 -145
- package/dist/core/storeContract.js +0 -12
- package/dist/docs/catalog.d.ts +0 -72
- package/dist/docs/catalog.js +0 -227
- package/dist/docs/index.d.ts +0 -10
- package/dist/docs/index.js +0 -10
- package/dist/environment.d.ts +0 -1
- package/dist/environment.js +0 -8
- package/dist/interfaces/index.d.ts +0 -311
- package/dist/interfaces/index.js +0 -9
- package/dist/keys/index.d.ts +0 -1
- package/dist/keys/index.js +0 -8
- package/dist/mutators/RecordingMutation.d.ts +0 -36
- package/dist/mutators/RecordingMutation.js +0 -182
- package/dist/mutators/Transaction.d.ts +0 -40
- package/dist/mutators/Transaction.js +0 -58
- package/dist/mutators/UndoManager.d.ts +0 -258
- package/dist/mutators/UndoManager.js +0 -658
- package/dist/mutators/defineMutators.d.ts +0 -60
- package/dist/mutators/defineMutators.js +0 -18
- package/dist/mutators/inverseOp.d.ts +0 -126
- package/dist/mutators/inverseOp.js +0 -71
- package/dist/mutators/mutateActions.d.ts +0 -45
- package/dist/mutators/mutateActions.js +0 -105
- package/dist/mutators/readerActions.d.ts +0 -33
- package/dist/mutators/readerActions.js +0 -57
- package/dist/mutators/undoApply.d.ts +0 -51
- package/dist/mutators/undoApply.js +0 -117
- package/dist/policy/index.d.ts +0 -21
- package/dist/policy/index.js +0 -20
- package/dist/query/client.d.ts +0 -61
- package/dist/query/client.js +0 -137
- package/dist/query/types.d.ts +0 -85
- package/dist/query/types.js +0 -16
- package/dist/react/AbloProvider.d.ts +0 -230
- package/dist/react/AbloProvider.js +0 -455
- package/dist/react/ClientSideSuspense.d.ts +0 -36
- package/dist/react/ClientSideSuspense.js +0 -17
- package/dist/react/DefaultFallback.d.ts +0 -24
- package/dist/react/DefaultFallback.js +0 -43
- package/dist/react/context.d.ts +0 -55
- package/dist/react/context.js +0 -29
- package/dist/react/index.d.ts +0 -61
- package/dist/react/index.js +0 -66
- package/dist/react/internalContext.d.ts +0 -33
- package/dist/react/internalContext.js +0 -3
- package/dist/react/useAblo.d.ts +0 -75
- package/dist/react/useAblo.js +0 -102
- package/dist/react/useCurrentUserId.d.ts +0 -22
- package/dist/react/useCurrentUserId.js +0 -34
- package/dist/react/useErrorListener.d.ts +0 -20
- package/dist/react/useErrorListener.js +0 -38
- package/dist/react/useMutationFailureListener.d.ts +0 -26
- package/dist/react/useMutationFailureListener.js +0 -38
- package/dist/react/useMutators.d.ts +0 -56
- package/dist/react/useMutators.js +0 -84
- package/dist/react/useReactive.d.ts +0 -35
- package/dist/react/useReactive.js +0 -123
- package/dist/react/useSyncStatus.d.ts +0 -59
- package/dist/react/useSyncStatus.js +0 -76
- package/dist/react/useUndoScope.d.ts +0 -34
- package/dist/react/useUndoScope.js +0 -81
- package/dist/schema/coordination.d.ts +0 -112
- package/dist/schema/coordination.js +0 -129
- package/dist/schema/ddl.d.ts +0 -97
- package/dist/schema/ddl.js +0 -491
- package/dist/schema/ddlLock.d.ts +0 -35
- package/dist/schema/ddlLock.js +0 -46
- package/dist/schema/diff.d.ts +0 -225
- package/dist/schema/diff.js +0 -289
- package/dist/schema/generate.d.ts +0 -19
- package/dist/schema/generate.js +0 -86
- package/dist/schema/index.d.ts +0 -41
- package/dist/schema/index.js +0 -76
- package/dist/schema/queries.d.ts +0 -201
- package/dist/schema/queries.js +0 -144
- package/dist/schema/select.d.ts +0 -40
- package/dist/schema/select.js +0 -87
- package/dist/schema/serialize.d.ts +0 -115
- package/dist/schema/serialize.js +0 -262
- package/dist/schema/sugar.d.ts +0 -109
- package/dist/schema/sugar.js +0 -83
- package/dist/schema/syncDeltaRow.d.ts +0 -6
- package/dist/schema/syncDeltaRow.js +0 -6
- package/dist/server/adapter.d.ts +0 -173
- package/dist/server/adapter.js +0 -18
- package/dist/server/commit.d.ts +0 -107
- package/dist/server/commit.js +0 -1
- package/dist/server/index.d.ts +0 -14
- package/dist/server/index.js +0 -2
- package/dist/server/readConfig.d.ts +0 -80
- package/dist/server/readConfig.js +0 -8
- package/dist/server/storageMode.d.ts +0 -23
- package/dist/server/storageMode.js +0 -17
- package/dist/source/adapter.d.ts +0 -81
- package/dist/source/adapter.js +0 -22
- package/dist/source/adapters/drizzle.d.ts +0 -48
- package/dist/source/adapters/drizzle.js +0 -219
- package/dist/source/adapters/kysely.d.ts +0 -42
- package/dist/source/adapters/kysely.js +0 -205
- package/dist/source/adapters/kyselyMutationCore.d.ts +0 -76
- package/dist/source/adapters/kyselyMutationCore.js +0 -125
- package/dist/source/adapters/memory.d.ts +0 -13
- package/dist/source/adapters/memory.js +0 -130
- package/dist/source/adapters/prisma.d.ts +0 -63
- package/dist/source/adapters/prisma.js +0 -202
- package/dist/source/conformance.d.ts +0 -37
- package/dist/source/conformance.js +0 -215
- package/dist/source/connector.d.ts +0 -95
- package/dist/source/connector.js +0 -266
- package/dist/source/connectorProtocol.d.ts +0 -154
- package/dist/source/connectorProtocol.js +0 -163
- package/dist/source/contract.d.ts +0 -195
- package/dist/source/contract.js +0 -164
- package/dist/source/factory.d.ts +0 -92
- package/dist/source/factory.js +0 -286
- package/dist/source/footprint.d.ts +0 -111
- package/dist/source/footprint.js +0 -0
- package/dist/source/idempotency.d.ts +0 -61
- package/dist/source/idempotency.js +0 -144
- package/dist/source/index.d.ts +0 -23
- package/dist/source/index.js +0 -30
- package/dist/source/migrations.d.ts +0 -21
- package/dist/source/migrations.js +0 -103
- package/dist/source/next.d.ts +0 -32
- package/dist/source/next.js +0 -25
- package/dist/source/pushQueue.d.ts +0 -134
- package/dist/source/pushQueue.js +0 -256
- package/dist/source/signing.d.ts +0 -92
- package/dist/source/signing.js +0 -162
- package/dist/source/types.d.ts +0 -401
- package/dist/source/types.js +0 -59
- package/dist/stores/ObjectStore.d.ts +0 -115
- package/dist/stores/ObjectStore.js +0 -393
- package/dist/stores/ObjectStoreContract.d.ts +0 -38
- package/dist/stores/ObjectStoreContract.js +0 -1
- package/dist/stores/SyncActionStore.d.ts +0 -97
- package/dist/stores/SyncActionStore.js +0 -504
- package/dist/stores/syncAction.d.ts +0 -26
- package/dist/stores/syncAction.js +0 -16
- package/dist/surface.d.ts +0 -36
- package/dist/surface.js +0 -75
- package/dist/sync/BootstrapFetcher.d.ts +0 -280
- package/dist/sync/BootstrapFetcher.js +0 -962
- package/dist/sync/ConnectionManager.d.ts +0 -8
- package/dist/sync/ConnectionManager.js +0 -8
- package/dist/sync/OnDemandLoader.d.ts +0 -228
- package/dist/sync/OnDemandLoader.js +0 -742
- package/dist/sync/SubscriptionManager.d.ts +0 -159
- package/dist/sync/SubscriptionManager.js +0 -243
- package/dist/sync/SyncWebSocket.d.ts +0 -173
- package/dist/sync/SyncWebSocket.js +0 -438
- package/dist/sync/awaitClaimGrant.d.ts +0 -6
- package/dist/sync/awaitClaimGrant.js +0 -6
- package/dist/sync/bootstrapApply.d.ts +0 -70
- package/dist/sync/bootstrapApply.js +0 -73
- package/dist/sync/commitFrames.d.ts +0 -8
- package/dist/sync/commitFrames.js +0 -8
- package/dist/sync/contextPorts.d.ts +0 -18
- package/dist/sync/contextPorts.js +0 -31
- package/dist/sync/createClaimStream.d.ts +0 -7
- package/dist/sync/createClaimStream.js +0 -7
- package/dist/sync/createPresenceStream.d.ts +0 -69
- package/dist/sync/createPresenceStream.js +0 -200
- package/dist/sync/createSnapshot.d.ts +0 -29
- package/dist/sync/createSnapshot.js +0 -118
- package/dist/sync/credentialLifecycle.d.ts +0 -7
- package/dist/sync/credentialLifecycle.js +0 -7
- package/dist/sync/deltaPipeline.d.ts +0 -113
- package/dist/sync/deltaPipeline.js +0 -261
- package/dist/sync/groupChange.d.ts +0 -113
- package/dist/sync/groupChange.js +0 -242
- package/dist/sync/participants.d.ts +0 -115
- package/dist/sync/participants.js +0 -344
- package/dist/sync/persistedPrefix.d.ts +0 -12
- package/dist/sync/persistedPrefix.js +0 -22
- package/dist/sync/schemaDrift.d.ts +0 -55
- package/dist/sync/schemaDrift.js +0 -53
- package/dist/sync/schemas.d.ts +0 -70
- package/dist/sync/schemas.js +0 -94
- package/dist/sync/syncCursor.d.ts +0 -40
- package/dist/sync/syncCursor.js +0 -55
- package/dist/sync/syncPlan.d.ts +0 -54
- package/dist/sync/syncPlan.js +0 -50
- package/dist/sync/wsFrameHandlers.d.ts +0 -8
- package/dist/sync/wsFrameHandlers.js +0 -8
- package/dist/testing/fixtures/bootstrap.d.ts +0 -49
- package/dist/testing/fixtures/bootstrap.js +0 -59
- package/dist/testing/fixtures/deltas.d.ts +0 -83
- package/dist/testing/fixtures/deltas.js +0 -136
- package/dist/testing/fixtures/httpResponses.d.ts +0 -70
- package/dist/testing/fixtures/httpResponses.js +0 -90
- package/dist/testing/fixtures/models.d.ts +0 -83
- package/dist/testing/fixtures/models.js +0 -272
- package/dist/testing/helpers/reactWrapper.d.ts +0 -69
- package/dist/testing/helpers/reactWrapper.js +0 -67
- package/dist/testing/helpers/syncEngineHarness.d.ts +0 -54
- package/dist/testing/helpers/syncEngineHarness.js +0 -73
- package/dist/testing/helpers/wait.d.ts +0 -30
- package/dist/testing/helpers/wait.js +0 -49
- package/dist/testing/index.d.ts +0 -23
- package/dist/testing/index.js +0 -33
- package/dist/testing/mocks/FakeDatabase.d.ts +0 -18
- package/dist/testing/mocks/FakeDatabase.js +0 -10
- package/dist/testing/mocks/MockMutationExecutor.d.ts +0 -87
- package/dist/testing/mocks/MockMutationExecutor.js +0 -186
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +0 -20
- package/dist/testing/mocks/MockNetworkMonitor.js +0 -46
- package/dist/testing/mocks/MockSyncContext.d.ts +0 -51
- package/dist/testing/mocks/MockSyncContext.js +0 -72
- package/dist/testing/mocks/MockSyncStore.d.ts +0 -88
- package/dist/testing/mocks/MockSyncStore.js +0 -171
- package/dist/testing/mocks/MockWebSocket.d.ts +0 -71
- package/dist/testing/mocks/MockWebSocket.js +0 -118
- package/dist/transaction/ablo.d.ts +0 -88
- package/dist/transaction/ablo.js +0 -33
- package/dist/transaction/auth/apiKey.d.ts +0 -152
- package/dist/transaction/auth/apiKey.js +0 -419
- package/dist/transaction/auth/bootstrapScope.d.ts +0 -15
- package/dist/transaction/auth/bootstrapScope.js +0 -1
- package/dist/transaction/auth/capability.d.ts +0 -177
- package/dist/transaction/auth/capability.js +0 -199
- package/dist/transaction/auth/credentialEndpoint.d.ts +0 -61
- package/dist/transaction/auth/credentialEndpoint.js +0 -86
- package/dist/transaction/auth/credentialPolicy.d.ts +0 -148
- package/dist/transaction/auth/credentialPolicy.js +0 -125
- package/dist/transaction/auth/credentialSource.d.ts +0 -30
- package/dist/transaction/auth/credentialSource.js +0 -55
- package/dist/transaction/auth/hostedEndpoints.d.ts +0 -21
- package/dist/transaction/auth/hostedEndpoints.js +0 -21
- package/dist/transaction/auth/identity.d.ts +0 -55
- package/dist/transaction/auth/identity.js +0 -210
- package/dist/transaction/auth/index.d.ts +0 -162
- package/dist/transaction/auth/index.js +0 -304
- package/dist/transaction/auth/schemas.d.ts +0 -59
- package/dist/transaction/auth/schemas.js +0 -85
- package/dist/transaction/auth/sessionMint.d.ts +0 -28
- package/dist/transaction/auth/sessionMint.js +0 -85
- package/dist/transaction/coordination/awaitClaimGrant.d.ts +0 -49
- package/dist/transaction/coordination/awaitClaimGrant.js +0 -112
- package/dist/transaction/coordination/claimHeartbeatLoop.d.ts +0 -50
- package/dist/transaction/coordination/claimHeartbeatLoop.js +0 -88
- package/dist/transaction/coordination/claimMeta.d.ts +0 -49
- package/dist/transaction/coordination/claimMeta.js +0 -52
- package/dist/transaction/coordination/createClaimStream.d.ts +0 -64
- package/dist/transaction/coordination/createClaimStream.js +0 -475
- package/dist/transaction/coordination/events.d.ts +0 -74
- package/dist/transaction/coordination/events.js +0 -7
- package/dist/transaction/coordination/index.d.ts +0 -19
- package/dist/transaction/coordination/index.js +0 -44
- package/dist/transaction/coordination/locator.d.ts +0 -83
- package/dist/transaction/coordination/locator.js +0 -82
- package/dist/transaction/coordination/schema.d.ts +0 -1473
- package/dist/transaction/coordination/schema.js +0 -1013
- package/dist/transaction/coordination/targetConflict.d.ts +0 -2
- package/dist/transaction/coordination/targetConflict.js +0 -103
- package/dist/transaction/coordination/trace.d.ts +0 -78
- package/dist/transaction/coordination/trace.js +0 -138
- package/dist/transaction/durableWrites.d.ts +0 -62
- package/dist/transaction/durableWrites.js +0 -71
- package/dist/transaction/environment.d.ts +0 -105
- package/dist/transaction/environment.js +0 -108
- package/dist/transaction/errorCodes.d.ts +0 -403
- package/dist/transaction/errorCodes.js +0 -480
- package/dist/transaction/errors.d.ts +0 -428
- package/dist/transaction/errors.js +0 -686
- package/dist/transaction/index.d.ts +0 -20
- package/dist/transaction/index.js +0 -20
- package/dist/transaction/keys/index.d.ts +0 -87
- package/dist/transaction/keys/index.js +0 -207
- package/dist/transaction/log/syncDeltaRow.d.ts +0 -158
- package/dist/transaction/log/syncDeltaRow.js +0 -95
- package/dist/transaction/logPosition.d.ts +0 -97
- package/dist/transaction/logPosition.js +0 -125
- package/dist/transaction/logger.d.ts +0 -16
- package/dist/transaction/logger.js +0 -7
- package/dist/transaction/observability.d.ts +0 -53
- package/dist/transaction/observability.js +0 -19
- package/dist/transaction/persistence.d.ts +0 -12
- package/dist/transaction/persistence.js +0 -11
- package/dist/transaction/plugin.d.ts +0 -192
- package/dist/transaction/plugin.js +0 -87
- package/dist/transaction/policy/types.d.ts +0 -217
- package/dist/transaction/policy/types.js +0 -126
- package/dist/transaction/resources/functionalUpdate.d.ts +0 -79
- package/dist/transaction/resources/functionalUpdate.js +0 -87
- package/dist/transaction/resources/httpResources.d.ts +0 -266
- package/dist/transaction/resources/httpResources.js +0 -7
- package/dist/transaction/resources/modelOperations.d.ts +0 -319
- package/dist/transaction/resources/modelOperations.js +0 -12
- package/dist/transaction/resources/mutationOptions.d.ts +0 -66
- package/dist/transaction/resources/mutationOptions.js +0 -9
- package/dist/transaction/resources/where.d.ts +0 -85
- package/dist/transaction/resources/where.js +0 -70
- package/dist/transaction/resources/writeOptionsSchema.d.ts +0 -47
- package/dist/transaction/resources/writeOptionsSchema.js +0 -73
- package/dist/transaction/schema/field.d.ts +0 -126
- package/dist/transaction/schema/field.js +0 -265
- package/dist/transaction/schema/loadStrategy.d.ts +0 -45
- package/dist/transaction/schema/loadStrategy.js +0 -46
- package/dist/transaction/schema/model.d.ts +0 -379
- package/dist/transaction/schema/model.js +0 -123
- package/dist/transaction/schema/openapi.d.ts +0 -57
- package/dist/transaction/schema/openapi.js +0 -340
- package/dist/transaction/schema/relation.d.ts +0 -199
- package/dist/transaction/schema/relation.js +0 -104
- package/dist/transaction/schema/residency.d.ts +0 -29
- package/dist/transaction/schema/residency.js +0 -25
- package/dist/transaction/schema/roles.d.ts +0 -249
- package/dist/transaction/schema/roles.js +0 -230
- package/dist/transaction/schema/schema.d.ts +0 -324
- package/dist/transaction/schema/schema.js +0 -305
- package/dist/transaction/schema/tenancy.d.ts +0 -139
- package/dist/transaction/schema/tenancy.js +0 -190
- package/dist/transaction/transactionLayer.d.ts +0 -82
- package/dist/transaction/transactionLayer.js +0 -24
- package/dist/transaction/transactions/settlement/commitEnvelope.d.ts +0 -143
- package/dist/transaction/transactions/settlement/commitEnvelope.js +0 -161
- package/dist/transaction/transactions/settlement/httpCommitEnvelope.d.ts +0 -53
- package/dist/transaction/transactions/settlement/httpCommitEnvelope.js +0 -207
- package/dist/transaction/transactions/settlement/idempotencyKey.d.ts +0 -10
- package/dist/transaction/transactions/settlement/idempotencyKey.js +0 -9
- package/dist/transaction/transactions/settlement/pendingWrite.d.ts +0 -112
- package/dist/transaction/transactions/settlement/pendingWrite.js +0 -20
- package/dist/transaction/transport/commitFrames.d.ts +0 -90
- package/dist/transaction/transport/commitFrames.js +0 -134
- package/dist/transaction/transport/connectionManager.d.ts +0 -215
- package/dist/transaction/transport/connectionManager.js +0 -673
- package/dist/transaction/transport/credentialLifecycle.d.ts +0 -177
- package/dist/transaction/transport/credentialLifecycle.js +0 -324
- package/dist/transaction/transport/heartbeat.d.ts +0 -65
- package/dist/transaction/transport/heartbeat.js +0 -93
- package/dist/transaction/transport/httpClient.d.ts +0 -123
- package/dist/transaction/transport/httpClient.js +0 -145
- package/dist/transaction/transport/httpOptions.d.ts +0 -33
- package/dist/transaction/transport/httpOptions.js +0 -12
- package/dist/transaction/transport/httpTransport.d.ts +0 -8
- package/dist/transaction/transport/httpTransport.js +0 -1276
- package/dist/transaction/transport/networkProbe.d.ts +0 -84
- package/dist/transaction/transport/networkProbe.js +0 -207
- package/dist/transaction/transport/wsFrameHandlers.d.ts +0 -128
- package/dist/transaction/transport/wsFrameHandlers.js +0 -429
- package/dist/transaction/transport/wsTransport.d.ts +0 -576
- package/dist/transaction/transport/wsTransport.js +0 -1017
- package/dist/transaction/types/assertExact.d.ts +0 -17
- package/dist/transaction/types/assertExact.js +0 -1
- package/dist/transaction/types/global.d.ts +0 -107
- package/dist/transaction/types/global.js +0 -40
- package/dist/transaction/types/index.d.ts +0 -205
- package/dist/transaction/types/index.js +0 -56
- package/dist/transaction/types/modelData.d.ts +0 -10
- package/dist/transaction/types/modelData.js +0 -9
- package/dist/transaction/types/participant.d.ts +0 -20
- package/dist/transaction/types/participant.js +0 -10
- package/dist/transaction/types/streams.d.ts +0 -540
- package/dist/transaction/types/streams.js +0 -11
- package/dist/transaction/utils/asyncIterator.d.ts +0 -34
- package/dist/transaction/utils/asyncIterator.js +0 -135
- package/dist/transaction/utils/duration.d.ts +0 -25
- package/dist/transaction/utils/duration.js +0 -45
- package/dist/transaction/utils/json.d.ts +0 -57
- package/dist/transaction/utils/json.js +0 -276
- package/dist/transaction/wire/accountResponses.d.ts +0 -351
- package/dist/transaction/wire/accountResponses.js +0 -255
- package/dist/transaction/wire/auth.d.ts +0 -49
- package/dist/transaction/wire/auth.js +0 -57
- package/dist/transaction/wire/bootstrapReason.d.ts +0 -9
- package/dist/transaction/wire/bootstrapReason.js +0 -8
- package/dist/transaction/wire/claimEvent.d.ts +0 -76
- package/dist/transaction/wire/claimEvent.js +0 -73
- package/dist/transaction/wire/claims.d.ts +0 -463
- package/dist/transaction/wire/claims.js +0 -229
- package/dist/transaction/wire/commit.d.ts +0 -603
- package/dist/transaction/wire/commit.js +0 -321
- package/dist/transaction/wire/delta.d.ts +0 -250
- package/dist/transaction/wire/delta.js +0 -147
- package/dist/transaction/wire/errorEnvelope.d.ts +0 -72
- package/dist/transaction/wire/errorEnvelope.js +0 -123
- package/dist/transaction/wire/feedCursor.d.ts +0 -60
- package/dist/transaction/wire/feedCursor.js +0 -82
- package/dist/transaction/wire/feedEvent.d.ts +0 -177
- package/dist/transaction/wire/feedEvent.js +0 -39
- package/dist/transaction/wire/frames.d.ts +0 -194
- package/dist/transaction/wire/frames.js +0 -50
- package/dist/transaction/wire/inboundFrames.d.ts +0 -552
- package/dist/transaction/wire/inboundFrames.js +0 -116
- package/dist/transaction/wire/index.d.ts +0 -50
- package/dist/transaction/wire/index.js +0 -74
- package/dist/transaction/wire/listEnvelope.d.ts +0 -37
- package/dist/transaction/wire/listEnvelope.js +0 -42
- package/dist/transaction/wire/modelResponses.d.ts +0 -85
- package/dist/transaction/wire/modelResponses.js +0 -43
- package/dist/transaction/wire/protocol.d.ts +0 -38
- package/dist/transaction/wire/protocol.js +0 -38
- package/dist/transaction/wire/protocolVersion.d.ts +0 -73
- package/dist/transaction/wire/protocolVersion.js +0 -83
- package/dist/transactions/mutations/MutationQueue.d.ts +0 -655
- package/dist/transactions/mutations/MutationQueue.js +0 -2797
- package/dist/transactions/mutations/MutationStore.d.ts +0 -20
- package/dist/transactions/mutations/MutationStore.js +0 -53
- package/dist/transactions/mutations/UnconfirmedWrites.d.ts +0 -82
- package/dist/transactions/mutations/UnconfirmedWrites.js +0 -104
- package/dist/transactions/mutations/coalesceRules.d.ts +0 -58
- package/dist/transactions/mutations/coalesceRules.js +0 -140
- package/dist/transactions/mutations/commitLatency.d.ts +0 -52
- package/dist/transactions/mutations/commitLatency.js +0 -130
- package/dist/transactions/mutations/commitOutboxStore.d.ts +0 -28
- package/dist/transactions/mutations/commitOutboxStore.js +0 -26
- package/dist/transactions/mutations/commitPayload.d.ts +0 -164
- package/dist/transactions/mutations/commitPayload.js +0 -152
- package/dist/transactions/mutations/deltaConfirmation.d.ts +0 -59
- package/dist/transactions/mutations/deltaConfirmation.js +0 -233
- package/dist/transactions/mutations/durableWriteStore.d.ts +0 -14
- package/dist/transactions/mutations/durableWriteStore.js +0 -12
- package/dist/transactions/mutations/optimisticApply.d.ts +0 -49
- package/dist/transactions/mutations/optimisticApply.js +0 -65
- package/dist/transactions/mutations/replayValidation.d.ts +0 -186
- package/dist/transactions/mutations/replayValidation.js +0 -163
- package/dist/utils/mobxSetup.d.ts +0 -53
- package/dist/utils/mobxSetup.js +0 -330
- package/dist/webhooks/events.d.ts +0 -43
- package/dist/webhooks/events.js +0 -42
- package/dist/webhooks/index.d.ts +0 -8
- package/dist/webhooks/index.js +0 -8
- package/dist/wire/index.d.ts +0 -1
- package/dist/wire/index.js +0 -8
- package/docs/interaction-model.md +0 -99
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The conflict types a policy decides on. The engine detects a conflict and
|
|
3
|
-
* hands it to your {@link ConflictPolicy}, which returns a
|
|
4
|
-
* {@link ConflictDecision}.
|
|
5
|
-
*
|
|
6
|
-
* There are two conflict shapes. A {@link StaleContextConflict} is a write
|
|
7
|
-
* whose `readAt` watermark is older than the latest delta on the target row. A
|
|
8
|
-
* {@link ClaimHeldConflict} is a participant trying to claim a target that
|
|
9
|
-
* someone else already holds. {@link Conflict} is the discriminated union of
|
|
10
|
-
* the two; switch on `kind` to narrow it.
|
|
11
|
-
*/
|
|
12
|
-
import type { ParticipantRef } from '../types/participant.js';
|
|
13
|
-
import type { CommitOperationType, OnStaleMode } from '../coordination/schema.js';
|
|
14
|
-
export type ConflictKind = 'stale_context' | 'claim_held';
|
|
15
|
-
/** Fields shared by every conflict shape. */
|
|
16
|
-
interface ConflictBase {
|
|
17
|
-
readonly committer: ParticipantRef;
|
|
18
|
-
readonly organizationId: string;
|
|
19
|
-
/** Human at the root of the committer's delegation chain (if any). */
|
|
20
|
-
readonly delegationChainRootUserId?: string | null;
|
|
21
|
-
}
|
|
22
|
-
/** The operation whose write conflicts. */
|
|
23
|
-
export interface ConflictOperation {
|
|
24
|
-
readonly model: string;
|
|
25
|
-
readonly id: string;
|
|
26
|
-
readonly type: CommitOperationType;
|
|
27
|
-
readonly input?: Readonly<Record<string, unknown>>;
|
|
28
|
-
}
|
|
29
|
-
export interface StaleContextConflict extends ConflictBase {
|
|
30
|
-
readonly kind: 'stale_context';
|
|
31
|
-
readonly operation: ConflictOperation;
|
|
32
|
-
/** Watermark the committer reasoned against. */
|
|
33
|
-
readonly readAt: number;
|
|
34
|
-
/** Most recent delta id on the target. */
|
|
35
|
-
readonly observedSyncId: number;
|
|
36
|
-
/**
|
|
37
|
-
* The fields whose concurrent change triggered this conflict — the
|
|
38
|
-
* intersection of the fields the committer wrote and the columns a newer
|
|
39
|
-
* delta touched. An empty array means the conflicting delta was a
|
|
40
|
-
* whole-entity change, such as a create or delete, which conflicts with any
|
|
41
|
-
* write. A policy can use this to decide at field granularity — for example,
|
|
42
|
-
* allowing the write when the only overlap is on a cosmetic field.
|
|
43
|
-
*/
|
|
44
|
-
readonly conflictingFields?: readonly string[];
|
|
45
|
-
/**
|
|
46
|
-
* The committer's declared `onStale` intent for this operation. The default
|
|
47
|
-
* policy honors it: `'notify'` holds the write and notifies, and anything
|
|
48
|
-
* else rejects. A custom policy may override this. When absent, it is treated
|
|
49
|
-
* as `'reject'`, the default for an unguarded write.
|
|
50
|
-
*/
|
|
51
|
-
readonly requestedMode?: OnStaleMode;
|
|
52
|
-
}
|
|
53
|
-
export interface ClaimHeldConflict extends ConflictBase {
|
|
54
|
-
readonly kind: 'claim_held';
|
|
55
|
-
readonly heldBy: ParticipantRef;
|
|
56
|
-
readonly claimId: string;
|
|
57
|
-
readonly entityType: string;
|
|
58
|
-
readonly entityId: string;
|
|
59
|
-
/** Holder's claim expiry (ms since epoch). */
|
|
60
|
-
readonly expiresAt: number;
|
|
61
|
-
/**
|
|
62
|
-
* The capability operations granted to the committer — the allowlist carried
|
|
63
|
-
* by its key. A policy decides purely from the conflict it is given, so this
|
|
64
|
-
* is the only place it can read the committer's privileges. It lets a policy
|
|
65
|
-
* express a rule such as "preempt only if the committer holds `claim.preempt`"
|
|
66
|
-
* (see {@link capabilityPreemptPolicy}). Empty for a human session that
|
|
67
|
-
* carries no allowlist.
|
|
68
|
-
*/
|
|
69
|
-
readonly committerOperations: readonly string[];
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* The discriminated union the policy receives. Switch on `.kind` to
|
|
73
|
-
* narrow to the variant.
|
|
74
|
-
*/
|
|
75
|
-
export type Conflict = StaleContextConflict | ClaimHeldConflict;
|
|
76
|
-
/** What the policy returns. */
|
|
77
|
-
export type ConflictDecision = {
|
|
78
|
-
readonly action: 'reject';
|
|
79
|
-
readonly reason?: string;
|
|
80
|
-
} | {
|
|
81
|
-
readonly action: 'allow';
|
|
82
|
-
readonly note?: string;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Evict the current holder and grant the target to the committer. This is
|
|
86
|
-
* only meaningful for a `claim_held` conflict raised at claim time: the
|
|
87
|
-
* holder receives a `claim_lost` notification with reason `'preempted'`, and
|
|
88
|
-
* the committer takes the lease ahead of anyone already waiting in line for
|
|
89
|
-
* it. Return it only for a committer you consider higher priority — for
|
|
90
|
-
* example, a supervisor over its own sub-agents, or an identity that holds a
|
|
91
|
-
* preempt capability. At commit time there is no holder to evict, so a
|
|
92
|
-
* `preempt` decision is treated as `allow`.
|
|
93
|
-
*/
|
|
94
|
-
| {
|
|
95
|
-
readonly action: 'preempt';
|
|
96
|
-
readonly reason?: string;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Hold the write instead of aborting it. This is only meaningful for a
|
|
100
|
-
* `stale_context` conflict. The engine withholds the conflicting operation
|
|
101
|
-
* and returns a `StaleNotification` carrying the current value, so the actor
|
|
102
|
-
* — an agent or a human — can reconcile and re-commit. The rest of the batch
|
|
103
|
-
* still commits. It maps from `onStale: 'notify'`.
|
|
104
|
-
*
|
|
105
|
-
* The monotonic `sync_id` landing order decides who yields: the stale
|
|
106
|
-
* committer always recomputes against the newer value, an asymmetry that
|
|
107
|
-
* prevents two notifying writers from looping against each other. Retries are
|
|
108
|
-
* bounded by the client's reconciliation retry cap.
|
|
109
|
-
*/
|
|
110
|
-
| {
|
|
111
|
-
readonly action: 'notify';
|
|
112
|
-
readonly reason?: string;
|
|
113
|
-
};
|
|
114
|
-
/**
|
|
115
|
-
* The function that decides a conflict. It receives a {@link Conflict} and
|
|
116
|
-
* returns a {@link ConflictDecision}, either synchronously or as a promise.
|
|
117
|
-
* Register your implementation with the engine; the example below allows a
|
|
118
|
-
* cosmetic "linter" writer and defers everything else to {@link defaultPolicy}.
|
|
119
|
-
*
|
|
120
|
-
* ```ts
|
|
121
|
-
* const policy: ConflictPolicy = (conflict) => {
|
|
122
|
-
* if (conflict.committer.id.startsWith('linter:')) {
|
|
123
|
-
* return { action: 'allow', note: 'cosmetic writer' };
|
|
124
|
-
* }
|
|
125
|
-
* return defaultPolicy(conflict);
|
|
126
|
-
* };
|
|
127
|
-
* ```
|
|
128
|
-
*/
|
|
129
|
-
export type ConflictPolicy = (conflict: Conflict) => ConflictDecision | Promise<ConflictDecision>;
|
|
130
|
-
/**
|
|
131
|
-
* The conflict policy the engine uses when you do not supply your own. It
|
|
132
|
-
* favors people: a human is never blocked, while agents and automated writers
|
|
133
|
-
* yield to a claim someone else holds.
|
|
134
|
-
*
|
|
135
|
-
* For a `claim_held` conflict, the decision follows the committer's kind:
|
|
136
|
-
*
|
|
137
|
-
* • `user` → `allow` — a human is never blocked by a claim. A claim is a
|
|
138
|
-
* coordination hint among agents, not a lock on
|
|
139
|
-
* people.
|
|
140
|
-
* • `agent` → `reject` — an agent yields to a claim held by someone else.
|
|
141
|
-
* The one sanctioned exception is the privileged
|
|
142
|
-
* `claim.preempt` capability; see
|
|
143
|
-
* {@link capabilityPreemptPolicy}.
|
|
144
|
-
* • `system` → `reject` — automated and backend writers serialize through
|
|
145
|
-
* claims the same way agents do, so a server job
|
|
146
|
-
* cannot silently overwrite a held row. Declare the
|
|
147
|
-
* model's conflict axis to overwrite if you want that.
|
|
148
|
-
*
|
|
149
|
-
* Allowing only `user` by default is deliberate: a backend key is a
|
|
150
|
-
* full-access credential, and claim serialization depends on those writers
|
|
151
|
-
* respecting claims unless a model opts out.
|
|
152
|
-
*
|
|
153
|
-
* For a `stale_context` conflict, the decision honors the committer's declared
|
|
154
|
-
* `onStale` intent: `'notify'` holds the write and notifies the actor to
|
|
155
|
-
* resolve it, and anything else (including `'reject'` or an absent value)
|
|
156
|
-
* rejects. An `onStale` of `'overwrite'` never reaches a policy — it is a hard
|
|
157
|
-
* opt-out resolved before the conflict is detected.
|
|
158
|
-
*
|
|
159
|
-
* To change this behavior for a model, declare its conflict axis in the schema;
|
|
160
|
-
* a declared axis overrides this default.
|
|
161
|
-
*/
|
|
162
|
-
export declare const defaultPolicy: (conflict: Conflict) => ConflictDecision;
|
|
163
|
-
/**
|
|
164
|
-
* A ready-made policy that grants capability-gated preemption. When the
|
|
165
|
-
* committer's capability allowlist includes the `claim.preempt` operation, a
|
|
166
|
-
* `claim_held` conflict is preempted: the current holder is evicted and the
|
|
167
|
-
* committer takes the lease. Every other conflict falls back to
|
|
168
|
-
* {@link defaultPolicy}, which rejects. Register it as your conflict policy to
|
|
169
|
-
* let a privileged identity take over a held entity without writing a bespoke
|
|
170
|
-
* policy. The authorization rests on holding the capability, not on any
|
|
171
|
-
* particular identity string.
|
|
172
|
-
*/
|
|
173
|
-
export declare const capabilityPreemptPolicy: ConflictPolicy;
|
|
174
|
-
/**
|
|
175
|
-
* A model's declared conflict disposition, keyed by the kind of committer. You
|
|
176
|
-
* set it in the model's schema, for example
|
|
177
|
-
* `conflict: { user: 'overwrite', agent: 'reject' }`, and the engine applies it
|
|
178
|
-
* at commit time. It is plain data using the same `'reject' | 'overwrite' |
|
|
179
|
-
* 'notify'` vocabulary as the write guards, so it travels through the schema
|
|
180
|
-
* registry to the server without naming any application model.
|
|
181
|
-
*
|
|
182
|
-
* Each key is the committer's participant kind, which the server derives and a
|
|
183
|
-
* client cannot forge; an omitted kind falls back to the engine default. So
|
|
184
|
-
* `{ user: 'overwrite', agent: 'reject' }` reads as "a human's write wins, an
|
|
185
|
-
* agent's write yields," and `system`, being unlisted, takes the default.
|
|
186
|
-
*/
|
|
187
|
-
export interface ConflictAxis {
|
|
188
|
-
/** What happens when a human (`user` session) commits into a conflict. */
|
|
189
|
-
readonly user?: OnStaleMode;
|
|
190
|
-
/** What happens when an AI `agent` commits into a conflict. */
|
|
191
|
-
readonly agent?: OnStaleMode;
|
|
192
|
-
/** What happens when a `system` / automation actor commits into a conflict. */
|
|
193
|
-
readonly system?: OnStaleMode;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Resolves a declared {@link ConflictAxis} into a {@link ConflictDecision} for
|
|
197
|
-
* one concrete conflict. It is pure and synchronous, doing no I/O, so it can
|
|
198
|
-
* run on either the client or the server. It reads the committer's kind from
|
|
199
|
-
* the conflict and maps the declared mode:
|
|
200
|
-
*
|
|
201
|
-
* - undefined → the engine default, {@link defaultPolicy}: a human is
|
|
202
|
-
* allowed, an agent or system committer is rejected on a
|
|
203
|
-
* `claim_held`, and a stale write honors `onStale: 'notify'`.
|
|
204
|
-
* - `overwrite` → `allow`; the write wins and the committer is never blocked.
|
|
205
|
-
* - `reject` → `reject`; the committer yields.
|
|
206
|
-
* - `notify` → on a `stale_context` conflict, hold the write and notify so
|
|
207
|
-
* the committer re-reads and re-applies; on a `claim_held`
|
|
208
|
-
* conflict there is no held write to reconcile (see
|
|
209
|
-
* {@link ConflictDecision} `notify`), so it degrades to
|
|
210
|
-
* `reject` rather than silently writing to a claimed row.
|
|
211
|
-
*
|
|
212
|
-
* This is only the generic interpretation. Stronger server-side rules — such as
|
|
213
|
-
* an agent never bypassing a claim held by someone else — are enforced where
|
|
214
|
-
* the decision is applied, not here.
|
|
215
|
-
*/
|
|
216
|
-
export declare function interpretConflictAxis(axis: ConflictAxis, conflict: Conflict): ConflictDecision;
|
|
217
|
-
export {};
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The conflict types a policy decides on. The engine detects a conflict and
|
|
3
|
-
* hands it to your {@link ConflictPolicy}, which returns a
|
|
4
|
-
* {@link ConflictDecision}.
|
|
5
|
-
*
|
|
6
|
-
* There are two conflict shapes. A {@link StaleContextConflict} is a write
|
|
7
|
-
* whose `readAt` watermark is older than the latest delta on the target row. A
|
|
8
|
-
* {@link ClaimHeldConflict} is a participant trying to claim a target that
|
|
9
|
-
* someone else already holds. {@link Conflict} is the discriminated union of
|
|
10
|
-
* the two; switch on `kind` to narrow it.
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* The conflict policy the engine uses when you do not supply your own. It
|
|
14
|
-
* favors people: a human is never blocked, while agents and automated writers
|
|
15
|
-
* yield to a claim someone else holds.
|
|
16
|
-
*
|
|
17
|
-
* For a `claim_held` conflict, the decision follows the committer's kind:
|
|
18
|
-
*
|
|
19
|
-
* • `user` → `allow` — a human is never blocked by a claim. A claim is a
|
|
20
|
-
* coordination hint among agents, not a lock on
|
|
21
|
-
* people.
|
|
22
|
-
* • `agent` → `reject` — an agent yields to a claim held by someone else.
|
|
23
|
-
* The one sanctioned exception is the privileged
|
|
24
|
-
* `claim.preempt` capability; see
|
|
25
|
-
* {@link capabilityPreemptPolicy}.
|
|
26
|
-
* • `system` → `reject` — automated and backend writers serialize through
|
|
27
|
-
* claims the same way agents do, so a server job
|
|
28
|
-
* cannot silently overwrite a held row. Declare the
|
|
29
|
-
* model's conflict axis to overwrite if you want that.
|
|
30
|
-
*
|
|
31
|
-
* Allowing only `user` by default is deliberate: a backend key is a
|
|
32
|
-
* full-access credential, and claim serialization depends on those writers
|
|
33
|
-
* respecting claims unless a model opts out.
|
|
34
|
-
*
|
|
35
|
-
* For a `stale_context` conflict, the decision honors the committer's declared
|
|
36
|
-
* `onStale` intent: `'notify'` holds the write and notifies the actor to
|
|
37
|
-
* resolve it, and anything else (including `'reject'` or an absent value)
|
|
38
|
-
* rejects. An `onStale` of `'overwrite'` never reaches a policy — it is a hard
|
|
39
|
-
* opt-out resolved before the conflict is detected.
|
|
40
|
-
*
|
|
41
|
-
* To change this behavior for a model, declare its conflict axis in the schema;
|
|
42
|
-
* a declared axis overrides this default.
|
|
43
|
-
*/
|
|
44
|
-
// Typed by its real synchronous shape with `satisfies`, rather than the
|
|
45
|
-
// async-permissive `ConflictPolicy` alias, so synchronous callers such as
|
|
46
|
-
// `interpretConflictAxis` and `capabilityPreemptPolicy` receive a plain
|
|
47
|
-
// `ConflictDecision` rather than `ConflictDecision | Promise<…>`. It remains
|
|
48
|
-
// assignable to `ConflictPolicy` wherever it is used as one.
|
|
49
|
-
export const defaultPolicy = ((conflict) => {
|
|
50
|
-
if (conflict.kind === 'claim_held') {
|
|
51
|
-
// A human (`user`) is never blocked; agents and system actors yield.
|
|
52
|
-
// Keeping every non-`user` kind on `reject` here ensures an agent cannot
|
|
53
|
-
// bypass a claim even on this default resolution path, which — unlike the
|
|
54
|
-
// declared-axis path — has no separate agent guard of its own.
|
|
55
|
-
return conflict.committer.kind === 'user'
|
|
56
|
-
? { action: 'allow', note: 'principal:not-blocked' }
|
|
57
|
-
: { action: 'reject', reason: 'claim_conflict' };
|
|
58
|
-
}
|
|
59
|
-
return conflict.requestedMode === 'notify'
|
|
60
|
-
? { action: 'notify', reason: 'stale_notify_hold' }
|
|
61
|
-
: { action: 'reject', reason: 'stale_context' };
|
|
62
|
-
});
|
|
63
|
-
/**
|
|
64
|
-
* A ready-made policy that grants capability-gated preemption. When the
|
|
65
|
-
* committer's capability allowlist includes the `claim.preempt` operation, a
|
|
66
|
-
* `claim_held` conflict is preempted: the current holder is evicted and the
|
|
67
|
-
* committer takes the lease. Every other conflict falls back to
|
|
68
|
-
* {@link defaultPolicy}, which rejects. Register it as your conflict policy to
|
|
69
|
-
* let a privileged identity take over a held entity without writing a bespoke
|
|
70
|
-
* policy. The authorization rests on holding the capability, not on any
|
|
71
|
-
* particular identity string.
|
|
72
|
-
*/
|
|
73
|
-
export const capabilityPreemptPolicy = (conflict) => {
|
|
74
|
-
if (conflict.kind === 'claim_held' &&
|
|
75
|
-
conflict.committerOperations.includes('claim.preempt')) {
|
|
76
|
-
return { action: 'preempt', reason: 'capability:claim.preempt' };
|
|
77
|
-
}
|
|
78
|
-
return defaultPolicy(conflict);
|
|
79
|
-
};
|
|
80
|
-
const _conflictAxisPinned = [true, true];
|
|
81
|
-
void _conflictAxisPinned;
|
|
82
|
-
/**
|
|
83
|
-
* Resolves a declared {@link ConflictAxis} into a {@link ConflictDecision} for
|
|
84
|
-
* one concrete conflict. It is pure and synchronous, doing no I/O, so it can
|
|
85
|
-
* run on either the client or the server. It reads the committer's kind from
|
|
86
|
-
* the conflict and maps the declared mode:
|
|
87
|
-
*
|
|
88
|
-
* - undefined → the engine default, {@link defaultPolicy}: a human is
|
|
89
|
-
* allowed, an agent or system committer is rejected on a
|
|
90
|
-
* `claim_held`, and a stale write honors `onStale: 'notify'`.
|
|
91
|
-
* - `overwrite` → `allow`; the write wins and the committer is never blocked.
|
|
92
|
-
* - `reject` → `reject`; the committer yields.
|
|
93
|
-
* - `notify` → on a `stale_context` conflict, hold the write and notify so
|
|
94
|
-
* the committer re-reads and re-applies; on a `claim_held`
|
|
95
|
-
* conflict there is no held write to reconcile (see
|
|
96
|
-
* {@link ConflictDecision} `notify`), so it degrades to
|
|
97
|
-
* `reject` rather than silently writing to a claimed row.
|
|
98
|
-
*
|
|
99
|
-
* This is only the generic interpretation. Stronger server-side rules — such as
|
|
100
|
-
* an agent never bypassing a claim held by someone else — are enforced where
|
|
101
|
-
* the decision is applied, not here.
|
|
102
|
-
*/
|
|
103
|
-
export function interpretConflictAxis(axis, conflict) {
|
|
104
|
-
const mode = axis[conflict.committer.kind];
|
|
105
|
-
if (mode === undefined)
|
|
106
|
-
return defaultPolicy(conflict);
|
|
107
|
-
switch (mode) {
|
|
108
|
-
case 'overwrite':
|
|
109
|
-
return { action: 'allow', note: 'conflict:overwrite' };
|
|
110
|
-
case 'reject':
|
|
111
|
-
return {
|
|
112
|
-
action: 'reject',
|
|
113
|
-
reason: conflict.kind === 'claim_held' ? 'claim_conflict' : 'stale_context',
|
|
114
|
-
};
|
|
115
|
-
case 'notify':
|
|
116
|
-
return conflict.kind === 'stale_context'
|
|
117
|
-
? { action: 'notify', reason: 'stale_notify_hold' }
|
|
118
|
-
: { action: 'reject', reason: 'claim_conflict' };
|
|
119
|
-
default: {
|
|
120
|
-
// Exhaustiveness backstop: a future `OnStaleMode` member surfaces as a
|
|
121
|
-
// localized compile error here, not a missing-return at the signature.
|
|
122
|
-
const _exhaustive = mode;
|
|
123
|
-
return _exhaustive;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The functional update — `ablo.<model>.update(id, current => next)`.
|
|
3
|
-
*
|
|
4
|
-
* This is the surface that just works under contention. You express only your
|
|
5
|
-
* intent — given the latest row, here is the next state — and the client does
|
|
6
|
-
* the rest: it reads the fresh row and its watermark, runs your updater, writes
|
|
7
|
-
* the result as a compare-and-swap against that watermark, and on any concurrent
|
|
8
|
-
* write it re-reads, recomputes, and retries. No claim, no identity, no transport
|
|
9
|
-
* awareness, and no `stale_context` or `claim_*` error codes ever reach the
|
|
10
|
-
* caller. The write either lands or, at the extreme, throws a single
|
|
11
|
-
* {@link AbloContentionError} once the reconcile budget is spent.
|
|
12
|
-
*
|
|
13
|
-
* Correctness comes from the `readAt` watermark plus `onStale: 'reject'`
|
|
14
|
-
* (optimistic concurrency, or compare-and-swap), not from participant identity.
|
|
15
|
-
* That is why it is immune to the shared-credential silent-overwrite hazard and
|
|
16
|
-
* behaves identically on both transports: the HTTP and WebSocket clients inject
|
|
17
|
-
* the same two functions ({@link ReconcileTransport}) into the shared loop below,
|
|
18
|
-
* so the guarantee cannot drift between them — only the mechanism differs.
|
|
19
|
-
*
|
|
20
|
-
* The mental model is React's `setState(prev => next)`: pass a function of the
|
|
21
|
-
* current state and the runtime owns reconciliation.
|
|
22
|
-
*/
|
|
23
|
-
import { AbloContentionError } from '../errors.js';
|
|
24
|
-
/**
|
|
25
|
-
* The functional form of an update: given the freshly-read row, return the
|
|
26
|
-
* fields to write. Return `null` or `undefined` to make no write — a no-op the
|
|
27
|
-
* caller chose after seeing the latest state (for example, "already done").
|
|
28
|
-
*/
|
|
29
|
-
export type ModelUpdater<T> = (current: T) => Partial<T> | null | undefined | Promise<Partial<T> | null | undefined>;
|
|
30
|
-
/** Tuning for the functional update's internal reconcile loop. */
|
|
31
|
-
export interface ContentionOptions {
|
|
32
|
-
/**
|
|
33
|
-
* Max reconcile rounds under contention before throwing
|
|
34
|
-
* {@link AbloContentionError}. Each round re-reads the latest row and re-runs
|
|
35
|
-
* your updater. Defaults to {@link DEFAULT_CONTENTION_RETRIES}.
|
|
36
|
-
*/
|
|
37
|
-
readonly retries?: number;
|
|
38
|
-
/** Abort the reconcile loop (e.g. the request was cancelled). */
|
|
39
|
-
readonly signal?: AbortSignal;
|
|
40
|
-
}
|
|
41
|
-
/** Reconcile rounds before a hot row is declared permanently contended. */
|
|
42
|
-
export declare const DEFAULT_CONTENTION_RETRIES = 16;
|
|
43
|
-
/**
|
|
44
|
-
* Reports whether a thrown error means "another writer moved the row — re-read
|
|
45
|
-
* and retry" rather than a genuine failure to surface. These are the
|
|
46
|
-
* optimistic-concurrency signals the functional update reconciles against:
|
|
47
|
-
* - `stale_context` — the `readAt` watermark was overtaken by a concurrent write
|
|
48
|
-
* - `claim_lost` — a holder preempted the write (for example a human under `humansOverwrite`)
|
|
49
|
-
* - `claim_queued` — a holder is actively editing the row right now
|
|
50
|
-
*/
|
|
51
|
-
export declare function isReconcilableConflict(err: unknown): boolean;
|
|
52
|
-
/**
|
|
53
|
-
* The transport-specific read and write that the shared loop drives. Each client
|
|
54
|
-
* injects its own pair — the one thing that differs between the HTTP and
|
|
55
|
-
* WebSocket transports.
|
|
56
|
-
*/
|
|
57
|
-
export interface ReconcileTransport<T, R> {
|
|
58
|
-
readonly model: string;
|
|
59
|
-
readonly id: string;
|
|
60
|
-
/** Read the latest row and its watermark from the authoritative store. */
|
|
61
|
-
readFresh: () => Promise<{
|
|
62
|
-
readonly data: T | null | undefined;
|
|
63
|
-
readonly stamp: number;
|
|
64
|
-
}>;
|
|
65
|
-
/**
|
|
66
|
-
* Write the computed patch as a compare-and-swap against `readAt`. It must
|
|
67
|
-
* throw a reconcilable conflict (`stale_context` or `claim_*`) when the
|
|
68
|
-
* watermark was overtaken — that rejection is what drives the next reconcile
|
|
69
|
-
* round.
|
|
70
|
-
*/
|
|
71
|
-
writeNext: (patch: Partial<T>, readAt: number) => Promise<R>;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Run the read-fresh → compute → compare-and-swap → reconcile loop. Shared by
|
|
75
|
-
* both transports so the guarantee is provably identical. Returns the write's
|
|
76
|
-
* result, or `undefined` when the updater opted out of writing.
|
|
77
|
-
*/
|
|
78
|
-
export declare function reconcileFunctionalUpdate<T, R>(updater: ModelUpdater<T>, options: ContentionOptions | undefined, transport: ReconcileTransport<T, R>): Promise<R | undefined>;
|
|
79
|
-
export { AbloContentionError };
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The functional update — `ablo.<model>.update(id, current => next)`.
|
|
3
|
-
*
|
|
4
|
-
* This is the surface that just works under contention. You express only your
|
|
5
|
-
* intent — given the latest row, here is the next state — and the client does
|
|
6
|
-
* the rest: it reads the fresh row and its watermark, runs your updater, writes
|
|
7
|
-
* the result as a compare-and-swap against that watermark, and on any concurrent
|
|
8
|
-
* write it re-reads, recomputes, and retries. No claim, no identity, no transport
|
|
9
|
-
* awareness, and no `stale_context` or `claim_*` error codes ever reach the
|
|
10
|
-
* caller. The write either lands or, at the extreme, throws a single
|
|
11
|
-
* {@link AbloContentionError} once the reconcile budget is spent.
|
|
12
|
-
*
|
|
13
|
-
* Correctness comes from the `readAt` watermark plus `onStale: 'reject'`
|
|
14
|
-
* (optimistic concurrency, or compare-and-swap), not from participant identity.
|
|
15
|
-
* That is why it is immune to the shared-credential silent-overwrite hazard and
|
|
16
|
-
* behaves identically on both transports: the HTTP and WebSocket clients inject
|
|
17
|
-
* the same two functions ({@link ReconcileTransport}) into the shared loop below,
|
|
18
|
-
* so the guarantee cannot drift between them — only the mechanism differs.
|
|
19
|
-
*
|
|
20
|
-
* The mental model is React's `setState(prev => next)`: pass a function of the
|
|
21
|
-
* current state and the runtime owns reconciliation.
|
|
22
|
-
*/
|
|
23
|
-
import { AbloError, AbloNotFoundError, AbloStaleContextError, AbloClaimedError, AbloContentionError, } from '../errors.js';
|
|
24
|
-
/** Reconcile rounds before a hot row is declared permanently contended. */
|
|
25
|
-
export const DEFAULT_CONTENTION_RETRIES = 16;
|
|
26
|
-
/**
|
|
27
|
-
* Reports whether a thrown error means "another writer moved the row — re-read
|
|
28
|
-
* and retry" rather than a genuine failure to surface. These are the
|
|
29
|
-
* optimistic-concurrency signals the functional update reconciles against:
|
|
30
|
-
* - `stale_context` — the `readAt` watermark was overtaken by a concurrent write
|
|
31
|
-
* - `claim_lost` — a holder preempted the write (for example a human under `humansOverwrite`)
|
|
32
|
-
* - `claim_queued` — a holder is actively editing the row right now
|
|
33
|
-
*/
|
|
34
|
-
export function isReconcilableConflict(err) {
|
|
35
|
-
if (err instanceof AbloStaleContextError)
|
|
36
|
-
return true;
|
|
37
|
-
if (err instanceof AbloClaimedError) {
|
|
38
|
-
return err.code === 'claim_lost' || err.code === 'claim_queued';
|
|
39
|
-
}
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
43
|
-
/**
|
|
44
|
-
* Jittered backoff so N reconcilers retrying at once don't lock-step straight
|
|
45
|
-
* back into the same collision. Bounded; grows mildly with the attempt.
|
|
46
|
-
*/
|
|
47
|
-
function backoffMs(attempt) {
|
|
48
|
-
return 60 + attempt * 40 + Math.floor(Math.random() * 60);
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Run the read-fresh → compute → compare-and-swap → reconcile loop. Shared by
|
|
52
|
-
* both transports so the guarantee is provably identical. Returns the write's
|
|
53
|
-
* result, or `undefined` when the updater opted out of writing.
|
|
54
|
-
*/
|
|
55
|
-
export async function reconcileFunctionalUpdate(updater, options, transport) {
|
|
56
|
-
const retries = options?.retries ?? DEFAULT_CONTENTION_RETRIES;
|
|
57
|
-
let lastConflict;
|
|
58
|
-
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
59
|
-
if (options?.signal?.aborted) {
|
|
60
|
-
throw new AbloError(`Update of ${transport.model}/${transport.id} was aborted before it landed.`, { code: 'update_aborted' });
|
|
61
|
-
}
|
|
62
|
-
const { data, stamp } = await transport.readFresh();
|
|
63
|
-
if (data == null) {
|
|
64
|
-
throw new AbloNotFoundError(`Cannot update ${transport.model}/${transport.id}: it does not exist (or is ` +
|
|
65
|
-
`outside this credential's scope).`, [transport.id]);
|
|
66
|
-
}
|
|
67
|
-
const patch = await updater(data);
|
|
68
|
-
if (patch == null)
|
|
69
|
-
return undefined; // updater opted out after reading fresh
|
|
70
|
-
try {
|
|
71
|
-
return await transport.writeNext(patch, stamp);
|
|
72
|
-
}
|
|
73
|
-
catch (err) {
|
|
74
|
-
if (!isReconcilableConflict(err))
|
|
75
|
-
throw err; // genuine failure — surface it
|
|
76
|
-
lastConflict = err;
|
|
77
|
-
if (attempt < retries)
|
|
78
|
-
await sleep(backoffMs(attempt));
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
throw new AbloContentionError(transport.model, transport.id, retries + 1, {
|
|
82
|
-
cause: lastConflict,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
// Re-exported so call sites import the loop and its terminal error from one
|
|
86
|
-
// place; the class itself lives with the rest of the error hierarchy.
|
|
87
|
-
export { AbloContentionError };
|