@abloatai/transaction 0.39.0 → 0.41.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/dist/auth/index.d.ts +12 -3
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +14 -6
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/schemas.d.ts +1 -0
- package/dist/auth/schemas.d.ts.map +1 -1
- package/dist/auth/schemas.js +10 -2
- package/dist/auth/schemas.js.map +1 -1
- package/dist/coordination/events.d.ts +9 -0
- package/dist/coordination/events.d.ts.map +1 -1
- package/dist/coordination/index.d.ts +2 -2
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +1 -1
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/schema.d.ts +226 -34
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +180 -48
- package/dist/coordination/schema.js.map +1 -1
- package/dist/coordination/trace.d.ts.map +1 -1
- package/dist/coordination/trace.js +9 -1
- package/dist/coordination/trace.js.map +1 -1
- package/dist/errorCodes.d.ts +5 -0
- package/dist/errorCodes.d.ts.map +1 -1
- package/dist/errorCodes.js +10 -1
- package/dist/errorCodes.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +9 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/policy/types.d.ts +10 -2
- package/dist/policy/types.d.ts.map +1 -1
- package/dist/policy/types.js.map +1 -1
- package/dist/pricing.d.ts +194 -0
- package/dist/pricing.d.ts.map +1 -0
- package/dist/pricing.js +330 -0
- package/dist/pricing.js.map +1 -0
- package/dist/resources/functionalUpdate.d.ts.map +1 -1
- package/dist/resources/functionalUpdate.js +8 -8
- package/dist/resources/functionalUpdate.js.map +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/roles.d.ts +19 -0
- package/dist/schema/roles.d.ts.map +1 -1
- package/dist/schema/roles.js +23 -3
- package/dist/schema/roles.js.map +1 -1
- package/dist/schema/schema.d.ts +1 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +1 -1
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/tenancy.d.ts +1 -1
- package/dist/transactions/settlement/commitEnvelope.d.ts +10 -2
- package/dist/transactions/settlement/commitEnvelope.d.ts.map +1 -1
- package/dist/transactions/settlement/pendingWrite.d.ts +10 -2
- package/dist/transactions/settlement/pendingWrite.d.ts.map +1 -1
- package/dist/transport/wsFrameHandlers.d.ts.map +1 -1
- package/dist/transport/wsFrameHandlers.js +9 -3
- package/dist/transport/wsFrameHandlers.js.map +1 -1
- package/dist/wire/accountResponses.d.ts +100 -0
- package/dist/wire/accountResponses.d.ts.map +1 -1
- package/dist/wire/accountResponses.js +70 -0
- package/dist/wire/accountResponses.js.map +1 -1
- package/dist/wire/auth.d.ts +1 -0
- package/dist/wire/auth.d.ts.map +1 -1
- package/dist/wire/auth.js +16 -4
- package/dist/wire/auth.js.map +1 -1
- package/dist/wire/commit.d.ts +708 -100
- package/dist/wire/commit.d.ts.map +1 -1
- package/dist/wire/dataSourceResponses.d.ts +171 -0
- package/dist/wire/dataSourceResponses.d.ts.map +1 -0
- package/dist/wire/dataSourceResponses.js +168 -0
- package/dist/wire/dataSourceResponses.js.map +1 -0
- package/dist/wire/frames.d.ts +20 -4
- package/dist/wire/frames.d.ts.map +1 -1
- package/dist/wire/inboundFrames.d.ts +102 -14
- package/dist/wire/inboundFrames.d.ts.map +1 -1
- package/dist/wire/index.d.ts +4 -2
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +5 -1
- package/dist/wire/index.js.map +1 -1
- package/dist/wire/pricing.d.ts +43 -0
- package/dist/wire/pricing.d.ts.map +1 -0
- package/dist/wire/pricing.js +36 -0
- package/dist/wire/pricing.js.map +1 -0
- package/package.json +6 -1
- package/src/auth/index.ts +26 -9
- package/src/auth/schemas.ts +14 -3
- package/src/coordination/events.ts +9 -0
- package/src/coordination/index.ts +8 -0
- package/src/coordination/schema.ts +200 -51
- package/src/coordination/trace.ts +9 -1
- package/src/errorCodes.ts +30 -1
- package/src/errors.ts +9 -2
- package/src/index.ts +4 -0
- package/src/policy/types.ts +10 -2
- package/src/pricing.ts +350 -0
- package/src/resources/functionalUpdate.ts +11 -11
- package/src/schema/index.ts +2 -0
- package/src/schema/roles.ts +26 -3
- package/src/schema/schema.ts +2 -0
- package/src/transport/wsFrameHandlers.ts +9 -3
- package/src/wire/accountResponses.ts +76 -0
- package/src/wire/auth.ts +19 -4
- package/src/wire/dataSourceResponses.ts +188 -0
- package/src/wire/index.ts +33 -0
- package/src/wire/pricing.ts +41 -0
package/dist/wire/index.js
CHANGED
|
@@ -74,7 +74,11 @@ export { fieldTypeSchema, fieldMetaSchema, relationTypeSchema, relationMetaSchem
|
|
|
74
74
|
export { modelMutationRequestSchema } from './modelMutations.js';
|
|
75
75
|
// The account routes' responses — projects, the deployed schema, the commit
|
|
76
76
|
// log, usage. What the server, the CLI, and the MCP server agree on.
|
|
77
|
-
export { projectResponseSchema, projectListResponseSchema, provisionedKeySchema, provisionKeyResponseSchema, conflictAxisWireSchema, schemaModelResponseSchema, schemaReadResponseSchema, logOpSchema, LOG_OP_BY_ACTION, logEventSchema, usageBucketSchema, usageReportResponseSchema, controlKeySchema, controlKeyListResponseSchema, keyMintedResponseSchema, keyRevokedResponseSchema, } from './accountResponses.js';
|
|
77
|
+
export { projectResponseSchema, projectListResponseSchema, provisionedKeySchema, provisionKeyResponseSchema, conflictAxisWireSchema, schemaModelResponseSchema, schemaReadResponseSchema, logOpSchema, LOG_OP_BY_ACTION, logEventSchema, usageBucketSchema, usageReportResponseSchema, meterUsageSchema, billingSummarySchema, usageSummaryResponseSchema, controlKeySchema, controlKeyListResponseSchema, keyMintedResponseSchema, keyRevokedResponseSchema, } from './accountResponses.js';
|
|
78
|
+
// The datasource routes' responses — the `ablo connect` surface: register,
|
|
79
|
+
// validate, locate, list, deregister. What the server, the CLI, and the
|
|
80
|
+
// dashboard agree on.
|
|
81
|
+
export { READINESS_ITEMS, READINESS_ADVISORY_ITEMS, isReadinessItem, readinessFailureSchema, readinessAdvisorySchema, datasourceSummarySchema, datasourceListResponseSchema, datasourceValidationResponseSchema, datasourceLocationResponseSchema, datasourceDisconnectedResponseSchema, } from './dataSourceResponses.js';
|
|
78
82
|
// The inbound socket surface: every frame the server can send, and how each
|
|
79
83
|
// one's payload is validated.
|
|
80
84
|
export { WS_INBOUND_FRAMES, wsInboundEnvelopeSchema, isKnownInboundFrame, isSchemaValidatedFrame, } from './inboundFrames.js';
|
package/dist/wire/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wire/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wire/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pricing vocabulary that crosses the wire: the tier names, the meter
|
|
3
|
+
* names, and the shape of one rate-card step. Account responses carry these,
|
|
4
|
+
* so they live in the dependency-free wire layer; the pricing contract
|
|
5
|
+
* (`../pricing.ts`) derives the rate card, the plans, and the bill arithmetic
|
|
6
|
+
* from them and re-exports them for its consumers.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
export declare const planTierSchema: z.ZodEnum<{
|
|
10
|
+
free: "free";
|
|
11
|
+
scale: "scale";
|
|
12
|
+
enterprise: "enterprise";
|
|
13
|
+
}>;
|
|
14
|
+
export type PlanTier = z.infer<typeof planTierSchema>;
|
|
15
|
+
/**
|
|
16
|
+
* Every meter the engine records, over any transport. This is the closed set
|
|
17
|
+
* behind the loose `eventName` strings that `UsageRecorder` and the quota gate
|
|
18
|
+
* pass around.
|
|
19
|
+
*
|
|
20
|
+
* Recording and pricing are separate questions. A meter exists so usage can be
|
|
21
|
+
* gated and attributed; whether it reaches an invoice is `METER_EVENT_AXIS`.
|
|
22
|
+
* Bootstraps are recorded and quota-gated but deliberately unpriced: a bootstrap
|
|
23
|
+
* is what a client does once to become useful, and charging for it would price
|
|
24
|
+
* the act of connecting.
|
|
25
|
+
*/
|
|
26
|
+
export declare const meterEventSchema: z.ZodEnum<{
|
|
27
|
+
"api.commit_ops": "api.commit_ops";
|
|
28
|
+
"api.model_reads": "api.model_reads";
|
|
29
|
+
"api.claim_creates": "api.claim_creates";
|
|
30
|
+
"api.bootstraps": "api.bootstraps";
|
|
31
|
+
}>;
|
|
32
|
+
export type MeterEvent = z.infer<typeof meterEventSchema>;
|
|
33
|
+
/**
|
|
34
|
+
* One step of the rate card. `throughOps` is the cumulative ceiling the rate
|
|
35
|
+
* applies up to, and `null` marks the final, unbounded step. Rates are marginal:
|
|
36
|
+
* crossing a ceiling reprices the operations above it, never the ones below.
|
|
37
|
+
*/
|
|
38
|
+
export declare const rateBracketSchema: z.ZodObject<{
|
|
39
|
+
throughOps: z.ZodNullable<z.ZodNumber>;
|
|
40
|
+
usdPerMillionOps: z.ZodNumber;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
export type RateBracket = z.infer<typeof rateBracketSchema>;
|
|
43
|
+
//# sourceMappingURL=pricing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/wire/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,cAAc;;;;EAA0C,CAAC;AACtE,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB;;;;;EAK3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pricing vocabulary that crosses the wire: the tier names, the meter
|
|
3
|
+
* names, and the shape of one rate-card step. Account responses carry these,
|
|
4
|
+
* so they live in the dependency-free wire layer; the pricing contract
|
|
5
|
+
* (`../pricing.ts`) derives the rate card, the plans, and the bill arithmetic
|
|
6
|
+
* from them and re-exports them for its consumers.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
export const planTierSchema = z.enum(['free', 'scale', 'enterprise']);
|
|
10
|
+
/**
|
|
11
|
+
* Every meter the engine records, over any transport. This is the closed set
|
|
12
|
+
* behind the loose `eventName` strings that `UsageRecorder` and the quota gate
|
|
13
|
+
* pass around.
|
|
14
|
+
*
|
|
15
|
+
* Recording and pricing are separate questions. A meter exists so usage can be
|
|
16
|
+
* gated and attributed; whether it reaches an invoice is `METER_EVENT_AXIS`.
|
|
17
|
+
* Bootstraps are recorded and quota-gated but deliberately unpriced: a bootstrap
|
|
18
|
+
* is what a client does once to become useful, and charging for it would price
|
|
19
|
+
* the act of connecting.
|
|
20
|
+
*/
|
|
21
|
+
export const meterEventSchema = z.enum([
|
|
22
|
+
'api.commit_ops',
|
|
23
|
+
'api.model_reads',
|
|
24
|
+
'api.claim_creates',
|
|
25
|
+
'api.bootstraps',
|
|
26
|
+
]);
|
|
27
|
+
/**
|
|
28
|
+
* One step of the rate card. `throughOps` is the cumulative ceiling the rate
|
|
29
|
+
* applies up to, and `null` marks the final, unbounded step. Rates are marginal:
|
|
30
|
+
* crossing a ceiling reprices the operations above it, never the ones below.
|
|
31
|
+
*/
|
|
32
|
+
export const rateBracketSchema = z.object({
|
|
33
|
+
throughOps: z.number().int().positive().nullable(),
|
|
34
|
+
usdPerMillionOps: z.number().nonnegative(),
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/wire/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;AAGtE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC;IACrC,gBAAgB;IAChB,iBAAiB;IACjB,mBAAmB;IACnB,gBAAgB;CACjB,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAClD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE;CAC3C,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abloatai/transaction",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.41.0",
|
|
4
4
|
"description": "The headless Ablo transaction client and canonical contracts for reads, commits, settlement, claims, and durable observation.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"import": "./dist/errorCodes.js",
|
|
18
18
|
"default": "./dist/errorCodes.js"
|
|
19
19
|
},
|
|
20
|
+
"./pricing": {
|
|
21
|
+
"types": "./dist/pricing.d.ts",
|
|
22
|
+
"import": "./dist/pricing.js",
|
|
23
|
+
"default": "./dist/pricing.js"
|
|
24
|
+
},
|
|
20
25
|
"./environment": {
|
|
21
26
|
"types": "./dist/environment.d.ts",
|
|
22
27
|
"import": "./dist/environment.js",
|
package/src/auth/index.ts
CHANGED
|
@@ -241,16 +241,25 @@ interface MintUserSessionBase {
|
|
|
241
241
|
* for organizations whose schemas it does not own has no way to name their
|
|
242
242
|
* models, and a grant is checked against the session's schema at mint time. The
|
|
243
243
|
* server expands the verbs across that schema and stores the same enumerated
|
|
244
|
-
* `model.verb` allowlist either way.
|
|
244
|
+
* `model.verb` allowlist either way. The third form grants no data operations
|
|
245
|
+
* at all, for a session that only proves identity to control-plane surfaces —
|
|
246
|
+
* it involves no schema, so it mints even for an organization that has not
|
|
247
|
+
* pushed one yet.
|
|
245
248
|
*/
|
|
246
249
|
export type MintUserSessionRequest = MintUserSessionBase & {
|
|
247
|
-
/** The allowlist, named model by model. Provide
|
|
250
|
+
/** The allowlist, named model by model. Provide exactly one grant form. */
|
|
248
251
|
readonly operations?: readonly GrantedOperation[];
|
|
249
252
|
/**
|
|
250
253
|
* The allowlist as verbs alone, expanded by the server across the models in
|
|
251
|
-
* the session's active schema. Provide
|
|
254
|
+
* the session's active schema. Provide exactly one grant form.
|
|
252
255
|
*/
|
|
253
256
|
readonly activeSchemaOperations?: readonly CapabilityOperation[];
|
|
257
|
+
/**
|
|
258
|
+
* No data operations: the session proves who the user is to control-plane
|
|
259
|
+
* surfaces (the dashboard, credential provisioning) and can touch no
|
|
260
|
+
* application data. Provide exactly one grant form.
|
|
261
|
+
*/
|
|
262
|
+
readonly controlPlaneOnly?: true;
|
|
254
263
|
};
|
|
255
264
|
|
|
256
265
|
/**
|
|
@@ -278,13 +287,19 @@ export async function mintUserSessionKey(
|
|
|
278
287
|
{ code: 'base_url_missing' },
|
|
279
288
|
);
|
|
280
289
|
}
|
|
281
|
-
// Exactly one grant form.
|
|
290
|
+
// Exactly one grant form. Several would be two answers to one question; none
|
|
282
291
|
// would send an empty allowlist, and an empty allowlist is read as
|
|
283
292
|
// unrestricted rather than as nothing. The server refuses either way; this
|
|
284
293
|
// says so before the round trip, where the caller can see which call did it.
|
|
285
|
-
|
|
294
|
+
const grantForms = [
|
|
295
|
+
options.operations,
|
|
296
|
+
options.activeSchemaOperations,
|
|
297
|
+
options.controlPlaneOnly,
|
|
298
|
+
].filter((form) => form !== undefined).length;
|
|
299
|
+
if (grantForms !== 1) {
|
|
286
300
|
throw new AbloAuthenticationError(
|
|
287
|
-
'Provide
|
|
301
|
+
'Provide exactly one of operations, activeSchemaOperations, or controlPlaneOnly ' +
|
|
302
|
+
'for a user-session mint.',
|
|
288
303
|
{ code: 'invalid_body' },
|
|
289
304
|
);
|
|
290
305
|
}
|
|
@@ -316,9 +331,11 @@ export async function mintUserSessionKey(
|
|
|
316
331
|
}
|
|
317
332
|
: {}),
|
|
318
333
|
...(options.syncGroups ? { syncGroups: options.syncGroups } : {}),
|
|
319
|
-
...(options.
|
|
320
|
-
? {
|
|
321
|
-
:
|
|
334
|
+
...(options.controlPlaneOnly
|
|
335
|
+
? { controlPlaneOnly: true }
|
|
336
|
+
: options.operations
|
|
337
|
+
? { operations: options.operations }
|
|
338
|
+
: { activeSchemaOperations: options.activeSchemaOperations }),
|
|
322
339
|
ttlSeconds: options.ttlSeconds,
|
|
323
340
|
...(options.label ? { label: options.label } : {}),
|
|
324
341
|
}),
|
package/src/auth/schemas.ts
CHANGED
|
@@ -46,9 +46,20 @@ export const EphemeralKeyResponseSchema = z.object({
|
|
|
46
46
|
branchId: z.string().min(1).nullable().default(null),
|
|
47
47
|
branchRoot: z.boolean().default(false),
|
|
48
48
|
syncGroups: z.array(z.string()),
|
|
49
|
-
/** Effective operation grant stored on the credential.
|
|
50
|
-
operations
|
|
51
|
-
|
|
49
|
+
/** Effective operation grant stored on the credential. Empty ONLY for a
|
|
50
|
+
* control-plane-only session, which grants no data operations by design. */
|
|
51
|
+
operations: z.array(grantedOperationSchema),
|
|
52
|
+
/** Echoed for a session minted with the control-plane-only grant form: the
|
|
53
|
+
* credential proves identity to control-plane surfaces and can touch no
|
|
54
|
+
* application data. */
|
|
55
|
+
controlPlaneOnly: z.literal(true).optional(),
|
|
56
|
+
}).refine(
|
|
57
|
+
(response) => response.controlPlaneOnly === true || response.operations.length > 0,
|
|
58
|
+
{
|
|
59
|
+
message: 'a data session must carry at least one granted operation',
|
|
60
|
+
path: ['operations'],
|
|
61
|
+
},
|
|
62
|
+
);
|
|
52
63
|
|
|
53
64
|
export type EphemeralKeyResponse = z.infer<typeof EphemeralKeyResponseSchema>;
|
|
54
65
|
|
|
@@ -76,6 +76,15 @@ export interface ConflictEvent {
|
|
|
76
76
|
id: string;
|
|
77
77
|
fields: readonly string[];
|
|
78
78
|
writtenBy?: ParticipantKind;
|
|
79
|
+
/**
|
|
80
|
+
* The group premise this row breached, when the conflict was found at group
|
|
81
|
+
* grain. `model`/`id` stay the row that actually moved, so a log line can
|
|
82
|
+
* say which row moved AND which premise it broke — the two used to be the
|
|
83
|
+
* same field, and a group conflict logged its group key as the row.
|
|
84
|
+
*/
|
|
85
|
+
group?: string;
|
|
86
|
+
/** How the row reached `group` — `self`, `parent`, or `transitive`. */
|
|
87
|
+
via?: string;
|
|
79
88
|
}[];
|
|
80
89
|
}
|
|
81
90
|
|
|
@@ -24,6 +24,10 @@ export {
|
|
|
24
24
|
onStaleModeSchema,
|
|
25
25
|
writeGuardSchema,
|
|
26
26
|
staleNotificationSchema,
|
|
27
|
+
rowStaleNotificationSchema,
|
|
28
|
+
groupStaleNotificationSchema,
|
|
29
|
+
stalePropagationSchema,
|
|
30
|
+
|
|
27
31
|
readDependencySchema,
|
|
28
32
|
trackDependencySchema,
|
|
29
33
|
// Layer 2 — pessimistic claim / claim-lease
|
|
@@ -101,6 +105,9 @@ export type {
|
|
|
101
105
|
OnStaleMode,
|
|
102
106
|
WriteGuard,
|
|
103
107
|
StaleNotification,
|
|
108
|
+
RowStaleNotification,
|
|
109
|
+
GroupStaleNotification,
|
|
110
|
+
StalePropagation,
|
|
104
111
|
ReadDependency,
|
|
105
112
|
TrackDependency,
|
|
106
113
|
// Layer 2 — pessimistic claim / claim-lease
|
|
@@ -179,3 +186,4 @@ export {
|
|
|
179
186
|
modelTarget,
|
|
180
187
|
streamTarget,
|
|
181
188
|
} from './locator.js';
|
|
189
|
+
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
syncGroupInputSchema,
|
|
4
|
+
syncGroupRefSchema,
|
|
5
|
+
syncGroupSchema,
|
|
6
|
+
} from '../schema/roles.js';
|
|
3
7
|
export { syncGroupInputSchema } from '../schema/roles.js';
|
|
4
8
|
import { isFieldRef, type FieldRef } from '../schema/fieldRef.js';
|
|
5
9
|
import type { ParticipantKind } from '../types/participant.js';
|
|
@@ -213,6 +217,28 @@ export const targetRefSchema = z.object({
|
|
|
213
217
|
});
|
|
214
218
|
export type TargetRef = z.infer<typeof targetRefSchema>;
|
|
215
219
|
|
|
220
|
+
/**
|
|
221
|
+
* What a {@link ModelClaim} points at — the target locator as SDK callers see
|
|
222
|
+
* it, keyed by `model` and `id` rather than the wire schema's `entityType` and
|
|
223
|
+
* `entityId`. This is the public `ModelTarget` shape.
|
|
224
|
+
*
|
|
225
|
+
* Declared beside {@link targetRefSchema} because the two are the same shape in
|
|
226
|
+
* two spellings, and a member added to one belongs in the other. Both are read
|
|
227
|
+
* by {@link staleNotificationSchema} and the claim family below, so this has to
|
|
228
|
+
* precede them.
|
|
229
|
+
*/
|
|
230
|
+
export const modelTargetSchema = z
|
|
231
|
+
.object({
|
|
232
|
+
model: z.string(),
|
|
233
|
+
id: z.string(),
|
|
234
|
+
field: z.string().optional(),
|
|
235
|
+
/** Several named parts at once — see {@link targetRefSchema}. */
|
|
236
|
+
fields: z.array(z.string()).readonly().optional(),
|
|
237
|
+
meta: z.record(z.string(), z.unknown()).optional(),
|
|
238
|
+
})
|
|
239
|
+
.readonly();
|
|
240
|
+
export type ModelTarget = z.infer<typeof modelTargetSchema>;
|
|
241
|
+
|
|
216
242
|
/**
|
|
217
243
|
* The same locator in the spelling the wait line and the claim handle use —
|
|
218
244
|
* `{ type, id }` for the entity, the sub-entity half unchanged. It is a
|
|
@@ -270,45 +296,153 @@ export type WriteGuard = z.infer<typeof writeGuardSchema>;
|
|
|
270
296
|
* re-commits. `reject` throws instead, and `overwrite` proceeds silently —
|
|
271
297
|
* neither notifies.
|
|
272
298
|
*/
|
|
273
|
-
|
|
299
|
+
/**
|
|
300
|
+
* A log position, as the server reports one.
|
|
301
|
+
*
|
|
302
|
+
* Server-PRODUCED watermarks are constrained here; the caller-supplied
|
|
303
|
+
* {@link writeGuardSchema} `readAt` deliberately is not. The asymmetry is the
|
|
304
|
+
* trust direction, not an oversight: the server controls what it stamps, so
|
|
305
|
+
* stating the domain costs nothing, while tightening an inbound field would
|
|
306
|
+
* reject payloads the wire accepts today.
|
|
307
|
+
*/
|
|
308
|
+
const syncIdSchema = z.number().int().nonnegative();
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* How a change reached the premise that fired — the three ways a record joins a
|
|
312
|
+
* sync group, which is the vocabulary `RecordGroupSpec` already routes by
|
|
313
|
+
* (`selfKind` / `parents` / `transitive`) rather than a fourth name for it.
|
|
314
|
+
*
|
|
315
|
+
* Without this a group notification can only say "something in the group you
|
|
316
|
+
* read moved", and the cheapest correct response to that is to re-read the
|
|
317
|
+
* whole group. `via` plus the notification's `target` narrows it to the row
|
|
318
|
+
* that actually moved and how it got there, which is usually a one-row re-read.
|
|
319
|
+
*
|
|
320
|
+
* • `self` — the row that moved IS the group's scope root.
|
|
321
|
+
* • `parent` — it sits one declared containment edge below the root.
|
|
322
|
+
* • `transitive` — the root is ≥2 hops up (`comment → task → project`).
|
|
323
|
+
*/
|
|
324
|
+
export const stalePropagationSchema = z
|
|
325
|
+
.object({
|
|
326
|
+
via: z.enum(['self', 'parent', 'transitive']),
|
|
327
|
+
/**
|
|
328
|
+
* The intermediate models walked from the moved row up to the scope root,
|
|
329
|
+
* nearest hop first — the part of the route a reader cannot see from the
|
|
330
|
+
* two endpoints. Empty on `self` and `parent`, which have no intermediate.
|
|
331
|
+
*
|
|
332
|
+
* Model names, not rows: naming the intermediate ROWS would cost a join per
|
|
333
|
+
* notification, and the route is what explains the reach. `target` already
|
|
334
|
+
* identifies the row that moved and `group` the premise it broke.
|
|
335
|
+
*/
|
|
336
|
+
through: z.array(z.string()).readonly(),
|
|
337
|
+
})
|
|
338
|
+
.readonly();
|
|
339
|
+
export type StalePropagation = z.infer<typeof stalePropagationSchema>;
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* What both notification scopes carry. The arms below derive from it rather
|
|
343
|
+
* than restate it, the same way {@link claimStateSchema} projects the claim
|
|
344
|
+
* record.
|
|
345
|
+
*/
|
|
346
|
+
const staleNotificationBaseSchema = z.object({
|
|
274
347
|
/** Names this object's type; every returned object carries such a tag. */
|
|
275
|
-
object: z.literal('stale_notification')
|
|
276
|
-
/** Model name of the conflicting row. */
|
|
277
|
-
model: z.string(),
|
|
278
|
-
/** Row id. */
|
|
279
|
-
id: z.string(),
|
|
280
|
-
/** The watermark the committer reasoned against (its `readAt`). */
|
|
281
|
-
readAt: z.number(),
|
|
282
|
-
/**
|
|
283
|
-
* Newest delta id on the row — the committer's new watermark. Re-capture
|
|
284
|
-
* context at/after this id to reconcile.
|
|
285
|
-
*/
|
|
286
|
-
observedSyncId: z.number(),
|
|
348
|
+
object: z.literal('stale_notification'),
|
|
287
349
|
/**
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
350
|
+
* The row that moved, and which part of it — `fields` holds the columns whose
|
|
351
|
+
* concurrent change collided (empty ⇒ a whole-entity CREATE/DELETE).
|
|
352
|
+
*
|
|
353
|
+
* The same shape a claim names its subject with, so one reader handles "who
|
|
354
|
+
* holds this row" and "this row moved under you" without learning two
|
|
355
|
+
* vocabularies. In BOTH scopes this is the row that actually changed: a group
|
|
356
|
+
* notification names the moved row here and the fired premise in `group`.
|
|
291
357
|
*/
|
|
292
|
-
|
|
358
|
+
target: modelTargetSchema,
|
|
359
|
+
/** The watermark the committer reasoned against (its `readAt`). */
|
|
360
|
+
readAt: syncIdSchema,
|
|
293
361
|
/**
|
|
294
|
-
*
|
|
295
|
-
*
|
|
362
|
+
* Newest delta id on the premise — the committer's new watermark. Re-capture
|
|
363
|
+
* context at/after this id to reconcile.
|
|
296
364
|
*/
|
|
297
|
-
|
|
365
|
+
observedSyncId: syncIdSchema,
|
|
298
366
|
/** Who wrote the conflicting delta. */
|
|
299
367
|
writtenBy: z.object({
|
|
300
368
|
kind: participantKindSchema,
|
|
301
369
|
id: z.string(),
|
|
302
370
|
}),
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
/** A premise on one row: that row moved. */
|
|
374
|
+
export const rowStaleNotificationSchema = staleNotificationBaseSchema.extend({
|
|
375
|
+
scope: z.literal('row'),
|
|
376
|
+
/**
|
|
377
|
+
* The live values of `target.fields` after the conflict — the piece a plain
|
|
378
|
+
* stale error omits. It lets the actor reconcile without a follow-up read.
|
|
379
|
+
*
|
|
380
|
+
* Row scope only. Reading live values is cheap for one known row and is what
|
|
381
|
+
* a group breach cannot promise, so the group arm omits the field rather than
|
|
382
|
+
* carrying an empty one that reads as "nothing changed".
|
|
383
|
+
*/
|
|
384
|
+
currentValues: z.record(z.string(), z.unknown()),
|
|
385
|
+
});
|
|
386
|
+
export type RowStaleNotification = z.infer<typeof rowStaleNotificationSchema>;
|
|
387
|
+
|
|
388
|
+
/** A premise on a whole sync group: something in it moved. */
|
|
389
|
+
export const groupStaleNotificationSchema = staleNotificationBaseSchema.extend({
|
|
390
|
+
scope: z.literal('group'),
|
|
391
|
+
/**
|
|
392
|
+
* The group premise that fired (`report:abc`, `section:s1`).
|
|
393
|
+
*
|
|
394
|
+
* Same format schema the premise declares, so the value a caller writes into
|
|
395
|
+
* `reads[].group` and the value it gets back name a group identically. The
|
|
396
|
+
* BRANDED view is for values Ablo mints; a notification only echoes the
|
|
397
|
+
* premise it was handed, and re-parsing it to acquire a brand would be a
|
|
398
|
+
* second validation of data the commit boundary already checked.
|
|
399
|
+
*/
|
|
400
|
+
group: syncGroupRefSchema,
|
|
401
|
+
/**
|
|
402
|
+
* How `target` reached `group`. Absent when the schema's record-group spec is
|
|
403
|
+
* unavailable to the commit path, which is the only case where the server
|
|
404
|
+
* knows a group moved without knowing the route.
|
|
405
|
+
*/
|
|
406
|
+
propagation: stalePropagationSchema.optional(),
|
|
303
407
|
/**
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
* changed
|
|
307
|
-
*
|
|
308
|
-
*
|
|
408
|
+
* How much of the group moved — the decision "re-read these rows" versus
|
|
409
|
+
* "give up and take the whole group" needs a size, and a premise that only
|
|
410
|
+
* says *something* changed forces the expensive branch every time.
|
|
411
|
+
*
|
|
412
|
+
* Counts DISTINCT ROWS, not deltas: two writes to one row is one row's worth
|
|
413
|
+
* of re-reading. `sample` names the most recently changed of them and is
|
|
414
|
+
* capped, so `truncated` says whether it tells the whole story.
|
|
415
|
+
*
|
|
416
|
+
* Absent when the commit path did not measure it (a durable `track` fires per
|
|
417
|
+
* commit and does not pay for the extra statement).
|
|
309
418
|
*/
|
|
310
|
-
|
|
419
|
+
changed: z
|
|
420
|
+
.object({
|
|
421
|
+
count: z.number().int().nonnegative(),
|
|
422
|
+
sample: z.array(modelTargetSchema).readonly(),
|
|
423
|
+
truncated: z.boolean(),
|
|
424
|
+
})
|
|
425
|
+
.optional(),
|
|
311
426
|
});
|
|
427
|
+
export type GroupStaleNotification = z.infer<
|
|
428
|
+
typeof groupStaleNotificationSchema
|
|
429
|
+
>;
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* One advisory, two scopes, told apart by `scope`.
|
|
433
|
+
*
|
|
434
|
+
* A real discriminated union rather than a flat object with an optional
|
|
435
|
+
* `group`, which is what {@link readDependencySchema} already does for the
|
|
436
|
+
* premise side. While it was flat, the two scopes disagreed about what their
|
|
437
|
+
* fields meant — `model`/`id` held a row in one and the group key in the other,
|
|
438
|
+
* and `conflictingFields`/`currentValues` were empty by construction in the
|
|
439
|
+
* group case — so every consumer had to re-derive the scope from `group`'s
|
|
440
|
+
* presence and read the prose to know which fields were load-bearing.
|
|
441
|
+
*/
|
|
442
|
+
export const staleNotificationSchema = z.discriminatedUnion('scope', [
|
|
443
|
+
rowStaleNotificationSchema,
|
|
444
|
+
groupStaleNotificationSchema,
|
|
445
|
+
]);
|
|
312
446
|
export type StaleNotification = z.infer<typeof staleNotificationSchema>;
|
|
313
447
|
|
|
314
448
|
/**
|
|
@@ -338,7 +472,13 @@ const readRowDependencySchema = z.object({
|
|
|
338
472
|
});
|
|
339
473
|
|
|
340
474
|
const readGroupDependencySchema = z.object({
|
|
341
|
-
|
|
475
|
+
/**
|
|
476
|
+
* The caller-facing view of the format: `reads: [{ group: 'report:abc' }]`
|
|
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
|
+
*/
|
|
481
|
+
group: syncGroupRefSchema,
|
|
342
482
|
readAt: z.number(),
|
|
343
483
|
onStale: onStaleModeSchema.optional(),
|
|
344
484
|
});
|
|
@@ -361,7 +501,12 @@ export type ReadDependency = z.infer<typeof readDependencySchema>;
|
|
|
361
501
|
* same reference: a track names its target exactly as a read does, and the
|
|
362
502
|
* three ways it differs are stated here as omissions the compiler holds.
|
|
363
503
|
*
|
|
364
|
-
* •
|
|
504
|
+
* • `onStale` NARROWED, not dropped — `notify` (the default) reports the
|
|
505
|
+
* change on the tracker's next receipt and lets the commit through;
|
|
506
|
+
* `reject` refuses that commit while the belief is stale, so an agent
|
|
507
|
+
* cannot write on something it has been shown to be out of date about.
|
|
508
|
+
* `overwrite` is excluded because it means "apply my write anyway" and a
|
|
509
|
+
* track guards no write of its own to apply;
|
|
365
510
|
* • no `fields` — a track fires at row grain, because the server keeps one
|
|
366
511
|
* row per tracked target and reports that the target moved, not which
|
|
367
512
|
* column did (`track_dependencies` has no field axis to store one in);
|
|
@@ -373,15 +518,36 @@ export type ReadDependency = z.infer<typeof readDependencySchema>;
|
|
|
373
518
|
* genuinely cannot carry has to be omitted here on purpose, in one line, rather
|
|
374
519
|
* than by being quietly left out of a copy.
|
|
375
520
|
*/
|
|
376
|
-
|
|
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
|
+
/**
|
|
530
|
+
* What a track does when the caller says nothing — reporting, the behavior every
|
|
531
|
+
* track had before the disposition existed, so an existing registration is
|
|
532
|
+
* unchanged.
|
|
533
|
+
*
|
|
534
|
+
* Declared here because the value has to agree in three places that cannot
|
|
535
|
+
* import each other: this schema, the column DEFAULT, and the server's insert.
|
|
536
|
+
* The two SQL copies are pinned to this one by a test
|
|
537
|
+
* (`trackOnStaleDomain.test.ts`) rather than by anyone remembering.
|
|
538
|
+
*/
|
|
539
|
+
export const DEFAULT_TRACK_ON_STALE: TrackOnStale = 'notify';
|
|
540
|
+
|
|
541
|
+
const trackBaseSchema = {
|
|
542
|
+
readAt: z.number().optional(),
|
|
543
|
+
onStale: trackOnStaleSchema.optional(),
|
|
544
|
+
} as const;
|
|
377
545
|
|
|
378
546
|
export const trackDependencySchema = z.union([
|
|
379
547
|
readRowDependencySchema
|
|
380
548
|
.omit({ onStale: true, fields: true, readAt: true })
|
|
381
|
-
.extend(
|
|
382
|
-
readGroupDependencySchema
|
|
383
|
-
.omit({ onStale: true, readAt: true })
|
|
384
|
-
.extend(trackReadAtSchema),
|
|
549
|
+
.extend(trackBaseSchema),
|
|
550
|
+
readGroupDependencySchema.omit({ onStale: true, readAt: true }).extend(trackBaseSchema),
|
|
385
551
|
]);
|
|
386
552
|
export type TrackDependency = z.infer<typeof trackDependencySchema>;
|
|
387
553
|
|
|
@@ -725,23 +891,6 @@ export const claimExpiredSchema = z.object({
|
|
|
725
891
|
export type ClaimExpired = z.infer<typeof claimExpiredSchema>;
|
|
726
892
|
|
|
727
893
|
|
|
728
|
-
/**
|
|
729
|
-
* What a {@link ModelClaim} points at — the target locator as SDK callers see
|
|
730
|
-
* it, keyed by `model` and `id` rather than the wire schema's `entityType` and
|
|
731
|
-
* `entityId`. This is the public `ModelTarget` shape.
|
|
732
|
-
*/
|
|
733
|
-
export const modelTargetSchema = z
|
|
734
|
-
.object({
|
|
735
|
-
model: z.string(),
|
|
736
|
-
id: z.string(),
|
|
737
|
-
field: z.string().optional(),
|
|
738
|
-
/** Several named parts at once — see {@link targetRefSchema}. */
|
|
739
|
-
fields: z.array(z.string()).readonly().optional(),
|
|
740
|
-
meta: z.record(z.string(), z.unknown()).optional(),
|
|
741
|
-
})
|
|
742
|
-
.readonly();
|
|
743
|
-
export type ModelTarget = z.infer<typeof modelTargetSchema>;
|
|
744
|
-
|
|
745
894
|
/**
|
|
746
895
|
* The two states a claim can be observed in while it still exists.
|
|
747
896
|
*
|
|
@@ -50,7 +50,15 @@ export function formatClaim(e: ClaimEvent): string {
|
|
|
50
50
|
|
|
51
51
|
/** A notify-instead-of-abort stale write as one readable line. */
|
|
52
52
|
export function formatConflict(e: ConflictEvent): string {
|
|
53
|
-
const rows = e.rows
|
|
53
|
+
const rows = e.rows
|
|
54
|
+
.map((r) => {
|
|
55
|
+
// A group conflict reads as "which row moved, and which premise it broke",
|
|
56
|
+
// because those are two different things and the reader needs both to know
|
|
57
|
+
// whether to re-read one row or the whole group.
|
|
58
|
+
const premise = r.group ? ` ${r.via ? `${r.via} → ` : '→ '}${r.group}` : '';
|
|
59
|
+
return `${r.model}/${r.id}(${r.fields.join(',')})${premise}`;
|
|
60
|
+
})
|
|
61
|
+
.join(', ');
|
|
54
62
|
return `conflict: tx ${e.clientTxId} — ${e.rows.length} row(s) changed underneath${rows ? `: ${rows}` : ''}`;
|
|
55
63
|
}
|
|
56
64
|
|