@abloatai/transaction 0.56.0 → 0.58.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/CONVENTIONS.md +54 -10
- package/README.md +3 -1
- package/dist/ai-sdk/modelTools.d.ts +3 -3
- package/dist/ai-sdk/modelTools.d.ts.map +1 -1
- package/dist/ai-sdk/modelTools.js +1 -1
- package/dist/ai-sdk/modelTools.js.map +1 -1
- package/dist/ai-sdk/updateTool.d.ts +5 -7
- package/dist/ai-sdk/updateTool.d.ts.map +1 -1
- package/dist/ai-sdk/updateTool.js +3 -5
- package/dist/ai-sdk/updateTool.js.map +1 -1
- package/dist/auth/capability.d.ts +5 -0
- package/dist/auth/capability.d.ts.map +1 -1
- package/dist/auth/capability.js +5 -0
- package/dist/auth/capability.js.map +1 -1
- package/dist/auth/capabilityLifecycle.d.ts +1 -1
- package/dist/auth/capabilityLifecycle.d.ts.map +1 -1
- package/dist/auth/credentialPolicy.d.ts +1 -1
- package/dist/auth/credentialPolicy.d.ts.map +1 -1
- package/dist/auth/identity.d.ts +3 -3
- package/dist/auth/identity.d.ts.map +1 -1
- package/dist/auth/identity.js +5 -5
- package/dist/auth/identity.js.map +1 -1
- package/dist/auth/index.d.ts +4 -208
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +4 -330
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/runtime.d.ts +218 -0
- package/dist/auth/runtime.d.ts.map +1 -0
- package/dist/auth/runtime.js +336 -0
- package/dist/auth/runtime.js.map +1 -0
- package/dist/auth/sessionMint.d.ts +1 -1
- package/dist/auth/sessionMint.d.ts.map +1 -1
- package/dist/auth/sessionMint.js +2 -1
- package/dist/auth/sessionMint.js.map +1 -1
- package/dist/branches.d.ts +25 -21
- package/dist/branches.d.ts.map +1 -1
- package/dist/branches.js +3 -0
- package/dist/branches.js.map +1 -1
- package/dist/{coordination/awaitClaimGrant.d.ts → claims/awaitGrant.d.ts} +1 -1
- package/dist/claims/awaitGrant.d.ts.map +1 -0
- package/dist/{coordination/awaitClaimGrant.js → claims/awaitGrant.js} +4 -4
- package/dist/claims/awaitGrant.js.map +1 -0
- package/dist/{wire/claims.d.ts → claims/contract.d.ts} +1 -1
- package/dist/claims/contract.d.ts.map +1 -0
- package/dist/{wire/claims.js → claims/contract.js} +2 -2
- package/dist/claims/contract.js.map +1 -0
- package/dist/{wire/claimEvent.d.ts → claims/eventContract.d.ts} +1 -1
- package/dist/claims/eventContract.d.ts.map +1 -0
- package/dist/{wire/claimEvent.js → claims/eventContract.js} +1 -1
- package/dist/claims/eventContract.js.map +1 -0
- package/dist/{coordination → claims}/events.d.ts +7 -11
- package/dist/claims/events.d.ts.map +1 -0
- package/dist/claims/events.js +8 -0
- package/dist/claims/events.js.map +1 -0
- package/dist/{coordination/claimHeartbeatLoop.d.ts → claims/heartbeat.d.ts} +1 -1
- package/dist/claims/heartbeat.d.ts.map +1 -0
- package/dist/{coordination/claimHeartbeatLoop.js → claims/heartbeat.js} +1 -1
- package/dist/claims/heartbeat.js.map +1 -0
- package/dist/claims/index.d.ts +17 -0
- package/dist/claims/index.d.ts.map +1 -0
- package/dist/claims/index.js +16 -0
- package/dist/claims/index.js.map +1 -0
- package/dist/claims/lifetime.d.ts +26 -0
- package/dist/claims/lifetime.d.ts.map +1 -0
- package/dist/claims/lifetime.js +62 -0
- package/dist/claims/lifetime.js.map +1 -0
- package/dist/{coordination → claims}/locator.d.ts +1 -1
- package/dist/claims/locator.d.ts.map +1 -0
- package/dist/{coordination → claims}/locator.js +2 -2
- package/dist/claims/locator.js.map +1 -0
- package/dist/{coordination/claimMeta.d.ts → claims/meta.d.ts} +1 -1
- package/dist/claims/meta.d.ts.map +1 -0
- package/dist/{coordination/claimMeta.js → claims/meta.js} +1 -1
- package/dist/claims/meta.js.map +1 -0
- package/dist/claims/routes.d.ts +59 -0
- package/dist/claims/routes.d.ts.map +1 -0
- package/dist/claims/routes.js +69 -0
- package/dist/claims/routes.js.map +1 -0
- package/dist/claims/targetConflict.d.ts.map +1 -0
- package/dist/claims/targetConflict.js.map +1 -0
- package/dist/{coordination → claims}/trace.d.ts +2 -2
- package/dist/claims/trace.d.ts.map +1 -0
- package/dist/{coordination → claims}/trace.js +5 -5
- package/dist/claims/trace.js.map +1 -0
- package/dist/{ablo.d.ts → client/ablo.d.ts} +6 -15
- package/dist/client/ablo.d.ts.map +1 -0
- package/dist/{ablo.js → client/ablo.js} +2 -2
- package/dist/client/ablo.js.map +1 -0
- package/dist/{transactionLayer.d.ts → client/contract.d.ts} +12 -14
- package/dist/client/contract.d.ts.map +1 -0
- package/dist/{transactionLayer.js → client/contract.js} +4 -5
- package/dist/client/contract.js.map +1 -0
- package/dist/{headlessClient.d.ts → client/headless.d.ts} +4 -4
- package/dist/client/headless.d.ts.map +1 -0
- package/dist/{headlessClient.js → client/headless.js} +8 -10
- package/dist/{headlessClient.js.map → client/headless.js.map} +1 -1
- package/dist/client/index.d.ts +11 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +11 -0
- package/dist/client/index.js.map +1 -0
- package/dist/{resources → client/resources}/functionalUpdate.d.ts +4 -4
- package/dist/client/resources/functionalUpdate.d.ts.map +1 -0
- package/dist/{resources → client/resources}/functionalUpdate.js +3 -3
- package/dist/client/resources/functionalUpdate.js.map +1 -0
- package/dist/{resources → client/resources}/httpResources.d.ts +92 -77
- package/dist/client/resources/httpResources.d.ts.map +1 -0
- package/dist/client/resources/httpResources.js +94 -0
- package/dist/client/resources/httpResources.js.map +1 -0
- package/dist/client/resources/modelCreate.d.ts +21 -0
- package/dist/client/resources/modelCreate.d.ts.map +1 -0
- package/dist/client/resources/modelCreate.js +49 -0
- package/dist/client/resources/modelCreate.js.map +1 -0
- package/dist/{resources → client/resources}/modelOperations.d.ts +57 -51
- package/dist/client/resources/modelOperations.d.ts.map +1 -0
- package/dist/{resources → client/resources}/modelOperations.js +1 -1
- package/dist/client/resources/modelOperations.js.map +1 -0
- package/dist/{resources → client/resources}/mutationOptions.d.ts +4 -17
- package/dist/client/resources/mutationOptions.d.ts.map +1 -0
- package/dist/client/resources/mutationOptions.js.map +1 -0
- package/dist/client/resources/where.d.ts.map +1 -0
- package/dist/{resources → client/resources}/where.js +1 -1
- package/dist/client/resources/where.js.map +1 -0
- package/dist/{resources → client/resources}/writeOptionsSchema.d.ts +16 -35
- package/dist/client/resources/writeOptionsSchema.d.ts.map +1 -0
- package/dist/{resources → client/resources}/writeOptionsSchema.js +25 -18
- package/dist/client/resources/writeOptionsSchema.js.map +1 -0
- package/dist/{transactions → commit}/confirmation/commitEnvelope.d.ts +1 -37
- package/dist/commit/confirmation/commitEnvelope.d.ts.map +1 -0
- package/dist/{transactions → commit}/confirmation/commitEnvelope.js +2 -7
- package/dist/commit/confirmation/commitEnvelope.js.map +1 -0
- package/dist/commit/confirmation/httpCommitEnvelope.d.ts.map +1 -0
- package/dist/{transactions → commit}/confirmation/httpCommitEnvelope.js +1 -1
- package/dist/commit/confirmation/httpCommitEnvelope.js.map +1 -0
- package/dist/commit/confirmation/idempotencyKey.d.ts.map +1 -0
- package/dist/commit/confirmation/idempotencyKey.js.map +1 -0
- package/dist/{transactions → commit}/confirmation/pendingWrite.d.ts +2 -33
- package/dist/commit/confirmation/pendingWrite.d.ts.map +1 -0
- package/dist/{transactions → commit}/confirmation/pendingWrite.js +1 -1
- package/dist/commit/confirmation/pendingWrite.js.map +1 -0
- package/dist/commit/contract.d.ts +1404 -0
- package/dist/commit/contract.d.ts.map +1 -0
- package/dist/{wire/commit.js → commit/contract.js} +26 -21
- package/dist/commit/contract.js.map +1 -0
- package/dist/{durableWrites.d.ts → commit/durableWrites.d.ts} +6 -6
- package/dist/commit/durableWrites.d.ts.map +1 -0
- package/dist/{durableWrites.js → commit/durableWrites.js} +5 -5
- package/dist/commit/durableWrites.js.map +1 -0
- package/dist/commit/httpRequest.d.ts +45 -0
- package/dist/commit/httpRequest.d.ts.map +1 -0
- package/dist/commit/httpRequest.js +66 -0
- package/dist/commit/httpRequest.js.map +1 -0
- package/dist/commit/index.d.ts +17 -0
- package/dist/commit/index.d.ts.map +1 -0
- package/dist/commit/index.js +17 -0
- package/dist/commit/index.js.map +1 -0
- package/dist/{readSetContext.d.ts → commit/readSetContext.d.ts} +7 -15
- package/dist/commit/readSetContext.d.ts.map +1 -0
- package/dist/{readSetContext.js → commit/readSetContext.js} +18 -28
- package/dist/commit/readSetContext.js.map +1 -0
- package/dist/{commitRecordRuntime.d.ts → commit/recordRuntime.d.ts} +3 -5
- package/dist/commit/recordRuntime.d.ts.map +1 -0
- package/dist/{commitRecordRuntime.js → commit/recordRuntime.js} +13 -54
- package/dist/commit/recordRuntime.js.map +1 -0
- package/dist/coordination/index.d.ts +6 -8
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +3 -9
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/schema.d.ts +11 -466
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +13 -265
- package/dist/coordination/schema.js.map +1 -1
- package/dist/errorCodes.d.ts +16 -9
- package/dist/errorCodes.d.ts.map +1 -1
- package/dist/errorCodes.js +14 -6
- package/dist/errorCodes.js.map +1 -1
- package/dist/errorObservation.d.ts +2 -2
- package/dist/errors.d.ts +3 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +27 -11
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/internal/read-set.d.ts +3 -3
- package/dist/internal/read-set.d.ts.map +1 -1
- package/dist/internal/read-set.js +2 -2
- package/dist/internal/read-set.js.map +1 -1
- package/dist/observability.d.ts +4 -4
- package/dist/observability.d.ts.map +1 -1
- package/dist/observability.js +2 -2
- package/dist/{wire/delta.d.ts → observation/contract.d.ts} +8 -8
- package/dist/observation/contract.d.ts.map +1 -0
- package/dist/{wire/delta.js → observation/contract.js} +3 -3
- package/dist/observation/contract.js.map +1 -0
- package/dist/{wire/feedCursor.d.ts → observation/cursor.d.ts} +1 -1
- package/dist/observation/cursor.d.ts.map +1 -0
- package/dist/{wire/feedCursor.js → observation/cursor.js} +1 -1
- package/dist/observation/cursor.js.map +1 -0
- package/dist/{wire/deltaDelivery.d.ts → observation/deliveryContract.d.ts} +1 -1
- package/dist/observation/deliveryContract.d.ts.map +1 -0
- package/dist/{wire/deltaDelivery.js → observation/deliveryContract.js} +1 -1
- package/dist/observation/deliveryContract.js.map +1 -0
- package/dist/{wire/feedEvent.d.ts → observation/feedContract.d.ts} +10 -10
- package/dist/observation/feedContract.d.ts.map +1 -0
- package/dist/{wire/feedEvent.js → observation/feedContract.js} +4 -4
- package/dist/observation/feedContract.js.map +1 -0
- package/dist/observation/httpFeed.d.ts +4 -0
- package/dist/observation/httpFeed.d.ts.map +1 -0
- package/dist/{transport → observation}/httpFeed.js +1 -1
- package/dist/{transport → observation}/httpFeed.js.map +1 -1
- package/dist/observation/index.d.ts +13 -0
- package/dist/observation/index.d.ts.map +1 -0
- package/dist/observation/index.js +13 -0
- package/dist/observation/index.js.map +1 -0
- package/dist/{log → observation/persistence}/syncDeltaRow.d.ts +8 -8
- package/dist/observation/persistence/syncDeltaRow.d.ts.map +1 -0
- package/dist/{log → observation/persistence}/syncDeltaRow.js +4 -4
- package/dist/observation/persistence/syncDeltaRow.js.map +1 -0
- package/dist/pricing.d.ts +20 -12
- package/dist/pricing.d.ts.map +1 -1
- package/dist/pricing.js +46 -26
- package/dist/pricing.js.map +1 -1
- package/dist/schema/audit.d.ts +15 -0
- package/dist/schema/audit.d.ts.map +1 -0
- package/dist/schema/audit.js +90 -0
- package/dist/schema/audit.js.map +1 -0
- package/dist/schema/ddl.d.ts.map +1 -1
- package/dist/schema/ddl.js +68 -1
- package/dist/schema/ddl.js.map +1 -1
- package/dist/schema/index.d.ts +7 -6
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +6 -7
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/model.d.ts +14 -27
- package/dist/schema/model.d.ts.map +1 -1
- package/dist/schema/model.js +2 -2
- package/dist/schema/model.js.map +1 -1
- package/dist/schema/openapi.d.ts.map +1 -1
- package/dist/schema/openapi.js +149 -8
- package/dist/schema/openapi.js.map +1 -1
- package/dist/schema/roles.d.ts +27 -0
- package/dist/schema/roles.d.ts.map +1 -1
- package/dist/schema/roles.js +40 -0
- package/dist/schema/roles.js.map +1 -1
- package/dist/schema/schema.d.ts +34 -7
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +39 -3
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/serialize.d.ts +5 -5
- package/dist/schema/serialize.d.ts.map +1 -1
- package/dist/schema/serialize.js +5 -5
- package/dist/schema/serialize.js.map +1 -1
- package/dist/schema/subject.d.ts +18 -0
- package/dist/schema/subject.d.ts.map +1 -0
- package/dist/schema/subject.js +27 -0
- package/dist/schema/subject.js.map +1 -0
- package/dist/schema/tenancy.d.ts +1 -1
- package/dist/server/adapter.d.ts +3 -1
- package/dist/server/adapter.d.ts.map +1 -1
- package/dist/server/commit.d.ts +6 -14
- package/dist/server/commit.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/readConfig.d.ts +3 -0
- package/dist/server/readConfig.d.ts.map +1 -1
- package/dist/server/readConfig.js +0 -21
- package/dist/server/readConfig.js.map +1 -1
- package/dist/server/storageMode.d.ts +1 -1
- package/dist/source/{adapter.d.ts → adapters/adapter.d.ts} +10 -4
- package/dist/source/adapters/adapter.d.ts.map +1 -0
- package/dist/source/adapters/adapter.js.map +1 -0
- package/dist/source/adapters/adapterFactory.d.ts.map +1 -0
- package/dist/source/{adapterFactory.js → adapters/adapterFactory.js} +1 -1
- package/dist/source/adapters/adapterFactory.js.map +1 -0
- package/dist/source/adapters/adapterProfile.d.ts.map +1 -0
- package/dist/source/adapters/adapterProfile.js.map +1 -0
- package/dist/source/{conformance.d.ts → adapters/conformance.d.ts} +1 -1
- package/dist/source/adapters/conformance.d.ts.map +1 -0
- package/dist/source/{conformance.js → adapters/conformance.js} +1 -1
- package/dist/source/adapters/conformance.js.map +1 -0
- package/dist/source/{contract.d.ts → adapters/contract.d.ts} +20 -75
- package/dist/source/adapters/contract.d.ts.map +1 -0
- package/dist/source/{contract.js → adapters/contract.js} +20 -55
- package/dist/source/adapters/contract.js.map +1 -0
- package/dist/source/adapters/drizzle.d.ts +1 -1
- package/dist/source/adapters/drizzle.d.ts.map +1 -1
- package/dist/source/adapters/drizzle.js +54 -25
- package/dist/source/adapters/drizzle.js.map +1 -1
- package/dist/source/adapters/idempotency.d.ts.map +1 -0
- package/dist/source/{idempotency.js → adapters/idempotency.js} +2 -2
- package/dist/source/adapters/idempotency.js.map +1 -0
- package/dist/source/adapters/index.d.ts +21 -0
- package/dist/source/adapters/index.d.ts.map +1 -0
- package/dist/source/adapters/index.js +21 -0
- package/dist/source/adapters/index.js.map +1 -0
- package/dist/source/adapters/kysely.d.ts +3 -1
- package/dist/source/adapters/kysely.d.ts.map +1 -1
- package/dist/source/adapters/kysely.js +49 -23
- package/dist/source/adapters/kysely.js.map +1 -1
- package/dist/source/adapters/kyselyMutationCore.d.ts +6 -3
- package/dist/source/adapters/kyselyMutationCore.d.ts.map +1 -1
- package/dist/source/adapters/kyselyMutationCore.js +17 -8
- package/dist/source/adapters/kyselyMutationCore.js.map +1 -1
- package/dist/source/adapters/memory.d.ts +3 -3
- package/dist/source/adapters/memory.d.ts.map +1 -1
- package/dist/source/adapters/memory.js +20 -7
- package/dist/source/adapters/memory.js.map +1 -1
- package/dist/source/adapters/migration.d.ts +8 -0
- package/dist/source/adapters/migration.d.ts.map +1 -0
- package/dist/source/adapters/migration.js +9 -0
- package/dist/source/adapters/migration.js.map +1 -0
- package/dist/source/{migrations.d.ts → adapters/migrations.d.ts} +3 -4
- package/dist/source/adapters/migrations.d.ts.map +1 -0
- package/dist/source/{migrations.js → adapters/migrations.js} +4 -31
- package/dist/source/adapters/migrations.js.map +1 -0
- package/dist/source/adapters/prisma.d.ts +1 -1
- package/dist/source/adapters/prisma.d.ts.map +1 -1
- package/dist/source/adapters/prisma.js +75 -30
- package/dist/source/adapters/prisma.js.map +1 -1
- package/dist/source/adapters/subjectAuthorization.d.ts +16 -0
- package/dist/source/adapters/subjectAuthorization.d.ts.map +1 -0
- package/dist/source/adapters/subjectAuthorization.js +126 -0
- package/dist/source/adapters/subjectAuthorization.js.map +1 -0
- package/dist/source/{connector.d.ts → connector/client.d.ts} +6 -1
- package/dist/source/connector/client.d.ts.map +1 -0
- package/dist/source/{connector.js → connector/client.js} +28 -11
- package/dist/source/connector/client.js.map +1 -0
- package/dist/source/connector/index.d.ts +4 -0
- package/dist/source/connector/index.d.ts.map +1 -0
- package/dist/source/connector/index.js +4 -0
- package/dist/source/connector/index.js.map +1 -0
- package/dist/source/{connectorProtocol.d.ts → connector/protocol.d.ts} +8 -1
- package/dist/source/connector/protocol.d.ts.map +1 -0
- package/dist/source/{connectorProtocol.js → connector/protocol.js} +10 -3
- package/dist/source/connector/protocol.js.map +1 -0
- package/dist/source/delivery/index.d.ts +3 -0
- package/dist/source/delivery/index.d.ts.map +1 -0
- package/dist/source/delivery/index.js +3 -0
- package/dist/source/delivery/index.js.map +1 -0
- package/dist/source/{pushQueue.d.ts → delivery/pushQueue.d.ts} +1 -1
- package/dist/source/delivery/pushQueue.d.ts.map +1 -0
- package/dist/source/{pushQueue.js → delivery/pushQueue.js} +1 -1
- package/dist/source/delivery/pushQueue.js.map +1 -0
- package/dist/source/{factory.d.ts → endpoint/factory.d.ts} +9 -3
- package/dist/source/endpoint/factory.d.ts.map +1 -0
- package/dist/source/{factory.js → endpoint/factory.js} +122 -6
- package/dist/source/endpoint/factory.js.map +1 -0
- package/dist/source/endpoint/index.d.ts +5 -0
- package/dist/source/endpoint/index.d.ts.map +1 -0
- package/dist/source/endpoint/index.js +5 -0
- package/dist/source/endpoint/index.js.map +1 -0
- package/dist/source/{next.d.ts → endpoint/next.d.ts} +2 -2
- package/dist/source/endpoint/next.d.ts.map +1 -0
- package/dist/source/{next.js → endpoint/next.js} +1 -1
- package/dist/source/endpoint/next.js.map +1 -0
- package/dist/source/{signing.d.ts → endpoint/signing.d.ts} +1 -1
- package/dist/source/endpoint/signing.d.ts.map +1 -0
- package/dist/source/{signing.js → endpoint/signing.js} +1 -1
- package/dist/source/endpoint/signing.js.map +1 -0
- package/dist/source/index.d.ts +15 -12
- package/dist/source/index.d.ts.map +1 -1
- package/dist/source/index.js +13 -10
- package/dist/source/index.js.map +1 -1
- package/dist/source/outbox/contract.d.ts +50 -0
- package/dist/source/outbox/contract.d.ts.map +1 -0
- package/dist/source/outbox/contract.js +50 -0
- package/dist/source/outbox/contract.js.map +1 -0
- package/dist/source/outbox/envelope.d.ts +9 -0
- package/dist/source/outbox/envelope.d.ts.map +1 -0
- package/dist/source/outbox/envelope.js +36 -0
- package/dist/source/outbox/envelope.js.map +1 -0
- package/dist/source/outbox/index.d.ts +11 -0
- package/dist/source/outbox/index.d.ts.map +1 -0
- package/dist/source/outbox/index.js +11 -0
- package/dist/source/outbox/index.js.map +1 -0
- package/dist/source/outbox/migrations.d.ts +4 -0
- package/dist/source/outbox/migrations.d.ts.map +1 -0
- package/dist/source/outbox/migrations.js +67 -0
- package/dist/source/outbox/migrations.js.map +1 -0
- package/dist/source/outbox/retention.d.ts +3 -0
- package/dist/source/outbox/retention.d.ts.map +1 -0
- package/dist/source/outbox/retention.js +3 -0
- package/dist/source/outbox/retention.js.map +1 -0
- package/dist/source/types.d.ts +59 -10
- package/dist/source/types.d.ts.map +1 -1
- package/dist/source/types.js +2 -0
- package/dist/source/types.js.map +1 -1
- package/dist/syncLog/contract.d.ts +19 -8
- package/dist/syncLog/contract.d.ts.map +1 -1
- package/dist/syncLog/contract.js +19 -6
- package/dist/syncLog/contract.js.map +1 -1
- package/dist/testing/fixtures/httpResponses.d.ts +6 -0
- package/dist/testing/fixtures/httpResponses.d.ts.map +1 -1
- package/dist/testing/fixtures/httpResponses.js +1 -0
- package/dist/testing/fixtures/httpResponses.js.map +1 -1
- package/dist/transport/{credentialLifecycle.d.ts → connection/credentialLifecycle.d.ts} +3 -3
- package/dist/transport/connection/credentialLifecycle.d.ts.map +1 -0
- package/dist/transport/{credentialLifecycle.js → connection/credentialLifecycle.js} +2 -2
- package/dist/transport/connection/credentialLifecycle.js.map +1 -0
- package/dist/transport/connection/index.d.ts +5 -0
- package/dist/transport/connection/index.d.ts.map +1 -0
- package/dist/transport/connection/index.js +5 -0
- package/dist/transport/connection/index.js.map +1 -0
- package/dist/transport/{connectionManager.d.ts → connection/manager.d.ts} +13 -5
- package/dist/transport/connection/manager.d.ts.map +1 -0
- package/dist/transport/{connectionManager.js → connection/manager.js} +6 -4
- package/dist/transport/connection/manager.js.map +1 -0
- package/dist/transport/{networkProbe.d.ts → connection/networkProbe.d.ts} +2 -2
- package/dist/transport/connection/networkProbe.d.ts.map +1 -0
- package/dist/transport/{networkProbe.js → connection/networkProbe.js} +4 -4
- package/dist/transport/connection/networkProbe.js.map +1 -0
- package/dist/transport/{httpClient.d.ts → http/client.d.ts} +32 -44
- package/dist/transport/http/client.d.ts.map +1 -0
- package/dist/transport/{httpClient.js → http/client.js} +96 -105
- package/dist/transport/http/client.js.map +1 -0
- package/dist/transport/http/helpers.d.ts +10 -0
- package/dist/transport/http/helpers.d.ts.map +1 -0
- package/dist/transport/http/helpers.js +46 -0
- package/dist/transport/http/helpers.js.map +1 -0
- package/dist/transport/http/index.d.ts +6 -0
- package/dist/transport/http/index.d.ts.map +1 -0
- package/dist/transport/http/index.js +6 -0
- package/dist/transport/http/index.js.map +1 -0
- package/dist/transport/{httpOptions.d.ts → http/options.d.ts} +7 -7
- package/dist/transport/{httpOptions.d.ts.map → http/options.d.ts.map} +1 -1
- package/dist/transport/{httpOptions.js → http/options.js} +1 -1
- package/dist/transport/http/options.js.map +1 -0
- package/dist/transport/http/subscription.d.ts +16 -0
- package/dist/transport/http/subscription.d.ts.map +1 -0
- package/dist/transport/http/subscription.js +146 -0
- package/dist/transport/http/subscription.js.map +1 -0
- package/dist/transport/{httpTransport.d.ts → http/transport.d.ts} +9 -6
- package/dist/transport/http/transport.d.ts.map +1 -0
- package/dist/transport/{httpTransport.js → http/transport.js} +153 -188
- package/dist/transport/http/transport.js.map +1 -0
- package/dist/transport/index.d.ts +8 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +8 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/{commitFrames.d.ts → websocket/commitFrames.d.ts} +8 -20
- package/dist/transport/websocket/commitFrames.d.ts.map +1 -0
- package/dist/transport/{commitFrames.js → websocket/commitFrames.js} +6 -25
- package/dist/transport/websocket/commitFrames.js.map +1 -0
- package/dist/transport/{wsFrameHandlers.d.ts → websocket/frameHandlers.d.ts} +5 -5
- package/dist/transport/websocket/frameHandlers.d.ts.map +1 -0
- package/dist/transport/{wsFrameHandlers.js → websocket/frameHandlers.js} +10 -51
- package/dist/transport/websocket/frameHandlers.js.map +1 -0
- package/dist/transport/{heartbeat.d.ts → websocket/heartbeat.d.ts} +1 -1
- package/dist/transport/websocket/heartbeat.d.ts.map +1 -0
- package/dist/transport/{heartbeat.js → websocket/heartbeat.js} +2 -2
- package/dist/transport/websocket/heartbeat.js.map +1 -0
- package/dist/transport/websocket/index.d.ts +6 -0
- package/dist/transport/websocket/index.d.ts.map +1 -0
- package/dist/transport/websocket/index.js +6 -0
- package/dist/transport/websocket/index.js.map +1 -0
- package/dist/transport/{wsTransport.d.ts → websocket/transport.d.ts} +13 -25
- package/dist/transport/websocket/transport.d.ts.map +1 -0
- package/dist/transport/{wsTransport.js → websocket/transport.js} +14 -14
- package/dist/transport/websocket/transport.js.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/streams.d.ts +8 -48
- package/dist/types/streams.d.ts.map +1 -1
- package/dist/types/streams.js +2 -2
- package/dist/wire/accountResponses.d.ts +4 -72
- package/dist/wire/accountResponses.d.ts.map +1 -1
- package/dist/wire/accountResponses.js +2 -10
- package/dist/wire/accountResponses.js.map +1 -1
- package/dist/wire/apiLifecycle.d.ts +63 -0
- package/dist/wire/apiLifecycle.d.ts.map +1 -0
- package/dist/wire/apiLifecycle.js +89 -0
- package/dist/wire/apiLifecycle.js.map +1 -0
- package/dist/wire/frames.d.ts +6 -83
- package/dist/wire/frames.d.ts.map +1 -1
- package/dist/wire/frames.js +4 -11
- package/dist/wire/frames.js.map +1 -1
- package/dist/wire/inboundFrames.d.ts +6 -131
- package/dist/wire/inboundFrames.d.ts.map +1 -1
- package/dist/wire/inboundFrames.js +3 -3
- package/dist/wire/inboundFrames.js.map +1 -1
- package/dist/wire/index.d.ts +20 -15
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +22 -8
- package/dist/wire/index.js.map +1 -1
- package/dist/wire/modelMutations.d.ts +1 -32
- package/dist/wire/modelMutations.d.ts.map +1 -1
- package/dist/wire/modelMutations.js +1 -8
- package/dist/wire/modelMutations.js.map +1 -1
- package/dist/wire/rateLimit.d.ts +82 -0
- package/dist/wire/rateLimit.d.ts.map +1 -0
- package/dist/wire/rateLimit.js +142 -0
- package/dist/wire/rateLimit.js.map +1 -0
- package/package.json +130 -10
- package/src/ai-sdk/modelTools.ts +5 -5
- package/src/ai-sdk/updateTool.ts +5 -7
- package/src/auth/capability.ts +5 -0
- package/src/auth/capabilityLifecycle.ts +1 -1
- package/src/auth/credentialPolicy.ts +1 -1
- package/src/auth/identity.ts +7 -7
- package/src/auth/index.ts +4 -663
- package/src/auth/runtime.ts +669 -0
- package/src/auth/sessionMint.ts +3 -2
- package/src/branches.ts +3 -0
- package/src/{coordination/awaitClaimGrant.ts → claims/awaitGrant.ts} +4 -4
- package/src/{wire/claims.ts → claims/contract.ts} +1 -1
- package/src/{coordination → claims}/events.ts +7 -11
- package/src/claims/index.ts +21 -0
- package/src/claims/lifetime.ts +78 -0
- package/src/{coordination → claims}/locator.ts +3 -3
- package/src/claims/routes.ts +81 -0
- package/src/{coordination → claims}/trace.ts +5 -5
- package/src/{ablo.ts → client/ablo.ts} +8 -20
- package/src/{transactionLayer.ts → client/contract.ts} +11 -13
- package/src/{headlessClient.ts → client/headless.ts} +13 -15
- package/src/client/index.ts +10 -0
- package/src/{resources → client/resources}/functionalUpdate.ts +4 -4
- package/src/{resources → client/resources}/httpResources.ts +163 -92
- package/src/client/resources/modelCreate.ts +73 -0
- package/src/{resources → client/resources}/modelOperations.ts +73 -55
- package/src/{resources → client/resources}/mutationOptions.ts +4 -17
- package/src/{resources → client/resources}/where.ts +1 -1
- package/src/{resources → client/resources}/writeOptionsSchema.ts +35 -27
- package/src/{transactions → commit}/confirmation/commitEnvelope.ts +2 -12
- package/src/{transactions → commit}/confirmation/httpCommitEnvelope.ts +1 -1
- package/src/{transactions → commit}/confirmation/pendingWrite.ts +1 -1
- package/src/{wire/commit.ts → commit/contract.ts} +27 -26
- package/src/{durableWrites.ts → commit/durableWrites.ts} +7 -7
- package/src/commit/httpRequest.ts +103 -0
- package/src/commit/index.ts +16 -0
- package/src/{readSetContext.ts → commit/readSetContext.ts} +24 -43
- package/src/{commitRecordRuntime.ts → commit/recordRuntime.ts} +12 -67
- package/src/coordination/index.ts +4 -54
- package/src/coordination/schema.ts +15 -309
- package/src/errorCodes.ts +62 -10
- package/src/errors.ts +32 -10
- package/src/index.ts +8 -8
- package/src/internal/read-set.ts +3 -6
- package/src/observability.ts +4 -4
- package/src/{wire/delta.ts → observation/contract.ts} +2 -2
- package/src/{wire/feedEvent.ts → observation/feedContract.ts} +3 -4
- package/src/{transport → observation}/httpFeed.ts +3 -3
- package/src/observation/index.ts +12 -0
- package/src/{log → observation/persistence}/syncDeltaRow.ts +6 -7
- package/src/pricing.ts +46 -25
- package/src/schema/audit.ts +121 -0
- package/src/schema/ddl.ts +71 -1
- package/src/schema/index.ts +20 -20
- package/src/schema/model.ts +17 -33
- package/src/schema/openapi.ts +170 -9
- package/src/schema/roles.ts +53 -0
- package/src/schema/schema.ts +91 -6
- package/src/schema/serialize.ts +8 -9
- package/src/schema/subject.ts +43 -0
- package/src/server/adapter.ts +3 -1
- package/src/server/commit.ts +6 -14
- package/src/server/index.ts +1 -1
- package/src/server/readConfig.ts +4 -0
- package/src/source/{adapter.ts → adapters/adapter.ts} +9 -5
- package/src/source/{adapterFactory.ts → adapters/adapterFactory.ts} +1 -1
- package/src/source/{conformance.ts → adapters/conformance.ts} +1 -1
- package/src/source/{contract.ts → adapters/contract.ts} +24 -61
- package/src/source/adapters/drizzle.ts +75 -29
- package/src/source/{idempotency.ts → adapters/idempotency.ts} +2 -2
- package/src/source/adapters/index.ts +20 -0
- package/src/source/adapters/kysely.ts +77 -27
- package/src/source/adapters/kyselyMutationCore.ts +23 -11
- package/src/source/adapters/memory.ts +26 -9
- package/src/source/adapters/migration.ts +11 -0
- package/src/source/{migrations.ts → adapters/migrations.ts} +6 -33
- package/src/source/adapters/prisma.ts +98 -34
- package/src/source/adapters/subjectAuthorization.ts +182 -0
- package/src/source/{connector.ts → connector/client.ts} +35 -12
- package/src/source/connector/index.ts +3 -0
- package/src/source/{connectorProtocol.ts → connector/protocol.ts} +10 -2
- package/src/source/delivery/index.ts +2 -0
- package/src/source/{pushQueue.ts → delivery/pushQueue.ts} +2 -2
- package/src/source/{factory.ts → endpoint/factory.ts} +150 -9
- package/src/source/endpoint/index.ts +4 -0
- package/src/source/{next.ts → endpoint/next.ts} +2 -2
- package/src/source/{signing.ts → endpoint/signing.ts} +1 -1
- package/src/source/index.ts +27 -18
- package/src/source/outbox/contract.ts +56 -0
- package/src/source/outbox/envelope.ts +47 -0
- package/src/source/outbox/index.ts +15 -0
- package/src/source/outbox/migrations.ts +71 -0
- package/src/source/outbox/retention.ts +2 -0
- package/src/source/types.ts +64 -10
- package/src/syncLog/contract.ts +19 -9
- package/src/testing/fixtures/httpResponses.ts +7 -0
- package/src/transport/{credentialLifecycle.ts → connection/credentialLifecycle.ts} +3 -3
- package/src/transport/connection/index.ts +4 -0
- package/src/transport/{connectionManager.ts → connection/manager.ts} +13 -4
- package/src/transport/{networkProbe.ts → connection/networkProbe.ts} +4 -4
- package/src/transport/{httpClient.ts → http/client.ts} +165 -184
- package/src/transport/http/helpers.ts +63 -0
- package/src/transport/http/index.ts +5 -0
- package/src/transport/{httpOptions.ts → http/options.ts} +6 -6
- package/src/transport/http/subscription.ts +174 -0
- package/src/transport/{httpTransport.ts → http/transport.ts} +210 -246
- package/src/transport/index.ts +7 -0
- package/src/transport/{commitFrames.ts → websocket/commitFrames.ts} +14 -46
- package/src/transport/{wsFrameHandlers.ts → websocket/frameHandlers.ts} +11 -54
- package/src/transport/{heartbeat.ts → websocket/heartbeat.ts} +2 -2
- package/src/transport/websocket/index.ts +5 -0
- package/src/transport/{wsTransport.ts → websocket/transport.ts} +16 -30
- package/src/types/index.ts +2 -6
- package/src/types/streams.ts +7 -61
- package/src/webhooks/events.ts +1 -1
- package/src/wire/accountResponses.ts +3 -12
- package/src/wire/apiLifecycle.ts +94 -0
- package/src/wire/frames.ts +5 -15
- package/src/wire/inboundFrames.ts +3 -3
- package/src/wire/index.ts +50 -15
- package/src/wire/modelMutations.ts +1 -14
- package/src/wire/rateLimit.ts +155 -0
- package/dist/ablo.d.ts.map +0 -1
- package/dist/ablo.js.map +0 -1
- package/dist/commitRecordRuntime.d.ts.map +0 -1
- package/dist/commitRecordRuntime.js.map +0 -1
- package/dist/coordination/awaitClaimGrant.d.ts.map +0 -1
- package/dist/coordination/awaitClaimGrant.js.map +0 -1
- package/dist/coordination/claimHeartbeatLoop.d.ts.map +0 -1
- package/dist/coordination/claimHeartbeatLoop.js.map +0 -1
- package/dist/coordination/claimMeta.d.ts.map +0 -1
- package/dist/coordination/claimMeta.js.map +0 -1
- package/dist/coordination/events.d.ts.map +0 -1
- package/dist/coordination/events.js +0 -8
- package/dist/coordination/events.js.map +0 -1
- package/dist/coordination/locator.d.ts.map +0 -1
- package/dist/coordination/locator.js.map +0 -1
- package/dist/coordination/targetConflict.d.ts.map +0 -1
- package/dist/coordination/targetConflict.js.map +0 -1
- package/dist/coordination/trace.d.ts.map +0 -1
- package/dist/coordination/trace.js.map +0 -1
- package/dist/durableWrites.d.ts.map +0 -1
- package/dist/durableWrites.js.map +0 -1
- package/dist/headlessClient.d.ts.map +0 -1
- package/dist/log/syncDeltaRow.d.ts.map +0 -1
- package/dist/log/syncDeltaRow.js.map +0 -1
- package/dist/policy/types.d.ts +0 -226
- package/dist/policy/types.d.ts.map +0 -1
- package/dist/policy/types.js +0 -127
- package/dist/policy/types.js.map +0 -1
- package/dist/readSetContext.d.ts.map +0 -1
- package/dist/readSetContext.js.map +0 -1
- package/dist/resources/functionalUpdate.d.ts.map +0 -1
- package/dist/resources/functionalUpdate.js.map +0 -1
- package/dist/resources/httpResources.d.ts.map +0 -1
- package/dist/resources/httpResources.js +0 -17
- package/dist/resources/httpResources.js.map +0 -1
- package/dist/resources/modelOperations.d.ts.map +0 -1
- package/dist/resources/modelOperations.js.map +0 -1
- package/dist/resources/mutationOptions.d.ts.map +0 -1
- package/dist/resources/mutationOptions.js.map +0 -1
- package/dist/resources/where.d.ts.map +0 -1
- package/dist/resources/where.js.map +0 -1
- package/dist/resources/writeOptionsSchema.d.ts.map +0 -1
- package/dist/resources/writeOptionsSchema.js.map +0 -1
- package/dist/schema/coordination.d.ts +0 -113
- package/dist/schema/coordination.d.ts.map +0 -1
- package/dist/schema/coordination.js +0 -134
- package/dist/schema/coordination.js.map +0 -1
- package/dist/source/adapter.d.ts.map +0 -1
- package/dist/source/adapter.js.map +0 -1
- package/dist/source/adapterFactory.d.ts.map +0 -1
- package/dist/source/adapterFactory.js.map +0 -1
- package/dist/source/adapterProfile.d.ts.map +0 -1
- package/dist/source/adapterProfile.js.map +0 -1
- package/dist/source/conformance.d.ts.map +0 -1
- package/dist/source/conformance.js.map +0 -1
- package/dist/source/connector.d.ts.map +0 -1
- package/dist/source/connector.js.map +0 -1
- package/dist/source/connectorProtocol.d.ts.map +0 -1
- package/dist/source/connectorProtocol.js.map +0 -1
- package/dist/source/contract.d.ts.map +0 -1
- package/dist/source/contract.js.map +0 -1
- package/dist/source/drizzle.d.ts +0 -2
- package/dist/source/drizzle.d.ts.map +0 -1
- package/dist/source/drizzle.js +0 -2
- package/dist/source/drizzle.js.map +0 -1
- package/dist/source/factory.d.ts.map +0 -1
- package/dist/source/factory.js.map +0 -1
- package/dist/source/idempotency.d.ts.map +0 -1
- package/dist/source/idempotency.js.map +0 -1
- package/dist/source/kysely.d.ts +0 -3
- package/dist/source/kysely.d.ts.map +0 -1
- package/dist/source/kysely.js +0 -3
- package/dist/source/kysely.js.map +0 -1
- package/dist/source/migrations.d.ts.map +0 -1
- package/dist/source/migrations.js.map +0 -1
- package/dist/source/next.d.ts.map +0 -1
- package/dist/source/next.js.map +0 -1
- package/dist/source/pushQueue.d.ts.map +0 -1
- package/dist/source/pushQueue.js.map +0 -1
- package/dist/source/signing.d.ts.map +0 -1
- package/dist/source/signing.js.map +0 -1
- package/dist/transactionLayer.d.ts.map +0 -1
- package/dist/transactionLayer.js.map +0 -1
- package/dist/transactions/confirmation/commitEnvelope.d.ts.map +0 -1
- package/dist/transactions/confirmation/commitEnvelope.js.map +0 -1
- package/dist/transactions/confirmation/httpCommitEnvelope.d.ts.map +0 -1
- package/dist/transactions/confirmation/httpCommitEnvelope.js.map +0 -1
- package/dist/transactions/confirmation/idempotencyKey.d.ts.map +0 -1
- package/dist/transactions/confirmation/idempotencyKey.js.map +0 -1
- package/dist/transactions/confirmation/pendingWrite.d.ts.map +0 -1
- package/dist/transactions/confirmation/pendingWrite.js.map +0 -1
- package/dist/transport/commitFrames.d.ts.map +0 -1
- package/dist/transport/commitFrames.js.map +0 -1
- package/dist/transport/connectionManager.d.ts.map +0 -1
- package/dist/transport/connectionManager.js.map +0 -1
- package/dist/transport/credentialLifecycle.d.ts.map +0 -1
- package/dist/transport/credentialLifecycle.js.map +0 -1
- package/dist/transport/heartbeat.d.ts.map +0 -1
- package/dist/transport/heartbeat.js.map +0 -1
- package/dist/transport/httpClient.d.ts.map +0 -1
- package/dist/transport/httpClient.js.map +0 -1
- package/dist/transport/httpFeed.d.ts +0 -4
- package/dist/transport/httpFeed.d.ts.map +0 -1
- package/dist/transport/httpOptions.js.map +0 -1
- package/dist/transport/httpTransport.d.ts.map +0 -1
- package/dist/transport/httpTransport.js.map +0 -1
- package/dist/transport/networkProbe.d.ts.map +0 -1
- package/dist/transport/networkProbe.js.map +0 -1
- package/dist/transport/wsFrameHandlers.d.ts.map +0 -1
- package/dist/transport/wsFrameHandlers.js.map +0 -1
- package/dist/transport/wsTransport.d.ts.map +0 -1
- package/dist/transport/wsTransport.js.map +0 -1
- package/dist/wire/claimEvent.d.ts.map +0 -1
- package/dist/wire/claimEvent.js.map +0 -1
- package/dist/wire/claims.d.ts.map +0 -1
- package/dist/wire/claims.js.map +0 -1
- package/dist/wire/commit.d.ts +0 -2801
- package/dist/wire/commit.d.ts.map +0 -1
- package/dist/wire/commit.js.map +0 -1
- package/dist/wire/delta.d.ts.map +0 -1
- package/dist/wire/delta.js.map +0 -1
- package/dist/wire/deltaDelivery.d.ts.map +0 -1
- package/dist/wire/deltaDelivery.js.map +0 -1
- package/dist/wire/feedCursor.d.ts.map +0 -1
- package/dist/wire/feedCursor.js.map +0 -1
- package/dist/wire/feedEvent.d.ts.map +0 -1
- package/dist/wire/feedEvent.js.map +0 -1
- package/src/policy/types.ts +0 -300
- package/src/schema/coordination.ts +0 -161
- package/src/source/drizzle.ts +0 -1
- package/src/source/kysely.ts +0 -2
- /package/dist/{coordination → claims}/targetConflict.d.ts +0 -0
- /package/dist/{coordination → claims}/targetConflict.js +0 -0
- /package/dist/{resources → client/resources}/mutationOptions.js +0 -0
- /package/dist/{resources → client/resources}/where.d.ts +0 -0
- /package/dist/{transactions → commit}/confirmation/httpCommitEnvelope.d.ts +0 -0
- /package/dist/{transactions → commit}/confirmation/idempotencyKey.d.ts +0 -0
- /package/dist/{transactions → commit}/confirmation/idempotencyKey.js +0 -0
- /package/dist/source/{adapter.js → adapters/adapter.js} +0 -0
- /package/dist/source/{adapterFactory.d.ts → adapters/adapterFactory.d.ts} +0 -0
- /package/dist/source/{adapterProfile.d.ts → adapters/adapterProfile.d.ts} +0 -0
- /package/dist/source/{adapterProfile.js → adapters/adapterProfile.js} +0 -0
- /package/dist/source/{idempotency.d.ts → adapters/idempotency.d.ts} +0 -0
- /package/src/{wire/claimEvent.ts → claims/eventContract.ts} +0 -0
- /package/src/{coordination/claimHeartbeatLoop.ts → claims/heartbeat.ts} +0 -0
- /package/src/{coordination/claimMeta.ts → claims/meta.ts} +0 -0
- /package/src/{coordination → claims}/targetConflict.ts +0 -0
- /package/src/{transactions → commit}/confirmation/idempotencyKey.ts +0 -0
- /package/src/{wire/feedCursor.ts → observation/cursor.ts} +0 -0
- /package/src/{wire/deltaDelivery.ts → observation/deliveryContract.ts} +0 -0
- /package/src/source/{adapterProfile.ts → adapters/adapterProfile.ts} +0 -0
package/src/schema/model.ts
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import { z } from 'zod';
|
|
22
22
|
import type { RelationDef } from './relation.js';
|
|
23
23
|
import type { EntityRole, GroupsInput } from './roles.js';
|
|
24
|
+
import type { SubjectRule } from './subject.js';
|
|
24
25
|
import { getFieldMeta, inferFieldMetaFromZod, type FieldMeta } from './field.js';
|
|
25
26
|
// Tenancy lives in `tenancy.ts`. Authoring uses the `policy` option
|
|
26
27
|
// (`PolicyInput`), which `resolvePolicy` normalizes into the canonical `Tenancy`
|
|
@@ -28,11 +29,6 @@ import { getFieldMeta, inferFieldMetaFromZod, type FieldMeta } from './field.js'
|
|
|
28
29
|
import { resolvePolicy, type Tenancy, type ScopedViaRef, type PolicyInput } from './tenancy.js';
|
|
29
30
|
export type { ScopedViaRef, Tenancy, PolicyInput } from './tenancy.js';
|
|
30
31
|
import { DEFAULT_RESIDENCY, type ModelResidency } from './residency.js';
|
|
31
|
-
// The write-conflict disposition. It is plain data (the `onStale` vocabulary) so it
|
|
32
|
-
// round-trips through schema serialization, and the engine interprets it when a
|
|
33
|
-
// commit is applied.
|
|
34
|
-
import type { ConflictAxis } from '../policy/types.js';
|
|
35
|
-
export type { ConflictAxis } from '../policy/types.js';
|
|
36
32
|
|
|
37
33
|
/** Normalize the `entityRoles` option (single | array | undefined) to an array. */
|
|
38
34
|
function normalizeEntityRoles(
|
|
@@ -152,6 +148,14 @@ export interface ModelOptions {
|
|
|
152
148
|
*/
|
|
153
149
|
policy?: PolicyInput;
|
|
154
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Credential-bound row authorization below organization tenancy. The named
|
|
153
|
+
* row field must match a trusted credential group: `{ field: 'workspaceId',
|
|
154
|
+
* group: 'workspace' }` authorizes only rows whose `workspaceId` has a
|
|
155
|
+
* matching `workspace:<id>` group on the request.
|
|
156
|
+
*/
|
|
157
|
+
subject?: SubjectRule;
|
|
158
|
+
|
|
155
159
|
/**
|
|
156
160
|
* Which database a model's rows live in. `tenant` (the default) is tenant data
|
|
157
161
|
* that provisioning places in the customer's own database; `control` is Ablo's own
|
|
@@ -176,6 +180,8 @@ export interface ModelOptions {
|
|
|
176
180
|
* - `roles` — explicit record-to-group roles keyed on a plain field, for routing
|
|
177
181
|
* that does not follow a relation, such as fanning a message into a recipient's
|
|
178
182
|
* inbox. Accepts one role or many.
|
|
183
|
+
* - `routingOnly: true` — explicitly acknowledges that these delivery groups
|
|
184
|
+
* are intentionally narrower than the model's independently safe read policy.
|
|
179
185
|
*
|
|
180
186
|
* ```ts
|
|
181
187
|
* // archiveMember: { userId, archiveId }
|
|
@@ -186,29 +192,6 @@ export interface ModelOptions {
|
|
|
186
192
|
*/
|
|
187
193
|
groups?: GroupsInput;
|
|
188
194
|
|
|
189
|
-
/**
|
|
190
|
-
* Write-conflict disposition, set per committer kind — decides what happens when a
|
|
191
|
-
* commit collides with another participant's claim or with a stale snapshot of this
|
|
192
|
-
* model. This is independent of {@link policy} (read access) and {@link groups}
|
|
193
|
-
* (delta routing). It is a map keyed by the committer's kind (`user`, `agent`, or
|
|
194
|
-
* `system`), with these outcomes as values:
|
|
195
|
-
*
|
|
196
|
-
* - `'overwrite'` — the write wins; that committer is never blocked.
|
|
197
|
-
* - `'reject'` — the write is refused; that committer yields.
|
|
198
|
-
* - `'notify'` — hold the write and hand the current value back so the committer
|
|
199
|
-
* re-reads and re-applies (for stale writes only).
|
|
200
|
-
*
|
|
201
|
-
* A kind you omit falls back to the engine default: reject, while honoring
|
|
202
|
-
* `onStale: 'notify'`. The value is plain data that travels with the schema to the
|
|
203
|
-
* server, where the engine interprets it. For example:
|
|
204
|
-
*
|
|
205
|
-
* ```ts
|
|
206
|
-
* // "a human's edit always wins (never blocked); an agent yields"
|
|
207
|
-
* conflict: { user: 'overwrite', agent: 'reject' }
|
|
208
|
-
* ```
|
|
209
|
-
*/
|
|
210
|
-
conflict?: ConflictAxis;
|
|
211
|
-
|
|
212
195
|
/**
|
|
213
196
|
* Whether clients may create, update, and delete this model's rows through the
|
|
214
197
|
* commit protocol. Defaults to true: declaring a model in your schema is the
|
|
@@ -353,6 +336,8 @@ export interface ModelDef<
|
|
|
353
336
|
/** The canonical tenancy descriptor for this model, normalized from the `policy`
|
|
354
337
|
* option at build time. See {@link ModelOptions.policy}. */
|
|
355
338
|
readonly tenancy: Tenancy;
|
|
339
|
+
/** Credential-bound row authorization. See {@link ModelOptions.subject}. */
|
|
340
|
+
readonly subject?: SubjectRule;
|
|
356
341
|
/** Which database this model's rows live in — `tenant` (default) can be a
|
|
357
342
|
* customer's own database; `control` is Ablo's. See {@link ModelOptions.plane}. */
|
|
358
343
|
readonly plane?: ModelResidency;
|
|
@@ -362,9 +347,8 @@ export interface ModelDef<
|
|
|
362
347
|
readonly grants?: GrantsRef;
|
|
363
348
|
/** Explicit record-to-group roles, normalized to an array. See {@link ModelOptions.groups}. */
|
|
364
349
|
readonly entityRoles?: readonly EntityRole[];
|
|
365
|
-
/**
|
|
366
|
-
|
|
367
|
-
readonly conflict?: ConflictAxis;
|
|
350
|
+
/** Explicit acknowledgement that sync groups are routing, not row access. */
|
|
351
|
+
readonly routingOnly?: true;
|
|
368
352
|
/** Whether wire-level CREATE/UPDATE/DELETE is allowed. See {@link ModelOptions.mutable}. */
|
|
369
353
|
readonly mutable?: boolean;
|
|
370
354
|
/** Defer MobX setup until first observer access. See {@link ModelOptions.lazyObservable}. */
|
|
@@ -445,13 +429,13 @@ export function model<
|
|
|
445
429
|
// Normalize the `policy` option into the canonical tenancy descriptor (defaults
|
|
446
430
|
// to a row-local organization column).
|
|
447
431
|
tenancy: resolvePolicy(options?.policy),
|
|
432
|
+
subject: options?.subject,
|
|
448
433
|
plane: options?.plane ?? DEFAULT_RESIDENCY,
|
|
449
434
|
// Unpack the `groups` option into the individual routing fields the server reads.
|
|
450
435
|
scope: options?.groups?.root,
|
|
451
436
|
grants: options?.groups?.grants,
|
|
452
437
|
entityRoles: normalizeEntityRoles(options?.groups?.roles),
|
|
453
|
-
|
|
454
|
-
conflict: options?.conflict,
|
|
438
|
+
routingOnly: options?.groups?.routingOnly,
|
|
455
439
|
mutable: options?.mutable ?? true,
|
|
456
440
|
lazyObservable: options?.lazyObservable,
|
|
457
441
|
computed: options?.computed,
|
package/src/schema/openapi.ts
CHANGED
|
@@ -25,6 +25,7 @@ import type { FieldMeta } from './field.js';
|
|
|
25
25
|
// Pulled from the endpoints module to keep this schema file free of the client's
|
|
26
26
|
// error-handling and credential dependencies.
|
|
27
27
|
import { ABLO_HOSTED_HTTP_BASE_URL } from '../auth/hostedEndpoints.js';
|
|
28
|
+
import { docUrlForCode } from '../errors.js';
|
|
28
29
|
// The commit body is DERIVED from the schema the server validates against —
|
|
29
30
|
// one definition site, so the documented surface cannot drift from the
|
|
30
31
|
// enforced one.
|
|
@@ -35,7 +36,7 @@ import {
|
|
|
35
36
|
commitRecordSchema,
|
|
36
37
|
commitRecordListSchema,
|
|
37
38
|
commitRecordWhereSchema,
|
|
38
|
-
} from '../
|
|
39
|
+
} from '../commit/contract.js';
|
|
39
40
|
import { CURSOR_PARAM, CURSOR_PARAM_ALIAS } from '../wire/listEnvelope.js';
|
|
40
41
|
import {
|
|
41
42
|
claimRequestSchema,
|
|
@@ -51,12 +52,26 @@ import {
|
|
|
51
52
|
claimReorderRequestSchema,
|
|
52
53
|
claimReorderReplySchema,
|
|
53
54
|
claimReleaseReplySchema,
|
|
54
|
-
} from '../
|
|
55
|
+
} from '../claims/contract.js';
|
|
55
56
|
import { errorEnvelopeSchema } from '../wire/errorEnvelope.js';
|
|
57
|
+
// The lifecycle promise and the rate-limit fields are contract, not prose about
|
|
58
|
+
// contract: the document renders the same constants the server emits, so the
|
|
59
|
+
// published policy cannot describe a signal the runtime does not send.
|
|
60
|
+
import {
|
|
61
|
+
API_DEPRECATION_HEADER,
|
|
62
|
+
API_LIFECYCLE,
|
|
63
|
+
API_SUNSET_HEADER,
|
|
64
|
+
API_VERSION_HEADER,
|
|
65
|
+
} from '../wire/apiLifecycle.js';
|
|
66
|
+
import {
|
|
67
|
+
RATE_LIMIT_HEADER,
|
|
68
|
+
RATE_LIMIT_POLICY_HEADER,
|
|
69
|
+
RETRY_AFTER_HEADER,
|
|
70
|
+
} from '../wire/rateLimit.js';
|
|
56
71
|
import { modelReadResponseSchema, modelListResponseSchema } from '../wire/modelResponses.js';
|
|
57
72
|
import { modelMutationRequestSchema } from '../wire/modelMutations.js';
|
|
58
|
-
import { logListResponseSchema, logQuerySchema } from '../
|
|
59
|
-
import { logDeliveryResponseSchema } from '../
|
|
73
|
+
import { logListResponseSchema, logQuerySchema } from '../observation/feedContract.js';
|
|
74
|
+
import { logDeliveryResponseSchema } from '../observation/deliveryContract.js';
|
|
60
75
|
import { schemaReadResponseSchema } from '../wire/accountResponses.js';
|
|
61
76
|
import {
|
|
62
77
|
ephemeralKeyRequestSchema,
|
|
@@ -400,6 +415,106 @@ const claimIdParam = (): Json => ({
|
|
|
400
415
|
*/
|
|
401
416
|
const commitBody = (): Json => jsonBody(derive(commitRequestSchema, 'input'));
|
|
402
417
|
|
|
418
|
+
/**
|
|
419
|
+
* The response headers every operation carries, declared once under
|
|
420
|
+
* `components/headers` and referenced from each response.
|
|
421
|
+
*
|
|
422
|
+
* A header a caller is expected to act on has to be IN the document to be
|
|
423
|
+
* actionable: a generated client surfaces what the spec declares and drops what
|
|
424
|
+
* it does not, so an undeclared `RateLimit` is a header the caller never sees
|
|
425
|
+
* and therefore never paces against. Declaring them here rather than at each
|
|
426
|
+
* response is what keeps one description of each — the reason the names are
|
|
427
|
+
* imported rather than typed out.
|
|
428
|
+
*/
|
|
429
|
+
const RESPONSE_HEADER_COMPONENTS: Readonly<Record<string, Json>> = {
|
|
430
|
+
AbloVersion: {
|
|
431
|
+
description:
|
|
432
|
+
'The date-stamped contract version this response was served under. Record ' +
|
|
433
|
+
'the value your integration was built against; a change means something ' +
|
|
434
|
+
'observable was added.',
|
|
435
|
+
schema: { type: 'string', examples: ['2026-08-15'] },
|
|
436
|
+
},
|
|
437
|
+
RateLimitPolicy: {
|
|
438
|
+
description:
|
|
439
|
+
'The standing allowance for this credential kind, as a Structured Fields ' +
|
|
440
|
+
'List: `"secret";q=600;w=12`. It does not move between responses, so read ' +
|
|
441
|
+
'it once and pace against it.',
|
|
442
|
+
schema: { type: 'string', examples: ['"secret";q=600;w=12'] },
|
|
443
|
+
},
|
|
444
|
+
RateLimit: {
|
|
445
|
+
description:
|
|
446
|
+
'This caller\u2019s live position in the allowance: `r` units left, `t` ' +
|
|
447
|
+
'seconds until they refill. Present once the request is attributed to a ' +
|
|
448
|
+
'credential.',
|
|
449
|
+
schema: { type: 'string', examples: ['"secret";r=412;t=8'] },
|
|
450
|
+
},
|
|
451
|
+
RetryAfter: {
|
|
452
|
+
description: 'Whole seconds to wait before retrying. Sent with 429 and 503.',
|
|
453
|
+
schema: { type: 'integer', minimum: 1, examples: [8] },
|
|
454
|
+
},
|
|
455
|
+
RequestId: {
|
|
456
|
+
description:
|
|
457
|
+
'Correlation id for this request, repeated in the error envelope\u2019s ' +
|
|
458
|
+
'`request_id`. Quote it in a support request.',
|
|
459
|
+
schema: { type: 'string', examples: ['req_52bb7f46-17bc-4f2d-9988-89d1398d2990'] },
|
|
460
|
+
},
|
|
461
|
+
Deprecation: {
|
|
462
|
+
description:
|
|
463
|
+
'Present only on a route being withdrawn: an sf-Date of when the ' +
|
|
464
|
+
'deprecation took effect (RFC 9745). The route still answers normally.',
|
|
465
|
+
schema: { type: 'string', examples: ['@1774483200'] },
|
|
466
|
+
},
|
|
467
|
+
Sunset: {
|
|
468
|
+
description:
|
|
469
|
+
'Present only on a route being withdrawn: the HTTP-date it stops ' +
|
|
470
|
+
'answering (RFC 8594). Never less than the published notice window after ' +
|
|
471
|
+
`\`${API_DEPRECATION_HEADER}\`.`,
|
|
472
|
+
schema: { type: 'string', examples: ['Tue, 08 Sep 2026 00:00:00 GMT'] },
|
|
473
|
+
},
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
const headerRef = (name: string): Json => ({ $ref: `#/components/headers/${name}` });
|
|
477
|
+
|
|
478
|
+
/** Carried by every response, whatever its status. */
|
|
479
|
+
const UNIVERSAL_RESPONSE_HEADERS: Readonly<Record<string, Json>> = {
|
|
480
|
+
[API_VERSION_HEADER]: headerRef('AbloVersion'),
|
|
481
|
+
'X-Request-Id': headerRef('RequestId'),
|
|
482
|
+
[RATE_LIMIT_POLICY_HEADER]: headerRef('RateLimitPolicy'),
|
|
483
|
+
[RATE_LIMIT_HEADER]: headerRef('RateLimit'),
|
|
484
|
+
[API_DEPRECATION_HEADER]: headerRef('Deprecation'),
|
|
485
|
+
[API_SUNSET_HEADER]: headerRef('Sunset'),
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
/** Statuses where a wait is what resolves the failure, so `Retry-After` is sent. */
|
|
489
|
+
const RETRY_AFTER_STATUSES = new Set(['429', '503']);
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Stamp the documented headers onto every response of every operation.
|
|
493
|
+
*
|
|
494
|
+
* Runs after the responses are built — including the canonical error ones — so
|
|
495
|
+
* a response added later cannot quietly ship without them.
|
|
496
|
+
*/
|
|
497
|
+
function attachResponseHeaders(paths: Json): void {
|
|
498
|
+
for (const rawPathItem of Object.values(paths)) {
|
|
499
|
+
const pathItem = rawPathItem as Json;
|
|
500
|
+
for (const [method, rawOperation] of Object.entries(pathItem)) {
|
|
501
|
+
if (!HTTP_METHODS.has(method)) continue;
|
|
502
|
+
const operation = rawOperation as Json;
|
|
503
|
+
const responses = (operation.responses ?? {}) as Json;
|
|
504
|
+
for (const [status, rawResponse] of Object.entries(responses)) {
|
|
505
|
+
const response = rawResponse as Json;
|
|
506
|
+
response.headers = {
|
|
507
|
+
...UNIVERSAL_RESPONSE_HEADERS,
|
|
508
|
+
...(RETRY_AFTER_STATUSES.has(status)
|
|
509
|
+
? { [RETRY_AFTER_HEADER]: headerRef('RetryAfter') }
|
|
510
|
+
: {}),
|
|
511
|
+
...((response.headers as Json | undefined) ?? {}),
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
403
518
|
/** The envelope shared by both specs — same server, same auth, same version. */
|
|
404
519
|
function envelope(options: SchemaToOpenApiOptions, description: string, paths: Json, schemas: Record<string, Json>): Json {
|
|
405
520
|
return {
|
|
@@ -407,18 +522,28 @@ function envelope(options: SchemaToOpenApiOptions, description: string, paths: J
|
|
|
407
522
|
info: {
|
|
408
523
|
title: options.title ?? 'Ablo API',
|
|
409
524
|
version: options.version ?? 'development',
|
|
410
|
-
|
|
525
|
+
// The lifecycle policy travels WITH the routes it governs. An agent
|
|
526
|
+
// deciding whether to integrate needs to know the surface will not move
|
|
527
|
+
// under it, and a policy published somewhere else is one it has to go
|
|
528
|
+
// find — so the document that describes the calls describes the promise.
|
|
529
|
+
description: `${description}\n\n${API_LIFECYCLE}`,
|
|
411
530
|
license: {
|
|
412
531
|
name: 'Apache License 2.0',
|
|
413
532
|
identifier: 'Apache-2.0',
|
|
414
533
|
},
|
|
534
|
+
contact: {
|
|
535
|
+
name: 'Ablo Support',
|
|
536
|
+
url: 'https://github.com/Abloatai/ablo/issues',
|
|
537
|
+
email: 'support@abloatai.com',
|
|
538
|
+
},
|
|
415
539
|
},
|
|
416
540
|
servers: [{ url: options.serverUrl ?? `${ABLO_HOSTED_HTTP_BASE_URL}/api` }],
|
|
417
541
|
security: [{ bearerAuth: [] }],
|
|
418
542
|
components: {
|
|
419
543
|
securitySchemes: {
|
|
420
|
-
bearerAuth: { type: 'http', scheme: 'bearer', description: 'Your Ablo API key (sk_
|
|
544
|
+
bearerAuth: { type: 'http', scheme: 'bearer', description: 'Your Ablo API key (sk_\u2026 / rk_\u2026).' },
|
|
421
545
|
},
|
|
546
|
+
headers: { ...RESPONSE_HEADER_COMPONENTS },
|
|
422
547
|
schemas,
|
|
423
548
|
},
|
|
424
549
|
paths,
|
|
@@ -436,6 +561,41 @@ const ERROR_RESPONSES: Readonly<Record<string, string>> = {
|
|
|
436
561
|
'503': 'A required service is temporarily unavailable.',
|
|
437
562
|
};
|
|
438
563
|
|
|
564
|
+
/**
|
|
565
|
+
* One real instance of the error shape every operation shares.
|
|
566
|
+
*
|
|
567
|
+
* This lives beside the canonical error responses rather than on the schema:
|
|
568
|
+
* OpenAPI consumers select examples from an operation's media type, and an
|
|
569
|
+
* example buried on a component does not tell them which response carries it.
|
|
570
|
+
* Stamping the same representative validation failure on every operation also
|
|
571
|
+
* means a newly added route cannot regress the published example coverage.
|
|
572
|
+
*/
|
|
573
|
+
const ERROR_RESPONSE_EXAMPLE: Readonly<Json> = {
|
|
574
|
+
type: 'AbloValidationError',
|
|
575
|
+
code: 'invalid_request',
|
|
576
|
+
param: 'body',
|
|
577
|
+
message: 'The request did not satisfy the published contract.',
|
|
578
|
+
doc_url: docUrlForCode('invalid_request'),
|
|
579
|
+
request_id: 'req_52bb7f46-17bc-4f2d-9988-89d1398d2990',
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
function canonicalErrorResp(description: string): Json {
|
|
583
|
+
return {
|
|
584
|
+
description,
|
|
585
|
+
content: {
|
|
586
|
+
'application/json': {
|
|
587
|
+
schema: schemaRef('ErrorEnvelope'),
|
|
588
|
+
examples: {
|
|
589
|
+
validation: {
|
|
590
|
+
summary: 'Typed validation failure',
|
|
591
|
+
value: ERROR_RESPONSE_EXAMPLE,
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
|
|
439
599
|
/**
|
|
440
600
|
* Every route passes failures through the same server error funnel. Publish
|
|
441
601
|
* that fact on every operation so generated transports decode all HTTP errors
|
|
@@ -450,11 +610,10 @@ function attachCanonicalErrors(paths: Json): void {
|
|
|
450
610
|
const operation = rawOperation as Json;
|
|
451
611
|
const responses = { ...(operation.responses as Json | undefined) };
|
|
452
612
|
for (const [status, description] of Object.entries(ERROR_RESPONSES)) {
|
|
453
|
-
responses[status] =
|
|
613
|
+
responses[status] = canonicalErrorResp(description);
|
|
454
614
|
}
|
|
455
|
-
responses.default =
|
|
615
|
+
responses.default = canonicalErrorResp(
|
|
456
616
|
'An HTTP error not otherwise listed; decoded through the canonical envelope.',
|
|
457
|
-
'ErrorEnvelope',
|
|
458
617
|
);
|
|
459
618
|
operation.responses = responses;
|
|
460
619
|
}
|
|
@@ -950,6 +1109,7 @@ export function abloOpenApi(options: SchemaToOpenApiOptions = {}): Json {
|
|
|
950
1109
|
|
|
951
1110
|
applyOperationIds(paths, ABLO_OPERATION_IDS);
|
|
952
1111
|
attachCanonicalErrors(paths);
|
|
1112
|
+
attachResponseHeaders(paths);
|
|
953
1113
|
|
|
954
1114
|
return envelope(
|
|
955
1115
|
options,
|
|
@@ -1078,6 +1238,7 @@ export function schemaToOpenApi<S extends SchemaRecord>(
|
|
|
1078
1238
|
operationIds['GET /v1/commits/{id}'] = 'getCommit';
|
|
1079
1239
|
applyOperationIds(paths, operationIds);
|
|
1080
1240
|
attachCanonicalErrors(paths);
|
|
1241
|
+
attachResponseHeaders(paths);
|
|
1081
1242
|
|
|
1082
1243
|
Object.assign(schemas, abloComponentSchemas());
|
|
1083
1244
|
|
package/src/schema/roles.ts
CHANGED
|
@@ -219,6 +219,8 @@ export const groupsInputSchema = z.object({
|
|
|
219
219
|
root: scopeSchema.optional(),
|
|
220
220
|
grants: grantsRefSchema.optional(),
|
|
221
221
|
roles: z.union([entityRoleSchema, z.array(entityRoleSchema)]).optional(),
|
|
222
|
+
/** Acknowledge that these groups are delivery routing, not row access. */
|
|
223
|
+
routingOnly: z.literal(true).optional(),
|
|
222
224
|
});
|
|
223
225
|
export type GroupsInput = z.infer<typeof groupsInputSchema>;
|
|
224
226
|
|
|
@@ -314,6 +316,57 @@ export function composeEntitySyncGroups(
|
|
|
314
316
|
return Array.from(out);
|
|
315
317
|
}
|
|
316
318
|
|
|
319
|
+
/** The row fields needed to derive its durable delivery groups. */
|
|
320
|
+
export interface RecordSyncGroupSpec {
|
|
321
|
+
readonly subject?: { readonly kind: string; readonly field: string };
|
|
322
|
+
readonly selfKind?: string;
|
|
323
|
+
readonly parents: readonly { readonly kind: string; readonly field: string }[];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** A subject-scoped row cannot be routed safely without its declared subject. */
|
|
327
|
+
export class InvalidRecordSubjectError extends Error {
|
|
328
|
+
readonly field: string;
|
|
329
|
+
|
|
330
|
+
constructor(field: string) {
|
|
331
|
+
super(`Record lacks non-empty subject field "${field}".`);
|
|
332
|
+
this.name = 'InvalidRecordSubjectError';
|
|
333
|
+
this.field = field;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Derive the exact durable delivery groups for a row.
|
|
339
|
+
*
|
|
340
|
+
* Delivery matching is OR-based, so a declared subject is an exclusive
|
|
341
|
+
* authorization route: self, parent, entity-role, writer, and transitive groups
|
|
342
|
+
* must not become alternate ways to receive the row. Additional groups are
|
|
343
|
+
* accepted here so every producer applies that rule in this one place.
|
|
344
|
+
*/
|
|
345
|
+
export function syncGroupsForRow(
|
|
346
|
+
spec: RecordSyncGroupSpec | undefined,
|
|
347
|
+
record: Readonly<Record<string, unknown>>,
|
|
348
|
+
additionalGroups: readonly string[] = [],
|
|
349
|
+
): string[] {
|
|
350
|
+
if (spec?.subject) {
|
|
351
|
+
const value = record[spec.subject.field];
|
|
352
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
353
|
+
throw new InvalidRecordSubjectError(spec.subject.field);
|
|
354
|
+
}
|
|
355
|
+
return [syncGroup(spec.subject.kind, value)];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const groups = new Set<string>(additionalGroups);
|
|
359
|
+
if (!spec) return [...groups];
|
|
360
|
+
if (spec.selfKind && typeof record.id === 'string' && record.id.length > 0) {
|
|
361
|
+
groups.add(syncGroup(spec.selfKind, record.id));
|
|
362
|
+
}
|
|
363
|
+
for (const parent of spec.parents) {
|
|
364
|
+
const value = record[parent.field];
|
|
365
|
+
if (value) groups.add(syncGroup(parent.kind, String(value)));
|
|
366
|
+
}
|
|
367
|
+
return [...groups];
|
|
368
|
+
}
|
|
369
|
+
|
|
317
370
|
/**
|
|
318
371
|
* Narrow a client's requested sync-group set to the groups it is actually
|
|
319
372
|
* allowed to subscribe to. This helper is fully generic — it never inspects the
|
package/src/schema/schema.ts
CHANGED
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
* status: z.enum(['todo', 'doing', 'done']).default('todo'),
|
|
14
14
|
* workspaceId: z.string().optional(),
|
|
15
15
|
* }, {
|
|
16
|
-
* workspace: relation.belongsTo('workspaces', 'workspaceId'),
|
|
16
|
+
* relations: { workspace: relation.belongsTo('workspaces', 'workspaceId') },
|
|
17
17
|
* }),
|
|
18
18
|
* });
|
|
19
19
|
*
|
|
20
|
-
* type Item =
|
|
20
|
+
* type Item = Model<typeof schema, 'items'>;
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import { z } from 'zod';
|
|
@@ -27,6 +27,7 @@ import { AbloValidationError } from '../errors.js';
|
|
|
27
27
|
import type { IdentityRole } from './roles.js';
|
|
28
28
|
import { fieldRef, type FieldRef } from './fieldRef.js';
|
|
29
29
|
import { scopeSchema, grantsRefSchema } from './roles.js';
|
|
30
|
+
import { subjectRuleSchema } from './subject.js';
|
|
30
31
|
|
|
31
32
|
// Sync-group roles (identity and entity) are defined in `./roles.js` and
|
|
32
33
|
// re-exported here so they can also be imported from this module. See
|
|
@@ -49,6 +50,9 @@ export {
|
|
|
49
50
|
extractEntityIds,
|
|
50
51
|
composeIdentitySyncGroups,
|
|
51
52
|
composeEntitySyncGroups,
|
|
53
|
+
syncGroupsForRow,
|
|
54
|
+
InvalidRecordSubjectError,
|
|
55
|
+
type RecordSyncGroupSpec,
|
|
52
56
|
intersectRequestedWithAllowed,
|
|
53
57
|
syncGroup,
|
|
54
58
|
identityAnchor,
|
|
@@ -150,6 +154,7 @@ export const RESERVED_SESSION_SETTINGS: readonly string[] = [
|
|
|
150
154
|
'app.current_participant_id',
|
|
151
155
|
'app.current_participant_kind',
|
|
152
156
|
'app.current_user_id',
|
|
157
|
+
'app.current_subject_groups',
|
|
153
158
|
];
|
|
154
159
|
|
|
155
160
|
export interface DefineSchemaOptions {
|
|
@@ -226,6 +231,13 @@ export const baseFieldsSchema = z.object({
|
|
|
226
231
|
/**
|
|
227
232
|
* The universal model field names. Audit and application metadata is declared
|
|
228
233
|
* by the application or carried by the commit record, never injected here.
|
|
234
|
+
*
|
|
235
|
+
* This is the runtime spelling of {@link baseFieldsSchema}, and the one every
|
|
236
|
+
* consumer outside this package derives from: the CLI's adopt rule, the MCP
|
|
237
|
+
* schema linter, and the docs that tell an author which names not to declare.
|
|
238
|
+
* It is exported from `@abloatai/transaction/schema` for exactly that reason —
|
|
239
|
+
* when this list last moved (0.52.0, five names down to one) three hand-written
|
|
240
|
+
* copies stayed behind and went on rejecting correct schemas for five releases.
|
|
229
241
|
*/
|
|
230
242
|
export const BASE_FIELDS = [
|
|
231
243
|
'id',
|
|
@@ -234,6 +246,18 @@ export const BASE_FIELDS = [
|
|
|
234
246
|
/** The base fields type — pure data columns. */
|
|
235
247
|
export type BaseModelFields = z.infer<typeof baseFieldsSchema>;
|
|
236
248
|
|
|
249
|
+
// Invariant equality (no runtime, no casts): true only when both are mutually
|
|
250
|
+
// assignable. `ExpectTrue`'s constraint is what turns a mismatch into an error
|
|
251
|
+
// at THIS declaration, so the tuple and the schema cannot move apart — in
|
|
252
|
+
// either direction, a name in one and not the other fails to compile.
|
|
253
|
+
type BaseFieldsEqual<A, B> =
|
|
254
|
+
(<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
|
255
|
+
type ExpectTrue<T extends true> = T;
|
|
256
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
257
|
+
type _BaseFieldsExact = ExpectTrue<
|
|
258
|
+
BaseFieldsEqual<(typeof BASE_FIELDS)[number], keyof BaseModelFields & string>
|
|
259
|
+
>;
|
|
260
|
+
|
|
237
261
|
/**
|
|
238
262
|
* Methods every model instance carries. These are intersected into
|
|
239
263
|
* {@link InferModel}, the read-side type, but not into the create or update
|
|
@@ -327,7 +351,8 @@ export interface Schema<S extends SchemaRecord = SchemaRecord> {
|
|
|
327
351
|
|
|
328
352
|
/**
|
|
329
353
|
* Infer the full model type from a schema.
|
|
330
|
-
* Includes base fields
|
|
354
|
+
* Includes the base fields, which today means `id` alone: audit timestamps are
|
|
355
|
+
* ordinary declared fields and appear here only when the model declares them.
|
|
331
356
|
*
|
|
332
357
|
* ```ts
|
|
333
358
|
* type Item = InferModel<typeof schema, 'items'>;
|
|
@@ -523,14 +548,34 @@ export type InsertValue<S extends Schema, ModelName extends keyof S['models']> =
|
|
|
523
548
|
export type UpsertValue<S extends Schema, ModelName extends keyof S['models']> =
|
|
524
549
|
InsertValue<S, ModelName>;
|
|
525
550
|
|
|
551
|
+
/**
|
|
552
|
+
* A patch over a row's fields: send a field to change it, omit it to leave it,
|
|
553
|
+
* send `null` to CLEAR it.
|
|
554
|
+
*
|
|
555
|
+
* The third of those is why this is a mapped type rather than `Partial`.
|
|
556
|
+
* Omitting a field and clearing a field are different intentions that
|
|
557
|
+
* `Partial` spells the same way, because `undefined` is what an absent key
|
|
558
|
+
* already means: it is dropped from the payload, so a caller who wrote
|
|
559
|
+
* `{ assigneeId: undefined }` to unassign kept the old assignee, and the
|
|
560
|
+
* unassign, the un-project and the cleared due date all did nothing without
|
|
561
|
+
* erroring. `null` is the value that clears, so `null` is what the type has to
|
|
562
|
+
* accept — otherwise the only way to write a working clear is to cast the
|
|
563
|
+
* payload, and a cast is what people reached for.
|
|
564
|
+
*
|
|
565
|
+
* Only a field the schema lets be absent is clearable. A required field cannot
|
|
566
|
+
* be nulled, which is the same rule the column has.
|
|
567
|
+
*/
|
|
568
|
+
export type Clearable<T> = {
|
|
569
|
+
[K in keyof T]?: undefined extends T[K] ? T[K] | null : T[K];
|
|
570
|
+
};
|
|
571
|
+
|
|
526
572
|
/**
|
|
527
573
|
* The value type for updating an existing row. `id` is required (identifies
|
|
528
|
-
* the row to update);
|
|
529
|
-
* are changed).
|
|
574
|
+
* the row to update); every other field is a {@link Clearable} patch.
|
|
530
575
|
*/
|
|
531
576
|
export type UpdateValue<S extends Schema, ModelName extends keyof S['models']> =
|
|
532
577
|
S['models'][ModelName] extends ModelDef<infer Shape>
|
|
533
|
-
? { id: string } &
|
|
578
|
+
? { id: string } & Clearable<z.input<z.ZodObject<Shape>>>
|
|
534
579
|
: never;
|
|
535
580
|
|
|
536
581
|
/**
|
|
@@ -708,6 +753,7 @@ export function defineSchema<const S extends SchemaRecord>(
|
|
|
708
753
|
}
|
|
709
754
|
|
|
710
755
|
validateSyncGroupSchema(resolvedModels);
|
|
756
|
+
validateSubjectSchema(resolvedModels);
|
|
711
757
|
validateSessionSettings(options?.sessionSettings ?? {});
|
|
712
758
|
|
|
713
759
|
return {
|
|
@@ -721,6 +767,45 @@ export function defineSchema<const S extends SchemaRecord>(
|
|
|
721
767
|
};
|
|
722
768
|
}
|
|
723
769
|
|
|
770
|
+
function validateSubjectSchema(models: Record<string, ModelDef>): void {
|
|
771
|
+
for (const [name, def] of Object.entries(models)) {
|
|
772
|
+
if (!def.subject) continue;
|
|
773
|
+
const parsed = subjectRuleSchema.safeParse(def.subject);
|
|
774
|
+
if (!parsed.success) {
|
|
775
|
+
throw new AbloValidationError(
|
|
776
|
+
`Model "${name}": subject must be { field, group } with valid identifiers.`,
|
|
777
|
+
{ code: 'schema_definition_invalid', param: `${name}.subject` },
|
|
778
|
+
);
|
|
779
|
+
}
|
|
780
|
+
if (!(def.subject.field in def.fields)) {
|
|
781
|
+
throw new AbloValidationError(
|
|
782
|
+
`Model "${name}": subject.field "${def.subject.field}" is not a declared field on this model.`,
|
|
783
|
+
{ code: 'schema_definition_invalid', param: `${name}.subject.field` },
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
const field = def.shape[def.subject.field];
|
|
787
|
+
const meta = def.fields[def.subject.field];
|
|
788
|
+
if (!field || !meta) {
|
|
789
|
+
throw new AbloValidationError(
|
|
790
|
+
`Model "${name}": subject.field "${def.subject.field}" is not a declared field on this model.`,
|
|
791
|
+
{ code: 'schema_definition_invalid', param: `${name}.subject.field` },
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
const subjectField = field as z.ZodType;
|
|
795
|
+
const acceptsInvalidValue =
|
|
796
|
+
subjectField.safeParse('').success ||
|
|
797
|
+
subjectField.safeParse(null).success ||
|
|
798
|
+
subjectField.safeParse(undefined).success ||
|
|
799
|
+
subjectField.safeParse(1).success;
|
|
800
|
+
if (!['string', 'enum'].includes(meta.type) || meta.isOptional || acceptsInvalidValue) {
|
|
801
|
+
throw new AbloValidationError(
|
|
802
|
+
`Model "${name}": subject.field "${def.subject.field}" must be a required, non-empty string field.`,
|
|
803
|
+
{ code: 'schema_definition_invalid', param: `${name}.subject.field` },
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
724
809
|
/**
|
|
725
810
|
* Reject session-setting mappings that couldn't do what the author intends —
|
|
726
811
|
* caught here at definition time rather than silently dropped on the write path.
|
package/src/schema/serialize.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* What round-trips:
|
|
14
14
|
* - all model routing and scoping metadata: typename, tableName, load,
|
|
15
15
|
* mutable, the `tenancy` descriptor, bootstrap hints, scope, grants,
|
|
16
|
-
* entityRoles, the `conflict` disposition map, persist, autoFill,
|
|
16
|
+
* entityRoles, the routing-only acknowledgement, the `conflict` disposition map, persist, autoFill,
|
|
17
17
|
* requiredFields, and lazyObservable. The authoring shorthands (`policy`
|
|
18
18
|
* and `groups`) are normalized into these canonical fields when the model
|
|
19
19
|
* is built, so only the canonical fields cross here.
|
|
@@ -33,6 +33,7 @@ import type { FieldMeta } from './field.js';
|
|
|
33
33
|
import { buildFieldRefs } from './schema.js';
|
|
34
34
|
import type { Tenancy } from './tenancy.js';
|
|
35
35
|
import type { ModelResidency } from './residency.js';
|
|
36
|
+
import type { SubjectRule } from './subject.js';
|
|
36
37
|
import type {
|
|
37
38
|
ModelDef,
|
|
38
39
|
RelationRecord,
|
|
@@ -40,7 +41,6 @@ import type {
|
|
|
40
41
|
LoadStrategy,
|
|
41
42
|
PersistOptions,
|
|
42
43
|
AutoFillRule,
|
|
43
|
-
ConflictAxis,
|
|
44
44
|
} from './model.js';
|
|
45
45
|
import {
|
|
46
46
|
relation,
|
|
@@ -80,6 +80,7 @@ export interface ModelJSON {
|
|
|
80
80
|
readonly typename: string;
|
|
81
81
|
readonly tableName?: string;
|
|
82
82
|
readonly tenancy: Tenancy;
|
|
83
|
+
readonly subject?: SubjectRule;
|
|
83
84
|
/** The database plane the model's rows live in. Optional for backward
|
|
84
85
|
* compatibility: when absent (an artifact written before this field existed)
|
|
85
86
|
* it reads as `tenant`, the default. See {@link ModelResidency}. */
|
|
@@ -87,9 +88,7 @@ export interface ModelJSON {
|
|
|
87
88
|
readonly scope?: boolean | string;
|
|
88
89
|
readonly grants?: GrantsRef;
|
|
89
90
|
readonly entityRoles?: readonly EntityRole[];
|
|
90
|
-
|
|
91
|
-
* the engine falls back to its default. */
|
|
92
|
-
readonly conflict?: ConflictAxis;
|
|
91
|
+
readonly routingOnly?: true;
|
|
93
92
|
readonly bootstrapLimit?: number;
|
|
94
93
|
readonly bootstrapOrderBy?: string;
|
|
95
94
|
readonly mutable?: boolean;
|
|
@@ -136,11 +135,12 @@ function modelToJSON(def: ModelDef): ModelJSON {
|
|
|
136
135
|
typename: def.typename ?? '',
|
|
137
136
|
tableName: def.tableName,
|
|
138
137
|
tenancy: def.tenancy,
|
|
138
|
+
subject: def.subject,
|
|
139
139
|
plane: def.plane,
|
|
140
140
|
scope: def.scope,
|
|
141
141
|
grants: def.grants,
|
|
142
142
|
entityRoles: def.entityRoles,
|
|
143
|
-
|
|
143
|
+
routingOnly: def.routingOnly,
|
|
144
144
|
bootstrapLimit: def.bootstrapLimit,
|
|
145
145
|
bootstrapOrderBy: def.bootstrapOrderBy,
|
|
146
146
|
mutable: def.mutable,
|
|
@@ -272,15 +272,14 @@ function modelFromJSON(json: ModelJSON): ModelDef {
|
|
|
272
272
|
persist: json.persist,
|
|
273
273
|
tableName: json.tableName,
|
|
274
274
|
tenancy: json.tenancy,
|
|
275
|
+
subject: json.subject,
|
|
275
276
|
// Absent in older artifacts → default `tenant`, matching the model builder
|
|
276
277
|
// and provisioning defaults so the round-trip stays stable.
|
|
277
278
|
plane: json.plane ?? 'tenant',
|
|
278
279
|
scope: json.scope,
|
|
279
280
|
grants: json.grants,
|
|
280
281
|
entityRoles: json.entityRoles,
|
|
281
|
-
|
|
282
|
-
// the function registry or the engine default.
|
|
283
|
-
conflict: json.conflict,
|
|
282
|
+
routingOnly: json.routingOnly,
|
|
284
283
|
mutable: json.mutable,
|
|
285
284
|
lazyObservable: json.lazyObservable,
|
|
286
285
|
// computed getters are closures and intentionally not serialized; a
|