@abloatai/transaction 0.47.0 → 0.49.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 +7 -7
- package/README.md +1 -1
- package/dist/ai-sdk/modelTools.d.ts +1 -1
- package/dist/ai-sdk/modelTools.js +1 -1
- package/dist/ai-sdk/updateTool.d.ts +2 -2
- package/dist/ai-sdk/updateTool.d.ts.map +1 -1
- package/dist/auth/bootstrapScope.d.ts +1 -1
- package/dist/auth/capability.d.ts +32 -10
- package/dist/auth/capability.d.ts.map +1 -1
- package/dist/auth/capability.js +9 -3
- package/dist/auth/capability.js.map +1 -1
- package/dist/auth/capabilityLifecycle.d.ts +2 -2
- package/dist/auth/capabilityLifecycle.d.ts.map +1 -1
- package/dist/auth/capabilityLifecycle.js +3 -2
- package/dist/auth/capabilityLifecycle.js.map +1 -1
- package/dist/auth/identity.d.ts +3 -0
- package/dist/auth/identity.d.ts.map +1 -1
- package/dist/auth/identity.js +13 -1
- package/dist/auth/identity.js.map +1 -1
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/schemas.d.ts +18 -1
- package/dist/auth/schemas.d.ts.map +1 -1
- package/dist/auth/schemas.js +3 -1
- package/dist/auth/schemas.js.map +1 -1
- package/dist/auth/sessionMint.d.ts.map +1 -1
- package/dist/auth/sessionMint.js +0 -1
- package/dist/auth/sessionMint.js.map +1 -1
- package/dist/branches.d.ts +61 -12
- package/dist/branches.d.ts.map +1 -1
- package/dist/branches.js +25 -3
- package/dist/branches.js.map +1 -1
- package/dist/commitRecordRuntime.d.ts +30 -0
- package/dist/commitRecordRuntime.d.ts.map +1 -0
- package/dist/commitRecordRuntime.js +188 -0
- package/dist/commitRecordRuntime.js.map +1 -0
- package/dist/coordination/index.d.ts +3 -3
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +2 -2
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/locator.d.ts +5 -0
- package/dist/coordination/locator.d.ts.map +1 -1
- package/dist/coordination/locator.js +12 -0
- package/dist/coordination/locator.js.map +1 -1
- package/dist/coordination/schema.d.ts +205 -15
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +88 -47
- package/dist/coordination/schema.js.map +1 -1
- package/dist/coordination/targetConflict.js +1 -1
- package/dist/durableWrites.d.ts +3 -3
- package/dist/durableWrites.d.ts.map +1 -1
- package/dist/durableWrites.js +1 -1
- package/dist/errorCodes.d.ts +35 -2
- package/dist/errorCodes.d.ts.map +1 -1
- package/dist/errorCodes.js +67 -19
- package/dist/errorCodes.js.map +1 -1
- package/dist/errorObservation.d.ts +82 -0
- package/dist/errorObservation.d.ts.map +1 -0
- package/dist/errorObservation.js +101 -0
- package/dist/errorObservation.js.map +1 -0
- package/dist/errors.d.ts +2 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +6 -1
- package/dist/errors.js.map +1 -1
- package/dist/footprint.d.ts +10 -22
- package/dist/footprint.d.ts.map +1 -1
- package/dist/footprint.js +12 -24
- package/dist/footprint.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/read-set.d.ts +8 -0
- package/dist/internal/read-set.d.ts.map +1 -0
- package/dist/internal/read-set.js +7 -0
- package/dist/internal/read-set.js.map +1 -0
- package/dist/logger.d.ts +1 -1
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +1 -1
- package/dist/readSetContext.d.ts +54 -0
- package/dist/readSetContext.d.ts.map +1 -0
- package/dist/readSetContext.js +98 -0
- package/dist/readSetContext.js.map +1 -0
- package/dist/resources/functionalUpdate.d.ts +13 -3
- package/dist/resources/functionalUpdate.d.ts.map +1 -1
- package/dist/resources/functionalUpdate.js.map +1 -1
- package/dist/resources/httpResources.d.ts +23 -7
- package/dist/resources/httpResources.d.ts.map +1 -1
- package/dist/resources/modelOperations.d.ts +2 -2
- package/dist/resources/modelOperations.js +1 -1
- package/dist/resources/mutationOptions.d.ts +1 -1
- package/dist/resources/mutationOptions.js +1 -1
- package/dist/resources/where.d.ts +1 -1
- package/dist/resources/where.js +1 -1
- package/dist/resources/writeOptionsSchema.d.ts +39 -4
- package/dist/resources/writeOptionsSchema.d.ts.map +1 -1
- package/dist/resources/writeOptionsSchema.js +12 -6
- package/dist/resources/writeOptionsSchema.js.map +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/openapi.d.ts.map +1 -1
- package/dist/schema/openapi.js +45 -11
- package/dist/schema/openapi.js.map +1 -1
- package/dist/server/commit.d.ts +7 -1
- 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/source/adapters/kysely.d.ts.map +1 -1
- package/dist/source/adapters/kysely.js +11 -4
- package/dist/source/adapters/kysely.js.map +1 -1
- package/dist/source/adapters/kyselyMutationCore.d.ts.map +1 -1
- package/dist/source/adapters/kyselyMutationCore.js +14 -2
- package/dist/source/adapters/kyselyMutationCore.js.map +1 -1
- package/dist/source/contract.d.ts +2 -0
- package/dist/source/contract.d.ts.map +1 -1
- package/dist/source/index.d.ts +1 -1
- package/dist/source/index.d.ts.map +1 -1
- package/dist/source/types.d.ts +1 -1
- package/dist/testing/fixtures/httpResponses.d.ts +30 -1
- package/dist/testing/fixtures/httpResponses.d.ts.map +1 -1
- package/dist/testing/fixtures/httpResponses.js +48 -1
- package/dist/testing/fixtures/httpResponses.js.map +1 -1
- package/dist/transactionLayer.d.ts +1 -1
- package/dist/transactions/{settlement → confirmation}/commitEnvelope.d.ts +4 -2
- package/dist/transactions/confirmation/commitEnvelope.d.ts.map +1 -0
- package/dist/transactions/{settlement → confirmation}/commitEnvelope.js +8 -3
- package/dist/transactions/confirmation/commitEnvelope.js.map +1 -0
- package/dist/transactions/confirmation/httpCommitEnvelope.d.ts.map +1 -0
- package/dist/transactions/confirmation/httpCommitEnvelope.js.map +1 -0
- package/dist/transactions/confirmation/idempotencyKey.d.ts.map +1 -0
- package/dist/transactions/confirmation/idempotencyKey.js.map +1 -0
- package/dist/transactions/{settlement → confirmation}/pendingWrite.d.ts +3 -2
- package/dist/transactions/confirmation/pendingWrite.d.ts.map +1 -0
- package/dist/transactions/confirmation/pendingWrite.js.map +1 -0
- package/dist/transport/commitFrames.d.ts +1 -0
- package/dist/transport/commitFrames.d.ts.map +1 -1
- package/dist/transport/commitFrames.js +8 -7
- package/dist/transport/commitFrames.js.map +1 -1
- package/dist/transport/connectionManager.d.ts +1 -1
- package/dist/transport/connectionManager.js +1 -1
- package/dist/transport/httpClient.d.ts +23 -9
- package/dist/transport/httpClient.d.ts.map +1 -1
- package/dist/transport/httpClient.js +134 -15
- package/dist/transport/httpClient.js.map +1 -1
- package/dist/transport/httpOptions.d.ts +9 -1
- package/dist/transport/httpOptions.d.ts.map +1 -1
- package/dist/transport/httpTransport.d.ts +3 -0
- package/dist/transport/httpTransport.d.ts.map +1 -1
- package/dist/transport/httpTransport.js +109 -22
- package/dist/transport/httpTransport.js.map +1 -1
- package/dist/transport/wsFrameHandlers.d.ts +3 -1
- package/dist/transport/wsFrameHandlers.d.ts.map +1 -1
- package/dist/transport/wsFrameHandlers.js +38 -17
- package/dist/transport/wsFrameHandlers.js.map +1 -1
- package/dist/transport/wsTransport.d.ts +3 -0
- package/dist/transport/wsTransport.d.ts.map +1 -1
- package/dist/transport/wsTransport.js +32 -1
- package/dist/transport/wsTransport.js.map +1 -1
- package/dist/utils/json.d.ts +1 -1
- package/dist/utils/json.js +1 -1
- package/dist/wire/accountResponses.d.ts +1 -1
- package/dist/wire/auth.d.ts +2 -2
- package/dist/wire/commit.d.ts +1652 -213
- package/dist/wire/commit.d.ts.map +1 -1
- package/dist/wire/commit.js +196 -132
- package/dist/wire/commit.js.map +1 -1
- package/dist/wire/delta.d.ts +1 -1
- package/dist/wire/errorEnvelope.d.ts +1 -0
- package/dist/wire/errorEnvelope.d.ts.map +1 -1
- package/dist/wire/errorEnvelope.js +1 -0
- package/dist/wire/errorEnvelope.js.map +1 -1
- package/dist/wire/feedCursor.d.ts +1 -1
- package/dist/wire/feedCursor.js +1 -1
- package/dist/wire/feedEvent.d.ts +3 -3
- package/dist/wire/frames.d.ts +8 -4
- package/dist/wire/frames.d.ts.map +1 -1
- package/dist/wire/frames.js +6 -3
- package/dist/wire/frames.js.map +1 -1
- package/dist/wire/inboundFrames.d.ts +44 -4
- package/dist/wire/inboundFrames.d.ts.map +1 -1
- package/dist/wire/index.d.ts +6 -4
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +6 -5
- package/dist/wire/index.js.map +1 -1
- package/dist/wire/modelMutations.d.ts +35 -0
- package/dist/wire/modelMutations.d.ts.map +1 -1
- package/dist/wire/modelMutations.js +9 -2
- package/dist/wire/modelMutations.js.map +1 -1
- package/dist/wire/modelResponses.d.ts +12 -1
- package/dist/wire/modelResponses.d.ts.map +1 -1
- package/dist/wire/modelResponses.js +12 -1
- package/dist/wire/modelResponses.js.map +1 -1
- package/package.json +12 -2
- package/src/ai-sdk/modelTools.ts +1 -1
- package/src/ai-sdk/updateTool.ts +2 -2
- package/src/auth/bootstrapScope.ts +1 -1
- package/src/auth/capability.ts +13 -4
- package/src/auth/capabilityLifecycle.ts +3 -2
- package/src/auth/identity.ts +16 -1
- package/src/auth/index.ts +2 -0
- package/src/auth/schemas.ts +3 -0
- package/src/auth/sessionMint.ts +0 -1
- package/src/branches.ts +27 -3
- package/src/commitRecordRuntime.ts +245 -0
- package/src/coordination/index.ts +24 -1
- package/src/coordination/locator.ts +17 -0
- package/src/coordination/schema.ts +114 -49
- package/src/coordination/targetConflict.ts +1 -1
- package/src/durableWrites.ts +3 -3
- package/src/errorCodes.ts +205 -25
- package/src/errorObservation.ts +121 -0
- package/src/errors.ts +5 -1
- package/src/footprint.ts +16 -27
- package/src/index.ts +8 -1
- package/src/internal/read-set.ts +18 -0
- package/src/logger.ts +1 -1
- package/src/observability.ts +1 -1
- package/src/readSetContext.ts +164 -0
- package/src/resources/functionalUpdate.ts +16 -4
- package/src/resources/httpResources.ts +27 -8
- package/src/resources/modelOperations.ts +2 -2
- package/src/resources/mutationOptions.ts +1 -1
- package/src/resources/where.ts +1 -1
- package/src/resources/writeOptionsSchema.ts +30 -12
- package/src/schema/index.ts +1 -1
- package/src/schema/openapi.ts +52 -11
- package/src/server/commit.ts +7 -1
- package/src/server/index.ts +5 -1
- package/src/source/adapters/kysely.ts +12 -4
- package/src/source/adapters/kyselyMutationCore.ts +14 -2
- package/src/source/index.ts +1 -1
- package/src/source/types.ts +1 -1
- package/src/testing/fixtures/httpResponses.ts +60 -1
- package/src/transactionLayer.ts +1 -1
- package/src/transactions/{settlement → confirmation}/commitEnvelope.ts +13 -3
- package/src/transport/commitFrames.ts +7 -5
- package/src/transport/connectionManager.ts +1 -1
- package/src/transport/httpClient.ts +256 -29
- package/src/transport/httpOptions.ts +9 -1
- package/src/transport/httpTransport.ts +139 -27
- package/src/transport/wsFrameHandlers.ts +46 -8
- package/src/transport/wsTransport.ts +42 -1
- package/src/utils/json.ts +1 -1
- package/src/wire/commit.ts +248 -147
- package/src/wire/errorEnvelope.ts +1 -0
- package/src/wire/feedCursor.ts +1 -1
- package/src/wire/frames.ts +9 -4
- package/src/wire/index.ts +38 -5
- package/src/wire/modelMutations.ts +16 -2
- package/src/wire/modelResponses.ts +14 -1
- package/dist/transactions/settlement/commitEnvelope.d.ts.map +0 -1
- package/dist/transactions/settlement/commitEnvelope.js.map +0 -1
- package/dist/transactions/settlement/httpCommitEnvelope.d.ts.map +0 -1
- package/dist/transactions/settlement/httpCommitEnvelope.js.map +0 -1
- package/dist/transactions/settlement/idempotencyKey.d.ts.map +0 -1
- package/dist/transactions/settlement/idempotencyKey.js.map +0 -1
- package/dist/transactions/settlement/pendingWrite.d.ts.map +0 -1
- package/dist/transactions/settlement/pendingWrite.js.map +0 -1
- /package/dist/transactions/{settlement → confirmation}/httpCommitEnvelope.d.ts +0 -0
- /package/dist/transactions/{settlement → confirmation}/httpCommitEnvelope.js +0 -0
- /package/dist/transactions/{settlement → confirmation}/idempotencyKey.d.ts +0 -0
- /package/dist/transactions/{settlement → confirmation}/idempotencyKey.js +0 -0
- /package/dist/transactions/{settlement → confirmation}/pendingWrite.js +0 -0
- /package/src/transactions/{settlement → confirmation}/httpCommitEnvelope.ts +0 -0
- /package/src/transactions/{settlement → confirmation}/idempotencyKey.ts +0 -0
- /package/src/transactions/{settlement → confirmation}/pendingWrite.ts +0 -0
|
@@ -267,6 +267,17 @@ const streamTargetSchema = targetRefSchema
|
|
|
267
267
|
export const onStaleModeSchema = z.enum(['reject', 'overwrite', 'notify']);
|
|
268
268
|
export type OnStaleMode = z.infer<typeof onStaleModeSchema>;
|
|
269
269
|
|
|
270
|
+
/** The exact authoritative position retained for one ReadSet entry. */
|
|
271
|
+
export const readSetWatermarkSchema = z.number().int().nonnegative();
|
|
272
|
+
export type ReadSetWatermark = z.infer<typeof readSetWatermarkSchema>;
|
|
273
|
+
|
|
274
|
+
/** Maximum decision-input entries one logical commit may ask the server to scan. */
|
|
275
|
+
export const MAX_READ_SET_ENTRIES = 500;
|
|
276
|
+
|
|
277
|
+
/** A persisted entry cannot overwrite: it observes future writes, not its own. */
|
|
278
|
+
export const trackOnStaleSchema = onStaleModeSchema.exclude(['overwrite']);
|
|
279
|
+
export type TrackOnStale = z.infer<typeof trackOnStaleSchema>;
|
|
280
|
+
|
|
270
281
|
/**
|
|
271
282
|
* The optimistic guard carried on a commit operation. `readAt` is the
|
|
272
283
|
* snapshot watermark from `context.capture` (null/absent ⇒ unguarded write).
|
|
@@ -274,7 +285,7 @@ export type OnStaleMode = z.infer<typeof onStaleModeSchema>;
|
|
|
274
285
|
* claim — see the claim layer below.
|
|
275
286
|
*/
|
|
276
287
|
export const writeGuardSchema = z.object({
|
|
277
|
-
readAt:
|
|
288
|
+
readAt: readSetWatermarkSchema.nullish(),
|
|
278
289
|
onStale: onStaleModeSchema.nullish(),
|
|
279
290
|
bypass: z.boolean().optional(),
|
|
280
291
|
});
|
|
@@ -445,42 +456,79 @@ export const staleNotificationSchema = z.discriminatedUnion('scope', [
|
|
|
445
456
|
]);
|
|
446
457
|
export type StaleNotification = z.infer<typeof staleNotificationSchema>;
|
|
447
458
|
|
|
448
|
-
/**
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
* write-target check, which only validates the rows being written. The server
|
|
452
|
-
* re-runs stale detection against each entry at its `readAt`; a moved premise
|
|
453
|
-
* fires the entry's `onStale` disposition (default `reject`) across the whole
|
|
454
|
-
* batch (`notify` holds every write and notifies, `reject` aborts, `overwrite`
|
|
455
|
-
* proceeds silently). An entry comes at one of two granularities:
|
|
456
|
-
*
|
|
457
|
-
* • Row — `{ model, id, readAt, fields? }`: did this specific row, or these
|
|
458
|
-
* specific fields, change?
|
|
459
|
-
* • Group — `{ group, readAt }`: did anything in this sync group change?
|
|
460
|
-
* `group` is a sync-group key such as `report:abc` or `section:s1`, the
|
|
461
|
-
* same unit a participant watches and claims.
|
|
462
|
-
*
|
|
463
|
-
* See `packages/ablo/docs/concurrency-convention.md` (§4) for the
|
|
464
|
-
* governing convention and the receive → reconcile loop.
|
|
465
|
-
*/
|
|
466
|
-
const readRowDependencySchema = z.object({
|
|
459
|
+
/** One row named by a commit-lifetime ReadSet entry. */
|
|
460
|
+
export const readSetRowTargetSchema = z.object({
|
|
461
|
+
scope: z.literal('row'),
|
|
467
462
|
model: z.string(),
|
|
468
463
|
id: z.string(),
|
|
469
|
-
readAt: z.number(),
|
|
470
464
|
fields: z.array(z.string()).readonly().optional(),
|
|
471
|
-
onStale: onStaleModeSchema.optional(),
|
|
472
465
|
});
|
|
466
|
+
export type ReadSetRowTarget = z.infer<typeof readSetRowTargetSchema>;
|
|
473
467
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
* type-checks inline, `'nonsense'` does not. The
|
|
478
|
-
* {@link groupStaleNotificationSchema} this premise fires uses the branded
|
|
479
|
-
* view, because there Ablo is the author.
|
|
480
|
-
*/
|
|
468
|
+
/** One sync group named by a ReadSet entry. */
|
|
469
|
+
export const readSetGroupTargetSchema = z.object({
|
|
470
|
+
scope: z.literal('group'),
|
|
481
471
|
group: syncGroupRefSchema,
|
|
482
|
-
|
|
483
|
-
|
|
472
|
+
});
|
|
473
|
+
export type ReadSetGroupTarget = z.infer<typeof readSetGroupTargetSchema>;
|
|
474
|
+
|
|
475
|
+
export const commitReadSetTargetSchema = z.discriminatedUnion('scope', [
|
|
476
|
+
readSetRowTargetSchema,
|
|
477
|
+
readSetGroupTargetSchema,
|
|
478
|
+
]);
|
|
479
|
+
export type CommitReadSetTarget = z.infer<typeof commitReadSetTargetSchema>;
|
|
480
|
+
|
|
481
|
+
/** Persisted row tracking is row-grained; it has no field storage axis. */
|
|
482
|
+
export const persistedReadSetRowTargetSchema = readSetRowTargetSchema.omit({ fields: true });
|
|
483
|
+
export const persistedReadSetTargetSchema = z.discriminatedUnion('scope', [
|
|
484
|
+
persistedReadSetRowTargetSchema,
|
|
485
|
+
readSetGroupTargetSchema,
|
|
486
|
+
]);
|
|
487
|
+
export type PersistedReadSetTarget = z.infer<typeof persistedReadSetTargetSchema>;
|
|
488
|
+
|
|
489
|
+
/** One exact input to the decision made by this commit. */
|
|
490
|
+
export const commitReadSetEntrySchema = z.object({
|
|
491
|
+
target: commitReadSetTargetSchema,
|
|
492
|
+
watermark: readSetWatermarkSchema,
|
|
493
|
+
lifetime: z.literal('commit'),
|
|
494
|
+
onStale: onStaleModeSchema,
|
|
495
|
+
});
|
|
496
|
+
export type CommitReadSetEntry = z.infer<typeof commitReadSetEntrySchema>;
|
|
497
|
+
|
|
498
|
+
/** One exact input retained after the declaring commit settles. */
|
|
499
|
+
export const persistedReadSetEntrySchema = z.object({
|
|
500
|
+
target: persistedReadSetTargetSchema,
|
|
501
|
+
watermark: readSetWatermarkSchema,
|
|
502
|
+
lifetime: z.literal('persisted'),
|
|
503
|
+
onStale: trackOnStaleSchema,
|
|
504
|
+
});
|
|
505
|
+
export type PersistedReadSetEntry = z.infer<typeof persistedReadSetEntrySchema>;
|
|
506
|
+
|
|
507
|
+
export const readSetEntrySchema = z.discriminatedUnion('lifetime', [
|
|
508
|
+
commitReadSetEntrySchema,
|
|
509
|
+
persistedReadSetEntrySchema,
|
|
510
|
+
]);
|
|
511
|
+
export type ReadSetEntry = z.infer<typeof readSetEntrySchema>;
|
|
512
|
+
|
|
513
|
+
export const readSetSchema = z
|
|
514
|
+
.array(readSetEntrySchema)
|
|
515
|
+
.max(MAX_READ_SET_ENTRIES)
|
|
516
|
+
.readonly();
|
|
517
|
+
export type ReadSet = z.infer<typeof readSetSchema>;
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Wire projection of a commit-lifetime ReadSet entry. The public field names
|
|
521
|
+
* stay compatible (`readAt`, flat row/group target); every member is selected
|
|
522
|
+
* from the canonical entry rather than restated beside it.
|
|
523
|
+
*/
|
|
524
|
+
const readRowDependencySchema = readSetRowTargetSchema.omit({ scope: true }).extend({
|
|
525
|
+
readAt: commitReadSetEntrySchema.shape.watermark,
|
|
526
|
+
onStale: commitReadSetEntrySchema.shape.onStale.optional(),
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
const readGroupDependencySchema = readSetGroupTargetSchema.omit({ scope: true }).extend({
|
|
530
|
+
readAt: commitReadSetEntrySchema.shape.watermark,
|
|
531
|
+
onStale: commitReadSetEntrySchema.shape.onStale.optional(),
|
|
484
532
|
});
|
|
485
533
|
|
|
486
534
|
export const readDependencySchema = z.union([
|
|
@@ -490,14 +538,14 @@ export const readDependencySchema = z.union([
|
|
|
490
538
|
export type ReadDependency = z.infer<typeof readDependencySchema>;
|
|
491
539
|
|
|
492
540
|
/**
|
|
493
|
-
* A durable
|
|
541
|
+
* A durable ReadSet entry — what a participant is watching so that a later
|
|
494
542
|
* change to it opens a {@link StaleNotification}. Where a {@link ReadDependency}
|
|
495
543
|
* is checked once at commit and discarded, a `TrackDependency` is kept and
|
|
496
544
|
* re-checked against every future delta. The row form watches one object; the
|
|
497
545
|
* group form watches a whole sync group ("anything in `report:abc`"). See
|
|
498
546
|
* `packages/ablo/docs/groups.md` for how it drives change propagation.
|
|
499
547
|
*
|
|
500
|
-
* It is a
|
|
548
|
+
* It is a projection of the canonical persisted entry, not a second declaration of the
|
|
501
549
|
* same reference: a track names its target exactly as a read does, and the
|
|
502
550
|
* three ways it differs are stated here as omissions the compiler holds.
|
|
503
551
|
*
|
|
@@ -514,18 +562,10 @@ export type ReadDependency = z.infer<typeof readDependencySchema>;
|
|
|
514
562
|
* registered the track, so a caller with nothing to say about when it last
|
|
515
563
|
* looked gets "from here on".
|
|
516
564
|
*
|
|
517
|
-
* A field added to the
|
|
565
|
+
* A field added to the ReadSet target reaches both halves; a field the durable half
|
|
518
566
|
* genuinely cannot carry has to be omitted here on purpose, in one line, rather
|
|
519
567
|
* than by being quietly left out of a copy.
|
|
520
568
|
*/
|
|
521
|
-
/**
|
|
522
|
-
* A track's disposition — the premise enum with `overwrite` subtracted, derived
|
|
523
|
-
* from it rather than spelled again, so a mode added to the convention reaches
|
|
524
|
-
* a track unless it is deliberately excluded here.
|
|
525
|
-
*/
|
|
526
|
-
export const trackOnStaleSchema = onStaleModeSchema.exclude(['overwrite']);
|
|
527
|
-
export type TrackOnStale = z.infer<typeof trackOnStaleSchema>;
|
|
528
|
-
|
|
529
569
|
/**
|
|
530
570
|
* What a track does when the caller says nothing — reporting, the behavior every
|
|
531
571
|
* track had before the disposition existed, so an existing registration is
|
|
@@ -539,18 +579,32 @@ export type TrackOnStale = z.infer<typeof trackOnStaleSchema>;
|
|
|
539
579
|
export const DEFAULT_TRACK_ON_STALE: TrackOnStale = 'notify';
|
|
540
580
|
|
|
541
581
|
const trackBaseSchema = {
|
|
542
|
-
readAt:
|
|
543
|
-
onStale:
|
|
582
|
+
readAt: persistedReadSetEntrySchema.shape.watermark.optional(),
|
|
583
|
+
onStale: persistedReadSetEntrySchema.shape.onStale.optional(),
|
|
544
584
|
} as const;
|
|
545
585
|
|
|
546
586
|
export const trackDependencySchema = z.union([
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
.extend(trackBaseSchema),
|
|
550
|
-
readGroupDependencySchema.omit({ onStale: true, readAt: true }).extend(trackBaseSchema),
|
|
587
|
+
persistedReadSetRowTargetSchema.omit({ scope: true }).extend(trackBaseSchema),
|
|
588
|
+
readSetGroupTargetSchema.omit({ scope: true }).extend(trackBaseSchema),
|
|
551
589
|
]);
|
|
552
590
|
export type TrackDependency = z.infer<typeof trackDependencySchema>;
|
|
553
591
|
|
|
592
|
+
/** Bounded wire projections of the two ReadSet lifetimes. */
|
|
593
|
+
export const readDependencyListSchema = z
|
|
594
|
+
.array(readDependencySchema)
|
|
595
|
+
.max(MAX_READ_SET_ENTRIES);
|
|
596
|
+
export const trackDependencyListSchema = z
|
|
597
|
+
.array(trackDependencySchema)
|
|
598
|
+
.max(MAX_READ_SET_ENTRIES);
|
|
599
|
+
|
|
600
|
+
/** Shared combined-cardinality rule for envelopes carrying both projections. */
|
|
601
|
+
export function readSetProjectionEntryCount(value: {
|
|
602
|
+
readonly reads?: readonly unknown[] | null;
|
|
603
|
+
readonly track?: readonly unknown[] | null;
|
|
604
|
+
}): number {
|
|
605
|
+
return (value.reads?.length ?? 0) + (value.track?.length ?? 0);
|
|
606
|
+
}
|
|
607
|
+
|
|
554
608
|
// ─────────────────────────────────────────────────────────────────────────
|
|
555
609
|
// Layer 2 — pessimistic claims and leases
|
|
556
610
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -1328,7 +1382,12 @@ export type UpdateSubscriptionPayload = z.infer<
|
|
|
1328
1382
|
export const subscriptionAckPayloadSchema = z.object({
|
|
1329
1383
|
success: z.boolean(),
|
|
1330
1384
|
syncGroups: z.array(z.string()),
|
|
1331
|
-
error: z.object({
|
|
1385
|
+
error: z.object({
|
|
1386
|
+
code: z.string(),
|
|
1387
|
+
message: z.string(),
|
|
1388
|
+
request_id: z.string().optional(),
|
|
1389
|
+
event_id: z.string().optional(),
|
|
1390
|
+
}).optional(),
|
|
1332
1391
|
});
|
|
1333
1392
|
export type SubscriptionAckPayload = z.infer<
|
|
1334
1393
|
typeof subscriptionAckPayloadSchema
|
|
@@ -1360,6 +1419,12 @@ export const commitOperationSchema = writeGuardSchema.extend({
|
|
|
1360
1419
|
input: z.record(z.string(), z.unknown()).nullish(),
|
|
1361
1420
|
/** Per-op client tx id, echoed on the broadcast delta. */
|
|
1362
1421
|
transactionId: z.string().nullish(),
|
|
1422
|
+
/**
|
|
1423
|
+
* The server-issued claim identity this operation was performed under.
|
|
1424
|
+
* Distinct from `transactionId`: a claim attributes and fences coordinated
|
|
1425
|
+
* ownership, while a transaction id correlates the resulting source echo.
|
|
1426
|
+
*/
|
|
1427
|
+
claimId: z.string().min(1).nullish(),
|
|
1363
1428
|
/**
|
|
1364
1429
|
* The fencing token from the held claim this write belongs to (Option B).
|
|
1365
1430
|
* Present only on a write issued under a claim that was granted one; the
|
|
@@ -12,7 +12,7 @@ import type { ClaimTargetDetails } from './locator.js';
|
|
|
12
12
|
* two places to land and no way to notice when it landed in one. It is one
|
|
13
13
|
* definition here, and both authorities import it.
|
|
14
14
|
*
|
|
15
|
-
* It lives in the
|
|
15
|
+
* It lives in the confirmation core rather than the server because it is the rule
|
|
16
16
|
* itself, not a deployment of it: a claim authority running against a
|
|
17
17
|
* developer's own database has to answer this question exactly the same way,
|
|
18
18
|
* and a client that wants to predict a refusal before paying for the round trip
|
package/src/durableWrites.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Owns the persistence contract behind `Ablo({ durableWrites })` — a behavior
|
|
5
5
|
* contract of methods, not a serialized shape, which is why it lives here
|
|
6
|
-
* rather than in `transactions/
|
|
6
|
+
* rather than in `transactions/confirmation/`. The records that cross this port
|
|
7
7
|
* are owned by `pendingWriteSchema` there; this module never redescribes them.
|
|
8
8
|
*
|
|
9
9
|
* The engine consumes the port through `commitOutboxStore`, and the HTTP client
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
import { z } from 'zod';
|
|
14
14
|
import { AbloValidationError } from './errors.js';
|
|
15
|
-
import type { CommitOutboxScope } from './transactions/
|
|
16
|
-
import type { PendingWrite } from './transactions/
|
|
15
|
+
import type { CommitOutboxScope } from './transactions/confirmation/commitEnvelope.js';
|
|
16
|
+
import type { PendingWrite } from './transactions/confirmation/pendingWrite.js';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Persistence port used by `Ablo({ durableWrites })`.
|
package/src/errorCodes.ts
CHANGED
|
@@ -39,7 +39,7 @@ import { z } from 'zod';
|
|
|
39
39
|
* error documentation and returned on the `Ablo-Version` response header, so a
|
|
40
40
|
* consumer can detect when its expected contract has drifted from the server's.
|
|
41
41
|
*/
|
|
42
|
-
export const ERROR_CONTRACT_VERSION = '2026-
|
|
42
|
+
export const ERROR_CONTRACT_VERSION = '2026-08-04';
|
|
43
43
|
|
|
44
44
|
/** A coarse grouping of error codes, used to organize metrics and documentation. */
|
|
45
45
|
export type ErrorCategory =
|
|
@@ -129,6 +129,36 @@ export interface ErrorCodeSpec {
|
|
|
129
129
|
* this field can be left unset.
|
|
130
130
|
*/
|
|
131
131
|
readonly recovery?: RecoveryClass;
|
|
132
|
+
/** Exhaustive sink and alert policy for this code. */
|
|
133
|
+
readonly observability: ErrorObservabilityPolicy;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface ErrorObservabilityPolicy {
|
|
137
|
+
readonly severity: 'info' | 'warning' | 'error' | 'fatal';
|
|
138
|
+
readonly sentry: 'log' | 'issue';
|
|
139
|
+
readonly pagingEligible: boolean;
|
|
140
|
+
readonly expectedVolume: 'low' | 'normal' | 'high';
|
|
141
|
+
readonly owner: 'platform' | 'product';
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function observabilityPolicy(
|
|
145
|
+
category: ErrorCategory,
|
|
146
|
+
httpStatus: number | undefined,
|
|
147
|
+
operational = false,
|
|
148
|
+
): ErrorObservabilityPolicy {
|
|
149
|
+
if ((httpStatus ?? 0) >= 500) {
|
|
150
|
+
return { severity: 'error', sentry: 'issue', pagingEligible: true, expectedVolume: 'low', owner: 'platform' };
|
|
151
|
+
}
|
|
152
|
+
if (operational) {
|
|
153
|
+
return { severity: 'warning', sentry: 'issue', pagingEligible: false, expectedVolume: 'low', owner: 'platform' };
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
severity: category === 'auth' ? 'info' : 'warning',
|
|
157
|
+
sentry: 'log',
|
|
158
|
+
pagingEligible: false,
|
|
159
|
+
expectedVolume: category === 'auth' ? 'high' : 'normal',
|
|
160
|
+
owner: 'product',
|
|
161
|
+
};
|
|
132
162
|
}
|
|
133
163
|
|
|
134
164
|
const wire = (
|
|
@@ -136,8 +166,17 @@ const wire = (
|
|
|
136
166
|
httpStatus: number,
|
|
137
167
|
retryable: boolean,
|
|
138
168
|
message: string,
|
|
139
|
-
recovery?: RecoveryClass
|
|
140
|
-
|
|
169
|
+
recovery?: RecoveryClass,
|
|
170
|
+
operational = false,
|
|
171
|
+
): ErrorCodeSpec => ({
|
|
172
|
+
category,
|
|
173
|
+
surface: 'wire',
|
|
174
|
+
httpStatus,
|
|
175
|
+
retryable,
|
|
176
|
+
message,
|
|
177
|
+
recovery,
|
|
178
|
+
observability: observabilityPolicy(category, httpStatus, operational),
|
|
179
|
+
});
|
|
141
180
|
|
|
142
181
|
const client = (
|
|
143
182
|
category: ErrorCategory,
|
|
@@ -147,6 +186,7 @@ const client = (
|
|
|
147
186
|
category,
|
|
148
187
|
surface: 'client',
|
|
149
188
|
retryable: false,
|
|
189
|
+
observability: observabilityPolicy(category, undefined),
|
|
150
190
|
message,
|
|
151
191
|
...(recovery !== undefined ? { recovery } : {}),
|
|
152
192
|
});
|
|
@@ -234,6 +274,18 @@ export const ERROR_CODES = {
|
|
|
234
274
|
'Your session has expired or is no longer valid. Sign in again to continue.',
|
|
235
275
|
'session_expiry'
|
|
236
276
|
),
|
|
277
|
+
better_auth_request_failed: wire(
|
|
278
|
+
'auth',
|
|
279
|
+
400,
|
|
280
|
+
false,
|
|
281
|
+
'The authentication request was rejected. Check the submitted credentials or request and try again.'
|
|
282
|
+
),
|
|
283
|
+
better_auth_upstream_failed: wire(
|
|
284
|
+
'server',
|
|
285
|
+
500,
|
|
286
|
+
true,
|
|
287
|
+
'The authentication service could not complete the request. Retry the request; if it continues to fail, contact support.'
|
|
288
|
+
),
|
|
237
289
|
// `jwt_invalid` is the general fallback; the codes below it split out specific
|
|
238
290
|
// failure modes, so an integrator can tell a wrong JWKS registration from a
|
|
239
291
|
// token with no organization claim from a wrong audience, instead of getting
|
|
@@ -319,6 +371,18 @@ export const ERROR_CODES = {
|
|
|
319
371
|
false,
|
|
320
372
|
'This deployment does not accept direct connection-string data sources. Register a signed Data Source endpoint instead.'
|
|
321
373
|
),
|
|
374
|
+
source_connector_localhost_required: wire(
|
|
375
|
+
'validation',
|
|
376
|
+
400,
|
|
377
|
+
false,
|
|
378
|
+
'A connector-only development Data Source must use a localhost descriptor. Use `ablo dev --local`; use the ordinary signed HTTPS endpoint registration for a deployed handler.'
|
|
379
|
+
),
|
|
380
|
+
source_connector_unauthenticated: wire(
|
|
381
|
+
'auth',
|
|
382
|
+
401,
|
|
383
|
+
false,
|
|
384
|
+
'The localhost Data Source connector could not authenticate. Rerun `ablo dev --local` so it mints and uses a fresh branch-bound secret key.'
|
|
385
|
+
),
|
|
322
386
|
|
|
323
387
|
// ── permission / capability (403) ──────────────────────────────────
|
|
324
388
|
capability_scope_denied: wire(
|
|
@@ -339,12 +403,6 @@ export const ERROR_CODES = {
|
|
|
339
403
|
false,
|
|
340
404
|
'This capability cannot be used — it is unknown, revoked, or expired. Request a fresh grant.'
|
|
341
405
|
),
|
|
342
|
-
test_database_not_registered: wire(
|
|
343
|
-
'permission',
|
|
344
|
-
403,
|
|
345
|
-
false,
|
|
346
|
-
'Test mode requires a registered dev database for this org — run `npx ablo init` to register one for your test key.'
|
|
347
|
-
),
|
|
348
406
|
tenant_routing_failed: wire(
|
|
349
407
|
'server',
|
|
350
408
|
500,
|
|
@@ -355,25 +413,37 @@ export const ERROR_CODES = {
|
|
|
355
413
|
'permission',
|
|
356
414
|
403,
|
|
357
415
|
false,
|
|
358
|
-
'The database role Ablo connects with is a superuser or has `BYPASSRLS`, so Postgres will not enforce row-level security for it. Connect with a role that is subject to RLS.'
|
|
416
|
+
'The database role Ablo connects with is a superuser or has `BYPASSRLS`, so Postgres will not enforce row-level security for it. Connect with a role that is subject to RLS.',
|
|
417
|
+
undefined,
|
|
418
|
+
true,
|
|
359
419
|
),
|
|
360
420
|
database_role_unreadable: wire(
|
|
361
421
|
'permission',
|
|
362
422
|
403,
|
|
363
423
|
false,
|
|
364
|
-
'Ablo could not introspect the database role it connects with, so it cannot verify that row-level security is enforced.'
|
|
424
|
+
'Ablo could not introspect the database role it connects with, so it cannot verify that row-level security is enforced.',
|
|
425
|
+
undefined,
|
|
426
|
+
true,
|
|
365
427
|
),
|
|
366
428
|
database_tables_unforced_rls: wire(
|
|
367
429
|
'permission',
|
|
368
430
|
403,
|
|
369
431
|
false,
|
|
370
|
-
'Some synced tables do not have `FORCE ROW LEVEL SECURITY` applied, so the table owner can bypass row isolation. Run `ALTER TABLE ... FORCE ROW LEVEL SECURITY` on each synced table.'
|
|
432
|
+
'Some synced tables do not have `FORCE ROW LEVEL SECURITY` applied, so the table owner can bypass row isolation. Run `ALTER TABLE ... FORCE ROW LEVEL SECURITY` on each synced table.',
|
|
433
|
+
undefined,
|
|
434
|
+
true,
|
|
371
435
|
),
|
|
372
436
|
database_host_not_allowed: wire(
|
|
373
437
|
'permission',
|
|
374
438
|
403,
|
|
375
439
|
false,
|
|
376
|
-
"The database host
|
|
440
|
+
"The database host did not resolve exclusively to an allowed address for this route. Use a publicly resolvable direct endpoint, or configure the matching PrivateLink, peering, or VPN route. Localhost has its own `database_loopback_requires_connector` workflow."
|
|
441
|
+
),
|
|
442
|
+
database_loopback_requires_connector: wire(
|
|
443
|
+
'validation',
|
|
444
|
+
400,
|
|
445
|
+
false,
|
|
446
|
+
'Ablo Cloud cannot open a direct PostgreSQL connection to localhost on your machine. For localhost-first development, run `ablo migrate` once and keep `ablo dev --local` running; use a network-reachable direct route only when Ablo must observe arbitrary SQL writes through WAL.'
|
|
377
447
|
),
|
|
378
448
|
connected_database_unreachable: wire(
|
|
379
449
|
'tenant',
|
|
@@ -430,7 +500,7 @@ export const ERROR_CODES = {
|
|
|
430
500
|
'claim',
|
|
431
501
|
409,
|
|
432
502
|
false,
|
|
433
|
-
'This
|
|
503
|
+
'This claim is no longer current because another participant completed newer work on the row. Re-claim the row and retry from the fresh state.'
|
|
434
504
|
),
|
|
435
505
|
entity_claimed: wire(
|
|
436
506
|
'claim',
|
|
@@ -486,7 +556,7 @@ export const ERROR_CODES = {
|
|
|
486
556
|
),
|
|
487
557
|
model_claim_not_configured: client(
|
|
488
558
|
'claim',
|
|
489
|
-
'Claiming
|
|
559
|
+
'Claiming is unavailable on this model client. Construct it through the standard Ablo({ schema, apiKey }) client and retry.'
|
|
490
560
|
),
|
|
491
561
|
model_join_not_configured: client(
|
|
492
562
|
'claim',
|
|
@@ -699,6 +769,18 @@ export const ERROR_CODES = {
|
|
|
699
769
|
false,
|
|
700
770
|
'The participant is not allowed to execute this mutator.'
|
|
701
771
|
),
|
|
772
|
+
source_connector_requires_secret_key: wire(
|
|
773
|
+
'permission',
|
|
774
|
+
403,
|
|
775
|
+
false,
|
|
776
|
+
'A Data Source reverse channel must authenticate with the branch-bound secret (`sk_`) key created by `ablo dev`; browser, ephemeral, restricted, and management keys cannot serve a database.'
|
|
777
|
+
),
|
|
778
|
+
source_connector_production_not_enabled: wire(
|
|
779
|
+
'permission',
|
|
780
|
+
403,
|
|
781
|
+
false,
|
|
782
|
+
'This production Data Source has not opted into reverse-channel transport. `ablo dev --local` is for child branches; use a direct production endpoint or explicitly enable the supported production reverse-channel route.'
|
|
783
|
+
),
|
|
702
784
|
|
|
703
785
|
// ── not found (404) ────────────────────────────────────────────────
|
|
704
786
|
entity_not_found: wire(
|
|
@@ -723,7 +805,15 @@ export const ERROR_CODES = {
|
|
|
723
805
|
'not_found',
|
|
724
806
|
404,
|
|
725
807
|
false,
|
|
726
|
-
'
|
|
808
|
+
'This branch is not connected to your database yet. Run `ablo connect` for a cloud-reachable direct Postgres endpoint, or `ablo dev --local` to register and serve a localhost Data Source, then retry.',
|
|
809
|
+
undefined,
|
|
810
|
+
true,
|
|
811
|
+
),
|
|
812
|
+
source_connector_no_source_registered: wire(
|
|
813
|
+
'not_found',
|
|
814
|
+
404,
|
|
815
|
+
false,
|
|
816
|
+
'The branch has no endpoint Data Source for this connector to serve. Run `ablo dev --local` with the current CLI, which registers the connector-only source before opening the socket.'
|
|
727
817
|
),
|
|
728
818
|
task_id_missing: wire(
|
|
729
819
|
'server',
|
|
@@ -978,7 +1068,55 @@ export const ERROR_CODES = {
|
|
|
978
1068
|
'transport',
|
|
979
1069
|
503,
|
|
980
1070
|
true,
|
|
981
|
-
'A network error occurred while talking to the data source.
|
|
1071
|
+
'A network error occurred while talking to the data source. For localhost mode, keep `ablo dev --local` running and check its connector output; for a direct source, check database connectivity and retry.'
|
|
1072
|
+
),
|
|
1073
|
+
source_request_failed: wire(
|
|
1074
|
+
'transport',
|
|
1075
|
+
502,
|
|
1076
|
+
true,
|
|
1077
|
+
'The signed Data Source returned a failure without a more specific code. Inspect the `ablo dev --local` process or deployed endpoint logs, then retry with the same idempotency key.'
|
|
1078
|
+
),
|
|
1079
|
+
source_connector_not_attached: wire(
|
|
1080
|
+
'transport',
|
|
1081
|
+
503,
|
|
1082
|
+
true,
|
|
1083
|
+
'This branch uses localhost connector-only storage, but no connector is attached. Start or restart `ablo dev --local` and keep that process running.'
|
|
1084
|
+
),
|
|
1085
|
+
source_connector_timeout: wire(
|
|
1086
|
+
'transport',
|
|
1087
|
+
504,
|
|
1088
|
+
true,
|
|
1089
|
+
'The local Data Source handler did not answer before the connector deadline. Check the local Postgres connection and handler logs; the same idempotent request may be retried.'
|
|
1090
|
+
),
|
|
1091
|
+
source_connector_send_failed: wire(
|
|
1092
|
+
'transport',
|
|
1093
|
+
502,
|
|
1094
|
+
true,
|
|
1095
|
+
'The connector socket closed while Ablo was forwarding a signed Data Source request. Keep `ablo dev --local` running; Ablo retries after the connector reconnects.'
|
|
1096
|
+
),
|
|
1097
|
+
source_connector_disconnected: wire(
|
|
1098
|
+
'transport',
|
|
1099
|
+
503,
|
|
1100
|
+
true,
|
|
1101
|
+
'The localhost Data Source connector disconnected with a request in flight. The connector reconnects automatically; retry after it reports ready.'
|
|
1102
|
+
),
|
|
1103
|
+
source_connector_superseded: wire(
|
|
1104
|
+
'transport',
|
|
1105
|
+
503,
|
|
1106
|
+
true,
|
|
1107
|
+
'A newer localhost Data Source connector replaced this one. Stop duplicate `ablo dev --local` processes and use the newest process; in-flight requests are safe to retry.'
|
|
1108
|
+
),
|
|
1109
|
+
source_connector_shutdown: wire(
|
|
1110
|
+
'transport',
|
|
1111
|
+
503,
|
|
1112
|
+
true,
|
|
1113
|
+
'The Ablo service shut down the connector while a request was in flight. The connector reconnects automatically after the service returns.'
|
|
1114
|
+
),
|
|
1115
|
+
source_connector_protocol_error: wire(
|
|
1116
|
+
'transport',
|
|
1117
|
+
400,
|
|
1118
|
+
false,
|
|
1119
|
+
'The CLI and Ablo service disagreed on the Data Source connector frame protocol, or a malformed frame arrived. Upgrade the Ablo CLI and SDK together, then restart `ablo dev --local`.'
|
|
982
1120
|
),
|
|
983
1121
|
source_unreachable: wire(
|
|
984
1122
|
'transport',
|
|
@@ -990,7 +1128,19 @@ export const ERROR_CODES = {
|
|
|
990
1128
|
'transport',
|
|
991
1129
|
503,
|
|
992
1130
|
false,
|
|
993
|
-
"
|
|
1131
|
+
"This branch's database connection is not ready. Check its credentials and configuration; Ablo will not send reads or writes anywhere else."
|
|
1132
|
+
),
|
|
1133
|
+
source_connector_handler_error: wire(
|
|
1134
|
+
'server',
|
|
1135
|
+
500,
|
|
1136
|
+
true,
|
|
1137
|
+
'The local signed Data Source handler threw while processing a request. Read the `ablo dev --local` error immediately above it, fix the database or adapter failure, and retry.'
|
|
1138
|
+
),
|
|
1139
|
+
source_connector_internal_error: wire(
|
|
1140
|
+
'server',
|
|
1141
|
+
500,
|
|
1142
|
+
true,
|
|
1143
|
+
'Ablo could not establish the Data Source reverse channel because of an internal service failure. Retry; if it persists, report the request id.'
|
|
994
1144
|
),
|
|
995
1145
|
identity_network_error: wire(
|
|
996
1146
|
'transport',
|
|
@@ -1103,6 +1253,30 @@ export const ERROR_CODES = {
|
|
|
1103
1253
|
),
|
|
1104
1254
|
|
|
1105
1255
|
// ── server (5xx) ───────────────────────────────────────────────────
|
|
1256
|
+
session_check_failed: wire(
|
|
1257
|
+
'server',
|
|
1258
|
+
503,
|
|
1259
|
+
true,
|
|
1260
|
+
'Ablo could not verify the current login session. Retry shortly.'
|
|
1261
|
+
),
|
|
1262
|
+
mint_failed: wire(
|
|
1263
|
+
'server',
|
|
1264
|
+
502,
|
|
1265
|
+
true,
|
|
1266
|
+
'Ablo could not mint the requested runtime credential. Retry shortly.'
|
|
1267
|
+
),
|
|
1268
|
+
server_side_only: wire(
|
|
1269
|
+
'permission', 403, false, 'This endpoint is available only to trusted server-side callers.'
|
|
1270
|
+
),
|
|
1271
|
+
unknown_auth_host: wire(
|
|
1272
|
+
'auth', 400, false, 'The authentication host is not recognized.'
|
|
1273
|
+
),
|
|
1274
|
+
no_active_organization: wire(
|
|
1275
|
+
'tenant', 400, false, 'Select an active organization before continuing.'
|
|
1276
|
+
),
|
|
1277
|
+
data_session_unsupported: wire(
|
|
1278
|
+
'validation', 400, false, 'This sign-in host cannot create the requested data session.'
|
|
1279
|
+
),
|
|
1106
1280
|
internal_error: wire(
|
|
1107
1281
|
'server',
|
|
1108
1282
|
500,
|
|
@@ -1140,7 +1314,7 @@ export const ERROR_CODES = {
|
|
|
1140
1314
|
),
|
|
1141
1315
|
db_identity_mismatch: client(
|
|
1142
1316
|
'client',
|
|
1143
|
-
'The local database
|
|
1317
|
+
'The local database is connected to a different organization, project, or branch.'
|
|
1144
1318
|
),
|
|
1145
1319
|
db_cleanup_failed: client(
|
|
1146
1320
|
'client',
|
|
@@ -1306,19 +1480,19 @@ export const ERROR_CODES = {
|
|
|
1306
1480
|
'tenant',
|
|
1307
1481
|
400,
|
|
1308
1482
|
false,
|
|
1309
|
-
"This model
|
|
1483
|
+
"This model gets its tenant identity from the connected Data Source, but that connection is not ready for scoped reads yet. Ablo refused the read to prevent data from crossing tenant boundaries. Connect the branch and retry; for internally logged models, use `by: 'column'` or `by: 'parent'`."
|
|
1310
1484
|
),
|
|
1311
1485
|
user_scope_not_enforced: wire(
|
|
1312
1486
|
'tenant',
|
|
1313
1487
|
400,
|
|
1314
1488
|
false,
|
|
1315
|
-
"Rows in this model belong to one person rather than
|
|
1489
|
+
"Rows in this model belong to one person rather than the whole organization, but the current read source does not carry the owner identity needed to enforce that boundary. Ablo returned nothing to prevent one member from seeing another member's private records. Use a read source that preserves owner identity, or a credential that acts for the organization."
|
|
1316
1490
|
),
|
|
1317
1491
|
model_not_provisioned: wire(
|
|
1318
1492
|
'tenant',
|
|
1319
1493
|
409,
|
|
1320
1494
|
false,
|
|
1321
|
-
"This model is in the
|
|
1495
|
+
"This model is in the branch's registered schema, but its table does not exist in the connected database yet. `ablo push` records the model but does not change a customer's database. Apply the table migration in your database, then retry the read."
|
|
1322
1496
|
),
|
|
1323
1497
|
schema_table_invalid: wire('schema', 500, false, "The model's table identifier is invalid."),
|
|
1324
1498
|
schema_scope_invalid: wire(
|
|
@@ -1355,7 +1529,9 @@ export const ERROR_CODES = {
|
|
|
1355
1529
|
'permission',
|
|
1356
1530
|
403,
|
|
1357
1531
|
false,
|
|
1358
|
-
'Schema registration could not create tables in the target database: the engine is not permitted to run DDL there.'
|
|
1532
|
+
'Schema registration could not create tables in the target database: the engine is not permitted to run DDL there.',
|
|
1533
|
+
undefined,
|
|
1534
|
+
true,
|
|
1359
1535
|
),
|
|
1360
1536
|
model_query_failed: wire(
|
|
1361
1537
|
'validation',
|
|
@@ -1492,7 +1668,7 @@ export const ERROR_CODES = {
|
|
|
1492
1668
|
'not_found',
|
|
1493
1669
|
404,
|
|
1494
1670
|
false,
|
|
1495
|
-
'No claim of yours exists with the given id. It was released,
|
|
1671
|
+
'No claim of yours exists with the given id. It was released, expired, or belongs to a different branch.'
|
|
1496
1672
|
),
|
|
1497
1673
|
invalid_participant_kind: wire(
|
|
1498
1674
|
'validation',
|
|
@@ -1549,6 +1725,10 @@ export const ERROR_CODES = {
|
|
|
1549
1725
|
),
|
|
1550
1726
|
request_too_large: wire('validation', 413, false, 'The request body exceeds the maximum size.'),
|
|
1551
1727
|
invalid_schema: wire('validation', 400, false, 'The submitted schema could not be parsed.'),
|
|
1728
|
+
operational_warning: client(
|
|
1729
|
+
'server',
|
|
1730
|
+
'Ablo handled an operational degradation that remains searchable for diagnosis.'
|
|
1731
|
+
),
|
|
1552
1732
|
incompatible_change: wire(
|
|
1553
1733
|
'conflict',
|
|
1554
1734
|
409,
|
|
@@ -1559,7 +1739,7 @@ export const ERROR_CODES = {
|
|
|
1559
1739
|
'conflict',
|
|
1560
1740
|
409,
|
|
1561
1741
|
false,
|
|
1562
|
-
'
|
|
1742
|
+
'This branch has live replicated rows for a mapped model that disappeared. Declare a rename or an explicit drop/reset before advancing the schema.'
|
|
1563
1743
|
),
|
|
1564
1744
|
} as const satisfies Record<string, ErrorCodeSpec>;
|
|
1565
1745
|
|