@openvtc/trust-tasks 0.12.1 → 0.12.3
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/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/vta/_shared/0.1/app-state-record.d.ts +17 -0
- package/dist/vta/_shared/0.1/app-state-record.d.ts.map +1 -0
- package/dist/vta/_shared/0.1/app-state-record.js +6 -0
- package/dist/vta/_shared/0.1/app-state-record.js.map +1 -0
- package/dist/vta/app-state/delete/1.0/payload.d.ts +488 -0
- package/dist/vta/app-state/delete/1.0/payload.d.ts.map +1 -0
- package/dist/vta/app-state/delete/1.0/payload.js +248 -0
- package/dist/vta/app-state/delete/1.0/payload.js.map +1 -0
- package/dist/vta/app-state/get/1.0/payload.d.ts +611 -0
- package/dist/vta/app-state/get/1.0/payload.d.ts.map +1 -0
- package/dist/vta/app-state/get/1.0/payload.js +306 -0
- package/dist/vta/app-state/get/1.0/payload.js.map +1 -0
- package/dist/vta/app-state/get-many/1.0/payload.d.ts +716 -0
- package/dist/vta/app-state/get-many/1.0/payload.d.ts.map +1 -0
- package/dist/vta/app-state/get-many/1.0/payload.js +350 -0
- package/dist/vta/app-state/get-many/1.0/payload.js.map +1 -0
- package/dist/vta/app-state/list/1.0/payload.d.ts +778 -0
- package/dist/vta/app-state/list/1.0/payload.d.ts.map +1 -0
- package/dist/vta/app-state/list/1.0/payload.js +368 -0
- package/dist/vta/app-state/list/1.0/payload.js.map +1 -0
- package/dist/vta/app-state/put/1.0/payload.d.ts +560 -0
- package/dist/vta/app-state/put/1.0/payload.d.ts.map +1 -0
- package/dist/vta/app-state/put/1.0/payload.js +291 -0
- package/dist/vta/app-state/put/1.0/payload.js.map +1 -0
- package/dist/vta/app-state/put-many/1.0/payload.d.ts +856 -0
- package/dist/vta/app-state/put-many/1.0/payload.d.ts.map +1 -0
- package/dist/vta/app-state/put-many/1.0/payload.js +455 -0
- package/dist/vta/app-state/put-many/1.0/payload.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +7 -0
- package/src/vta/_shared/0.1/app-state-record.ts +17 -0
- package/src/vta/app-state/delete/1.0/payload.ts +323 -0
- package/src/vta/app-state/get/1.0/payload.ts +404 -0
- package/src/vta/app-state/get-many/1.0/payload.ts +469 -0
- package/src/vta/app-state/list/1.0/payload.ts +509 -0
- package/src/vta/app-state/put/1.0/payload.ts +382 -0
- package/src/vta/app-state/put-many/1.0/payload.ts +584 -0
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated by scripts/build-ts-bindings.mjs — DO NOT EDIT BY HAND.
|
|
3
|
+
* Source: specs/vta/app-state/put-many/1.0/payload.schema.json
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* One namespace per batch. Atomicity is only meaningful within the counter the writes take their versions from, and that counter is per (contextId, namespace).
|
|
7
|
+
*/
|
|
8
|
+
export type Namespace = string;
|
|
9
|
+
/**
|
|
10
|
+
* One write within the batch. Shaped exactly like a vta/app-state/put payload minus the context and namespace, which the batch supplies.
|
|
11
|
+
*/
|
|
12
|
+
export type Write = {
|
|
13
|
+
[k: string]: unknown | undefined;
|
|
14
|
+
} | {
|
|
15
|
+
[k: string]: unknown | undefined;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Application-chosen identifier for a record within a namespace. Opaque to the maintainer: it MUST NOT be parsed, normalized, or case-folded, and prefix matching in `list` is a byte-prefix comparison over the UTF-8 encoding. Applications SHOULD use `/`-delimited hierarchical keys (`community/acme`, `contact/z6Mk…`) so that `prefix` can address a record family, but the delimiter is a convention between an application and itself — the maintainer attaches no meaning to it.
|
|
19
|
+
*/
|
|
20
|
+
export type Key = string;
|
|
21
|
+
/**
|
|
22
|
+
* The new version, on `written`.
|
|
23
|
+
*/
|
|
24
|
+
export type Version = number;
|
|
25
|
+
/**
|
|
26
|
+
* On `conflict`: the version the maintainer actually holds. Absent when the conflict is that no record exists (`expectedVersion` was positive and the address is empty).
|
|
27
|
+
*/
|
|
28
|
+
export type Version1 = number;
|
|
29
|
+
/**
|
|
30
|
+
* The namespace's counter value after the batch. A writer that is also a sync consumer can adopt this instead of issuing a list call to discover where its own writes landed.
|
|
31
|
+
*/
|
|
32
|
+
export type Version2 = number;
|
|
33
|
+
/**
|
|
34
|
+
* Write up to 64 application-state records in one round trip, each carrying its own optimistic-concurrency precondition. The batch `mode` decides what a single failure costs: `independent` (the default) applies each write on its own merits, `atomic` applies all or none.
|
|
35
|
+
*/
|
|
36
|
+
export interface VTAApplicationStatePutManyPayload {
|
|
37
|
+
/**
|
|
38
|
+
* The VTA context the records are scoped to; the isolation boundary.
|
|
39
|
+
*/
|
|
40
|
+
contextId: string;
|
|
41
|
+
namespace: Namespace;
|
|
42
|
+
/**
|
|
43
|
+
* `independent` applies each write on its own merits, so one conflicted record does not block the other nine — what a flush of unrelated edits wants, and why it is the default. `atomic` applies all or none, for records carrying a joint invariant. An atomic DEFAULT would let one stale record silently wedge an entire flush, and a caller could not tell a wedged flush from a slow one.
|
|
44
|
+
*/
|
|
45
|
+
mode?: "independent" | "atomic";
|
|
46
|
+
/**
|
|
47
|
+
* The writes to apply. Keys MUST be distinct: two writes to one key in a batch have no defined order and are refused rather than serialised.
|
|
48
|
+
*
|
|
49
|
+
* @minItems 1
|
|
50
|
+
* @maxItems 64
|
|
51
|
+
*/
|
|
52
|
+
writes: [Write, ...Write[]];
|
|
53
|
+
ext?: Ext;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Ecosystem-defined extension members per SPEC.md §4.5.1.
|
|
57
|
+
*/
|
|
58
|
+
export interface Ext {
|
|
59
|
+
[k: string]: unknown | undefined;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Success response to vta/app-state/put-many in `independent` mode. Type https://trusttasks.org/spec/vta/app-state/put-many/1.0#response. A response is returned even when some writes conflicted, because the task did what it promised — applied each write on its own merits — and the per-record outcomes are the answer rather than the failure. An `atomic` batch that does not apply is a trust-task-error carrying vta/app-state/put-many:atomicBatchRejected, whose details carry the same per-record outcomes.
|
|
63
|
+
*/
|
|
64
|
+
export interface VTAApplicationStatePutManyResponsePayload {
|
|
65
|
+
/**
|
|
66
|
+
* The mode the maintainer applied, echoed so a caller relying on the default sees what it got.
|
|
67
|
+
*/
|
|
68
|
+
mode: "independent" | "atomic";
|
|
69
|
+
/**
|
|
70
|
+
* One result per requested write, in request order. Every write is accounted for.
|
|
71
|
+
*
|
|
72
|
+
* @minItems 1
|
|
73
|
+
* @maxItems 64
|
|
74
|
+
*/
|
|
75
|
+
results: [WriteResult, ...WriteResult[]];
|
|
76
|
+
highWatermark?: Version2;
|
|
77
|
+
ext?: Ext1;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The outcome of one write within a `vta/app-state/put-many` batch. Per-record rather than per-batch, because the default batch mode applies each write on its own merits: a caller flushing ten unrelated edits needs to know which one conflicted, not merely that something did.
|
|
81
|
+
*/
|
|
82
|
+
export interface WriteResult {
|
|
83
|
+
key: Key;
|
|
84
|
+
/**
|
|
85
|
+
* `written`: applied, and `version` carries the new value. `conflict`: `expectedVersion` did not match; `currentVersion`, `currentValue` and `currentDeleted` carry the maintainer's view so the caller can resolve without a re-read. `tooLarge`: the value exceeded the per-record cap; `limitBytes` and `actualBytes` say by how much. `notFound`: a `mergePatch` write named an address with no live record. `skipped`: atomic mode only — this write was not attempted because another in the batch failed.
|
|
86
|
+
*/
|
|
87
|
+
outcome: "written" | "conflict" | "tooLarge" | "notFound" | "skipped";
|
|
88
|
+
version?: Version;
|
|
89
|
+
/**
|
|
90
|
+
* On `written`: true when no live record existed at the address beforehand.
|
|
91
|
+
*/
|
|
92
|
+
created?: boolean;
|
|
93
|
+
currentVersion?: Version1;
|
|
94
|
+
/**
|
|
95
|
+
* On `conflict`: the value the maintainer actually holds, returned WITH the rejection rather than left for the caller to re-read. A bare rejection has no fixed point under contention — between the rejection and the re-read the record can change again — so returning the winner's view removes the race rather than narrowing it. Absent when `currentDeleted` is true or no record exists.
|
|
96
|
+
*/
|
|
97
|
+
currentValue?: {
|
|
98
|
+
[k: string]: unknown | undefined;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* On `conflict`: true when the address holds a tombstone rather than a live record.
|
|
102
|
+
*/
|
|
103
|
+
currentDeleted?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* On `tooLarge`: the maintainer's per-record cap in bytes.
|
|
106
|
+
*/
|
|
107
|
+
limitBytes?: number;
|
|
108
|
+
/**
|
|
109
|
+
* On `tooLarge`: the size of the rejected value in bytes.
|
|
110
|
+
*/
|
|
111
|
+
actualBytes?: number;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Ecosystem-defined extension members per SPEC.md §4.5.1.
|
|
115
|
+
*/
|
|
116
|
+
export interface Ext1 {
|
|
117
|
+
[k: string]: unknown | undefined;
|
|
118
|
+
}
|
|
119
|
+
/** Trust Task type URI. */
|
|
120
|
+
export declare const TYPE_URI: "https://trusttasks.org/spec/vta/app-state/put-many/1.0";
|
|
121
|
+
/** Stable alias for this specification's request payload shape. */
|
|
122
|
+
export type Payload = VTAApplicationStatePutManyPayload;
|
|
123
|
+
/** Trust Task response type URI (request type URI + "#response"). */
|
|
124
|
+
export declare const RESPONSE_TYPE_URI: "https://trusttasks.org/spec/vta/app-state/put-many/1.0#response";
|
|
125
|
+
/** Stable alias for this specification's success-response payload shape. */
|
|
126
|
+
export type Response = VTAApplicationStatePutManyResponsePayload;
|
|
127
|
+
/**
|
|
128
|
+
* This specification's payload schema, as a value.
|
|
129
|
+
*
|
|
130
|
+
* SPEC.md §7.2 item 2 is performed against this. It is shipped as data
|
|
131
|
+
* rather than only as a `.json` file because TypeScript types are erased
|
|
132
|
+
* at runtime: without a schema a consumer has nothing to validate, and
|
|
133
|
+
* every REQUIRED payload member is optional in practice. Cross-file
|
|
134
|
+
* `$ref`s are already inlined, so it needs no resolver.
|
|
135
|
+
*/
|
|
136
|
+
export declare const PAYLOAD_SCHEMA: {
|
|
137
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
138
|
+
readonly $id: "https://trusttasks.org/spec/vta/app-state/put-many/1.0";
|
|
139
|
+
readonly title: "VTA Application State Put-Many — payload";
|
|
140
|
+
readonly description: "Write up to 64 application-state records in one round trip, each carrying its own optimistic-concurrency precondition. The batch `mode` decides what a single failure costs: `independent` (the default) applies each write on its own merits, `atomic` applies all or none.";
|
|
141
|
+
readonly type: "object";
|
|
142
|
+
readonly additionalProperties: false;
|
|
143
|
+
readonly required: readonly ["contextId", "namespace", "writes"];
|
|
144
|
+
readonly properties: {
|
|
145
|
+
readonly contextId: {
|
|
146
|
+
readonly type: "string";
|
|
147
|
+
readonly minLength: 1;
|
|
148
|
+
readonly description: "The VTA context the records are scoped to; the isolation boundary.";
|
|
149
|
+
};
|
|
150
|
+
readonly namespace: {
|
|
151
|
+
readonly $ref: "#/$defs/Namespace";
|
|
152
|
+
readonly description: "One namespace per batch. Atomicity is only meaningful within the counter the writes take their versions from, and that counter is per (contextId, namespace).";
|
|
153
|
+
};
|
|
154
|
+
readonly mode: {
|
|
155
|
+
readonly type: "string";
|
|
156
|
+
readonly enum: readonly ["independent", "atomic"];
|
|
157
|
+
readonly default: "independent";
|
|
158
|
+
readonly description: "`independent` applies each write on its own merits, so one conflicted record does not block the other nine — what a flush of unrelated edits wants, and why it is the default. `atomic` applies all or none, for records carrying a joint invariant. An atomic DEFAULT would let one stale record silently wedge an entire flush, and a caller could not tell a wedged flush from a slow one.";
|
|
159
|
+
readonly $comment: "The default is load-bearing rather than a convenience; see the spec's Abstract.";
|
|
160
|
+
};
|
|
161
|
+
readonly writes: {
|
|
162
|
+
readonly type: "array";
|
|
163
|
+
readonly minItems: 1;
|
|
164
|
+
readonly maxItems: 64;
|
|
165
|
+
readonly items: {
|
|
166
|
+
readonly $ref: "#/$defs/Write";
|
|
167
|
+
};
|
|
168
|
+
readonly description: "The writes to apply. Keys MUST be distinct: two writes to one key in a batch have no defined order and are refused rather than serialised.";
|
|
169
|
+
};
|
|
170
|
+
readonly ext: {
|
|
171
|
+
readonly $ref: "#/$defs/Ext";
|
|
172
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
readonly $defs: {
|
|
176
|
+
readonly Write: {
|
|
177
|
+
readonly title: "Write";
|
|
178
|
+
readonly description: "One write within the batch. Shaped exactly like a vta/app-state/put payload minus the context and namespace, which the batch supplies.";
|
|
179
|
+
readonly type: "object";
|
|
180
|
+
readonly additionalProperties: false;
|
|
181
|
+
readonly required: readonly ["key"];
|
|
182
|
+
readonly oneOf: readonly [{
|
|
183
|
+
readonly required: readonly ["value"];
|
|
184
|
+
readonly not: {
|
|
185
|
+
readonly required: readonly ["mergePatch"];
|
|
186
|
+
};
|
|
187
|
+
}, {
|
|
188
|
+
readonly required: readonly ["mergePatch"];
|
|
189
|
+
readonly not: {
|
|
190
|
+
readonly required: readonly ["value"];
|
|
191
|
+
};
|
|
192
|
+
}];
|
|
193
|
+
readonly properties: {
|
|
194
|
+
readonly key: {
|
|
195
|
+
readonly $ref: "#/$defs/Key";
|
|
196
|
+
};
|
|
197
|
+
readonly value: {
|
|
198
|
+
readonly description: "The complete new value, replacing whatever the record held. Any JSON value, including `null`. Mutually exclusive with `mergePatch`.";
|
|
199
|
+
};
|
|
200
|
+
readonly mergePatch: {
|
|
201
|
+
readonly type: "object";
|
|
202
|
+
readonly description: "An RFC 7386 JSON Merge Patch applied to the record's current value. Requires a live record at the address; otherwise this write's outcome is `notFound`. Mutually exclusive with `value`.";
|
|
203
|
+
};
|
|
204
|
+
readonly expectedVersion: {
|
|
205
|
+
readonly $ref: "#/$defs/ExpectedVersion";
|
|
206
|
+
readonly description: "This write's own precondition, evaluated independently of every other write in the batch. A positive value requires the record to be at exactly that version; 0 requires that no live record exists.";
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
readonly Response: {
|
|
211
|
+
readonly $anchor: "response";
|
|
212
|
+
readonly title: "VTA Application State Put-Many — response payload";
|
|
213
|
+
readonly description: "Success response to vta/app-state/put-many in `independent` mode. Type https://trusttasks.org/spec/vta/app-state/put-many/1.0#response. A response is returned even when some writes conflicted, because the task did what it promised — applied each write on its own merits — and the per-record outcomes are the answer rather than the failure. An `atomic` batch that does not apply is a trust-task-error carrying vta/app-state/put-many:atomicBatchRejected, whose details carry the same per-record outcomes.";
|
|
214
|
+
readonly type: "object";
|
|
215
|
+
readonly additionalProperties: false;
|
|
216
|
+
readonly required: readonly ["mode", "results"];
|
|
217
|
+
readonly properties: {
|
|
218
|
+
readonly mode: {
|
|
219
|
+
readonly type: "string";
|
|
220
|
+
readonly enum: readonly ["independent", "atomic"];
|
|
221
|
+
readonly description: "The mode the maintainer applied, echoed so a caller relying on the default sees what it got.";
|
|
222
|
+
};
|
|
223
|
+
readonly results: {
|
|
224
|
+
readonly type: "array";
|
|
225
|
+
readonly minItems: 1;
|
|
226
|
+
readonly maxItems: 64;
|
|
227
|
+
readonly items: {
|
|
228
|
+
readonly $ref: "#/$defs/WriteResult";
|
|
229
|
+
};
|
|
230
|
+
readonly description: "One result per requested write, in request order. Every write is accounted for.";
|
|
231
|
+
};
|
|
232
|
+
readonly highWatermark: {
|
|
233
|
+
readonly $ref: "#/$defs/Version";
|
|
234
|
+
readonly description: "The namespace's counter value after the batch. A writer that is also a sync consumer can adopt this instead of issuing a list call to discover where its own writes landed.";
|
|
235
|
+
};
|
|
236
|
+
readonly ext: {
|
|
237
|
+
readonly $ref: "#/$defs/Ext";
|
|
238
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
readonly Ext: {
|
|
243
|
+
readonly title: "Ext";
|
|
244
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
245
|
+
readonly type: "object";
|
|
246
|
+
readonly minProperties: 1;
|
|
247
|
+
readonly additionalProperties: true;
|
|
248
|
+
readonly propertyNames: {
|
|
249
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
250
|
+
};
|
|
251
|
+
};
|
|
252
|
+
readonly Version: {
|
|
253
|
+
readonly title: "Version";
|
|
254
|
+
readonly description: "A value of the namespace's monotonic write counter (see this schema's description). Server-assigned; a producer never chooses one.";
|
|
255
|
+
readonly type: "integer";
|
|
256
|
+
readonly minimum: 1;
|
|
257
|
+
};
|
|
258
|
+
readonly WriteResult: {
|
|
259
|
+
readonly title: "WriteResult";
|
|
260
|
+
readonly description: "The outcome of one write within a `vta/app-state/put-many` batch. Per-record rather than per-batch, because the default batch mode applies each write on its own merits: a caller flushing ten unrelated edits needs to know which one conflicted, not merely that something did.";
|
|
261
|
+
readonly type: "object";
|
|
262
|
+
readonly additionalProperties: false;
|
|
263
|
+
readonly required: readonly ["key", "outcome"];
|
|
264
|
+
readonly properties: {
|
|
265
|
+
readonly key: {
|
|
266
|
+
readonly $ref: "#/$defs/Key";
|
|
267
|
+
};
|
|
268
|
+
readonly outcome: {
|
|
269
|
+
readonly type: "string";
|
|
270
|
+
readonly enum: readonly ["written", "conflict", "tooLarge", "notFound", "skipped"];
|
|
271
|
+
readonly description: "`written`: applied, and `version` carries the new value. `conflict`: `expectedVersion` did not match; `currentVersion`, `currentValue` and `currentDeleted` carry the maintainer's view so the caller can resolve without a re-read. `tooLarge`: the value exceeded the per-record cap; `limitBytes` and `actualBytes` say by how much. `notFound`: a `mergePatch` write named an address with no live record. `skipped`: atomic mode only — this write was not attempted because another in the batch failed.";
|
|
272
|
+
};
|
|
273
|
+
readonly version: {
|
|
274
|
+
readonly $ref: "#/$defs/Version";
|
|
275
|
+
readonly description: "The new version, on `written`.";
|
|
276
|
+
};
|
|
277
|
+
readonly created: {
|
|
278
|
+
readonly type: "boolean";
|
|
279
|
+
readonly description: "On `written`: true when no live record existed at the address beforehand.";
|
|
280
|
+
};
|
|
281
|
+
readonly currentVersion: {
|
|
282
|
+
readonly $ref: "#/$defs/Version";
|
|
283
|
+
readonly description: "On `conflict`: the version the maintainer actually holds. Absent when the conflict is that no record exists (`expectedVersion` was positive and the address is empty).";
|
|
284
|
+
};
|
|
285
|
+
readonly currentValue: {
|
|
286
|
+
readonly description: "On `conflict`: the value the maintainer actually holds, returned WITH the rejection rather than left for the caller to re-read. A bare rejection has no fixed point under contention — between the rejection and the re-read the record can change again — so returning the winner's view removes the race rather than narrowing it. Absent when `currentDeleted` is true or no record exists.";
|
|
287
|
+
};
|
|
288
|
+
readonly currentDeleted: {
|
|
289
|
+
readonly type: "boolean";
|
|
290
|
+
readonly description: "On `conflict`: true when the address holds a tombstone rather than a live record.";
|
|
291
|
+
};
|
|
292
|
+
readonly limitBytes: {
|
|
293
|
+
readonly type: "integer";
|
|
294
|
+
readonly minimum: 0;
|
|
295
|
+
readonly description: "On `tooLarge`: the maintainer's per-record cap in bytes.";
|
|
296
|
+
};
|
|
297
|
+
readonly actualBytes: {
|
|
298
|
+
readonly type: "integer";
|
|
299
|
+
readonly minimum: 0;
|
|
300
|
+
readonly description: "On `tooLarge`: the size of the rejected value in bytes.";
|
|
301
|
+
};
|
|
302
|
+
};
|
|
303
|
+
};
|
|
304
|
+
readonly Key: {
|
|
305
|
+
readonly title: "Key";
|
|
306
|
+
readonly description: "Application-chosen identifier for a record within a namespace. Opaque to the maintainer: it MUST NOT be parsed, normalized, or case-folded, and prefix matching in `list` is a byte-prefix comparison over the UTF-8 encoding. Applications SHOULD use `/`-delimited hierarchical keys (`community/acme`, `contact/z6Mk…`) so that `prefix` can address a record family, but the delimiter is a convention between an application and itself — the maintainer attaches no meaning to it.";
|
|
307
|
+
readonly type: "string";
|
|
308
|
+
readonly minLength: 1;
|
|
309
|
+
readonly maxLength: 512;
|
|
310
|
+
readonly pattern: "^[^\\u0000]+$";
|
|
311
|
+
};
|
|
312
|
+
readonly ExpectedVersion: {
|
|
313
|
+
readonly title: "ExpectedVersion";
|
|
314
|
+
readonly description: "Optimistic-concurrency precondition on a write. A positive value requires that the record's current `version` equals it exactly. Zero means \"create only\" — the write applies only if no LIVE record exists at the address, which is what makes lease acquisition safe: without it two instances can each read \"absent\", each write, and each believe it won. A tombstone is not a live record, so `expectedVersion: 0` succeeds over one; the created record takes the namespace's next counter value, which is necessarily greater than the tombstone's.";
|
|
315
|
+
readonly type: "integer";
|
|
316
|
+
readonly minimum: 0;
|
|
317
|
+
};
|
|
318
|
+
readonly Namespace: {
|
|
319
|
+
readonly title: "Namespace";
|
|
320
|
+
readonly description: "Scopes one application's records within a context, so several tools can share a context without colliding — `openvtc`, `cnm`, an agent runtime. The maintainer MUST NOT interpret the value; it is an opaque partition name. Namespaces are first-come and unreserved, so an application SHOULD pick a stable, specific one: a future per-namespace ACL would grant on this exact string, which makes renaming a namespace a migration rather than an edit.";
|
|
321
|
+
readonly type: "string";
|
|
322
|
+
readonly minLength: 1;
|
|
323
|
+
readonly maxLength: 64;
|
|
324
|
+
readonly pattern: "^[a-z][a-z0-9]*(-[a-z0-9]+)*$";
|
|
325
|
+
};
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
/** As {@link PAYLOAD_SCHEMA}, for the success-response variant. */
|
|
329
|
+
export declare const RESPONSE_PAYLOAD_SCHEMA: {
|
|
330
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
331
|
+
readonly $ref: "#/$defs/Response";
|
|
332
|
+
readonly $defs: {
|
|
333
|
+
readonly Write: {
|
|
334
|
+
readonly title: "Write";
|
|
335
|
+
readonly description: "One write within the batch. Shaped exactly like a vta/app-state/put payload minus the context and namespace, which the batch supplies.";
|
|
336
|
+
readonly type: "object";
|
|
337
|
+
readonly additionalProperties: false;
|
|
338
|
+
readonly required: readonly ["key"];
|
|
339
|
+
readonly oneOf: readonly [{
|
|
340
|
+
readonly required: readonly ["value"];
|
|
341
|
+
readonly not: {
|
|
342
|
+
readonly required: readonly ["mergePatch"];
|
|
343
|
+
};
|
|
344
|
+
}, {
|
|
345
|
+
readonly required: readonly ["mergePatch"];
|
|
346
|
+
readonly not: {
|
|
347
|
+
readonly required: readonly ["value"];
|
|
348
|
+
};
|
|
349
|
+
}];
|
|
350
|
+
readonly properties: {
|
|
351
|
+
readonly key: {
|
|
352
|
+
readonly $ref: "#/$defs/Key";
|
|
353
|
+
};
|
|
354
|
+
readonly value: {
|
|
355
|
+
readonly description: "The complete new value, replacing whatever the record held. Any JSON value, including `null`. Mutually exclusive with `mergePatch`.";
|
|
356
|
+
};
|
|
357
|
+
readonly mergePatch: {
|
|
358
|
+
readonly type: "object";
|
|
359
|
+
readonly description: "An RFC 7386 JSON Merge Patch applied to the record's current value. Requires a live record at the address; otherwise this write's outcome is `notFound`. Mutually exclusive with `value`.";
|
|
360
|
+
};
|
|
361
|
+
readonly expectedVersion: {
|
|
362
|
+
readonly $ref: "#/$defs/ExpectedVersion";
|
|
363
|
+
readonly description: "This write's own precondition, evaluated independently of every other write in the batch. A positive value requires the record to be at exactly that version; 0 requires that no live record exists.";
|
|
364
|
+
};
|
|
365
|
+
};
|
|
366
|
+
};
|
|
367
|
+
readonly Response: {
|
|
368
|
+
readonly $anchor: "response";
|
|
369
|
+
readonly title: "VTA Application State Put-Many — response payload";
|
|
370
|
+
readonly description: "Success response to vta/app-state/put-many in `independent` mode. Type https://trusttasks.org/spec/vta/app-state/put-many/1.0#response. A response is returned even when some writes conflicted, because the task did what it promised — applied each write on its own merits — and the per-record outcomes are the answer rather than the failure. An `atomic` batch that does not apply is a trust-task-error carrying vta/app-state/put-many:atomicBatchRejected, whose details carry the same per-record outcomes.";
|
|
371
|
+
readonly type: "object";
|
|
372
|
+
readonly additionalProperties: false;
|
|
373
|
+
readonly required: readonly ["mode", "results"];
|
|
374
|
+
readonly properties: {
|
|
375
|
+
readonly mode: {
|
|
376
|
+
readonly type: "string";
|
|
377
|
+
readonly enum: readonly ["independent", "atomic"];
|
|
378
|
+
readonly description: "The mode the maintainer applied, echoed so a caller relying on the default sees what it got.";
|
|
379
|
+
};
|
|
380
|
+
readonly results: {
|
|
381
|
+
readonly type: "array";
|
|
382
|
+
readonly minItems: 1;
|
|
383
|
+
readonly maxItems: 64;
|
|
384
|
+
readonly items: {
|
|
385
|
+
readonly $ref: "#/$defs/WriteResult";
|
|
386
|
+
};
|
|
387
|
+
readonly description: "One result per requested write, in request order. Every write is accounted for.";
|
|
388
|
+
};
|
|
389
|
+
readonly highWatermark: {
|
|
390
|
+
readonly $ref: "#/$defs/Version";
|
|
391
|
+
readonly description: "The namespace's counter value after the batch. A writer that is also a sync consumer can adopt this instead of issuing a list call to discover where its own writes landed.";
|
|
392
|
+
};
|
|
393
|
+
readonly ext: {
|
|
394
|
+
readonly $ref: "#/$defs/Ext";
|
|
395
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
396
|
+
};
|
|
397
|
+
};
|
|
398
|
+
};
|
|
399
|
+
readonly Ext: {
|
|
400
|
+
readonly title: "Ext";
|
|
401
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
402
|
+
readonly type: "object";
|
|
403
|
+
readonly minProperties: 1;
|
|
404
|
+
readonly additionalProperties: true;
|
|
405
|
+
readonly propertyNames: {
|
|
406
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
407
|
+
};
|
|
408
|
+
};
|
|
409
|
+
readonly Version: {
|
|
410
|
+
readonly title: "Version";
|
|
411
|
+
readonly description: "A value of the namespace's monotonic write counter (see this schema's description). Server-assigned; a producer never chooses one.";
|
|
412
|
+
readonly type: "integer";
|
|
413
|
+
readonly minimum: 1;
|
|
414
|
+
};
|
|
415
|
+
readonly WriteResult: {
|
|
416
|
+
readonly title: "WriteResult";
|
|
417
|
+
readonly description: "The outcome of one write within a `vta/app-state/put-many` batch. Per-record rather than per-batch, because the default batch mode applies each write on its own merits: a caller flushing ten unrelated edits needs to know which one conflicted, not merely that something did.";
|
|
418
|
+
readonly type: "object";
|
|
419
|
+
readonly additionalProperties: false;
|
|
420
|
+
readonly required: readonly ["key", "outcome"];
|
|
421
|
+
readonly properties: {
|
|
422
|
+
readonly key: {
|
|
423
|
+
readonly $ref: "#/$defs/Key";
|
|
424
|
+
};
|
|
425
|
+
readonly outcome: {
|
|
426
|
+
readonly type: "string";
|
|
427
|
+
readonly enum: readonly ["written", "conflict", "tooLarge", "notFound", "skipped"];
|
|
428
|
+
readonly description: "`written`: applied, and `version` carries the new value. `conflict`: `expectedVersion` did not match; `currentVersion`, `currentValue` and `currentDeleted` carry the maintainer's view so the caller can resolve without a re-read. `tooLarge`: the value exceeded the per-record cap; `limitBytes` and `actualBytes` say by how much. `notFound`: a `mergePatch` write named an address with no live record. `skipped`: atomic mode only — this write was not attempted because another in the batch failed.";
|
|
429
|
+
};
|
|
430
|
+
readonly version: {
|
|
431
|
+
readonly $ref: "#/$defs/Version";
|
|
432
|
+
readonly description: "The new version, on `written`.";
|
|
433
|
+
};
|
|
434
|
+
readonly created: {
|
|
435
|
+
readonly type: "boolean";
|
|
436
|
+
readonly description: "On `written`: true when no live record existed at the address beforehand.";
|
|
437
|
+
};
|
|
438
|
+
readonly currentVersion: {
|
|
439
|
+
readonly $ref: "#/$defs/Version";
|
|
440
|
+
readonly description: "On `conflict`: the version the maintainer actually holds. Absent when the conflict is that no record exists (`expectedVersion` was positive and the address is empty).";
|
|
441
|
+
};
|
|
442
|
+
readonly currentValue: {
|
|
443
|
+
readonly description: "On `conflict`: the value the maintainer actually holds, returned WITH the rejection rather than left for the caller to re-read. A bare rejection has no fixed point under contention — between the rejection and the re-read the record can change again — so returning the winner's view removes the race rather than narrowing it. Absent when `currentDeleted` is true or no record exists.";
|
|
444
|
+
};
|
|
445
|
+
readonly currentDeleted: {
|
|
446
|
+
readonly type: "boolean";
|
|
447
|
+
readonly description: "On `conflict`: true when the address holds a tombstone rather than a live record.";
|
|
448
|
+
};
|
|
449
|
+
readonly limitBytes: {
|
|
450
|
+
readonly type: "integer";
|
|
451
|
+
readonly minimum: 0;
|
|
452
|
+
readonly description: "On `tooLarge`: the maintainer's per-record cap in bytes.";
|
|
453
|
+
};
|
|
454
|
+
readonly actualBytes: {
|
|
455
|
+
readonly type: "integer";
|
|
456
|
+
readonly minimum: 0;
|
|
457
|
+
readonly description: "On `tooLarge`: the size of the rejected value in bytes.";
|
|
458
|
+
};
|
|
459
|
+
};
|
|
460
|
+
};
|
|
461
|
+
readonly Key: {
|
|
462
|
+
readonly title: "Key";
|
|
463
|
+
readonly description: "Application-chosen identifier for a record within a namespace. Opaque to the maintainer: it MUST NOT be parsed, normalized, or case-folded, and prefix matching in `list` is a byte-prefix comparison over the UTF-8 encoding. Applications SHOULD use `/`-delimited hierarchical keys (`community/acme`, `contact/z6Mk…`) so that `prefix` can address a record family, but the delimiter is a convention between an application and itself — the maintainer attaches no meaning to it.";
|
|
464
|
+
readonly type: "string";
|
|
465
|
+
readonly minLength: 1;
|
|
466
|
+
readonly maxLength: 512;
|
|
467
|
+
readonly pattern: "^[^\\u0000]+$";
|
|
468
|
+
};
|
|
469
|
+
readonly ExpectedVersion: {
|
|
470
|
+
readonly title: "ExpectedVersion";
|
|
471
|
+
readonly description: "Optimistic-concurrency precondition on a write. A positive value requires that the record's current `version` equals it exactly. Zero means \"create only\" — the write applies only if no LIVE record exists at the address, which is what makes lease acquisition safe: without it two instances can each read \"absent\", each write, and each believe it won. A tombstone is not a live record, so `expectedVersion: 0` succeeds over one; the created record takes the namespace's next counter value, which is necessarily greater than the tombstone's.";
|
|
472
|
+
readonly type: "integer";
|
|
473
|
+
readonly minimum: 0;
|
|
474
|
+
};
|
|
475
|
+
readonly Namespace: {
|
|
476
|
+
readonly title: "Namespace";
|
|
477
|
+
readonly description: "Scopes one application's records within a context, so several tools can share a context without colliding — `openvtc`, `cnm`, an agent runtime. The maintainer MUST NOT interpret the value; it is an opaque partition name. Namespaces are first-come and unreserved, so an application SHOULD pick a stable, specific one: a future per-namespace ACL would grant on this exact string, which makes renaming a namespace a migration rather than an edit.";
|
|
478
|
+
readonly type: "string";
|
|
479
|
+
readonly minLength: 1;
|
|
480
|
+
readonly maxLength: 64;
|
|
481
|
+
readonly pattern: "^[a-z][a-z0-9]*(-[a-z0-9]+)*$";
|
|
482
|
+
};
|
|
483
|
+
};
|
|
484
|
+
};
|
|
485
|
+
/**
|
|
486
|
+
* SPEC.md §7.2 policy for the request variant, from this specification's
|
|
487
|
+
* front matter. Pass to `consumeInbound` — items 5b, 7 and 8 are
|
|
488
|
+
* per-specification and cannot be derived from the document alone, and
|
|
489
|
+
* item 2 needs the schema this carries.
|
|
490
|
+
*/
|
|
491
|
+
export declare const SPEC: {
|
|
492
|
+
readonly typeUri: "https://trusttasks.org/spec/vta/app-state/put-many/1.0";
|
|
493
|
+
readonly isBearer: false;
|
|
494
|
+
readonly isProofRequired: true;
|
|
495
|
+
readonly isRecipientRequired: true;
|
|
496
|
+
readonly payloadSchema: {
|
|
497
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
498
|
+
readonly $id: "https://trusttasks.org/spec/vta/app-state/put-many/1.0";
|
|
499
|
+
readonly title: "VTA Application State Put-Many — payload";
|
|
500
|
+
readonly description: "Write up to 64 application-state records in one round trip, each carrying its own optimistic-concurrency precondition. The batch `mode` decides what a single failure costs: `independent` (the default) applies each write on its own merits, `atomic` applies all or none.";
|
|
501
|
+
readonly type: "object";
|
|
502
|
+
readonly additionalProperties: false;
|
|
503
|
+
readonly required: readonly ["contextId", "namespace", "writes"];
|
|
504
|
+
readonly properties: {
|
|
505
|
+
readonly contextId: {
|
|
506
|
+
readonly type: "string";
|
|
507
|
+
readonly minLength: 1;
|
|
508
|
+
readonly description: "The VTA context the records are scoped to; the isolation boundary.";
|
|
509
|
+
};
|
|
510
|
+
readonly namespace: {
|
|
511
|
+
readonly $ref: "#/$defs/Namespace";
|
|
512
|
+
readonly description: "One namespace per batch. Atomicity is only meaningful within the counter the writes take their versions from, and that counter is per (contextId, namespace).";
|
|
513
|
+
};
|
|
514
|
+
readonly mode: {
|
|
515
|
+
readonly type: "string";
|
|
516
|
+
readonly enum: readonly ["independent", "atomic"];
|
|
517
|
+
readonly default: "independent";
|
|
518
|
+
readonly description: "`independent` applies each write on its own merits, so one conflicted record does not block the other nine — what a flush of unrelated edits wants, and why it is the default. `atomic` applies all or none, for records carrying a joint invariant. An atomic DEFAULT would let one stale record silently wedge an entire flush, and a caller could not tell a wedged flush from a slow one.";
|
|
519
|
+
readonly $comment: "The default is load-bearing rather than a convenience; see the spec's Abstract.";
|
|
520
|
+
};
|
|
521
|
+
readonly writes: {
|
|
522
|
+
readonly type: "array";
|
|
523
|
+
readonly minItems: 1;
|
|
524
|
+
readonly maxItems: 64;
|
|
525
|
+
readonly items: {
|
|
526
|
+
readonly $ref: "#/$defs/Write";
|
|
527
|
+
};
|
|
528
|
+
readonly description: "The writes to apply. Keys MUST be distinct: two writes to one key in a batch have no defined order and are refused rather than serialised.";
|
|
529
|
+
};
|
|
530
|
+
readonly ext: {
|
|
531
|
+
readonly $ref: "#/$defs/Ext";
|
|
532
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
533
|
+
};
|
|
534
|
+
};
|
|
535
|
+
readonly $defs: {
|
|
536
|
+
readonly Write: {
|
|
537
|
+
readonly title: "Write";
|
|
538
|
+
readonly description: "One write within the batch. Shaped exactly like a vta/app-state/put payload minus the context and namespace, which the batch supplies.";
|
|
539
|
+
readonly type: "object";
|
|
540
|
+
readonly additionalProperties: false;
|
|
541
|
+
readonly required: readonly ["key"];
|
|
542
|
+
readonly oneOf: readonly [{
|
|
543
|
+
readonly required: readonly ["value"];
|
|
544
|
+
readonly not: {
|
|
545
|
+
readonly required: readonly ["mergePatch"];
|
|
546
|
+
};
|
|
547
|
+
}, {
|
|
548
|
+
readonly required: readonly ["mergePatch"];
|
|
549
|
+
readonly not: {
|
|
550
|
+
readonly required: readonly ["value"];
|
|
551
|
+
};
|
|
552
|
+
}];
|
|
553
|
+
readonly properties: {
|
|
554
|
+
readonly key: {
|
|
555
|
+
readonly $ref: "#/$defs/Key";
|
|
556
|
+
};
|
|
557
|
+
readonly value: {
|
|
558
|
+
readonly description: "The complete new value, replacing whatever the record held. Any JSON value, including `null`. Mutually exclusive with `mergePatch`.";
|
|
559
|
+
};
|
|
560
|
+
readonly mergePatch: {
|
|
561
|
+
readonly type: "object";
|
|
562
|
+
readonly description: "An RFC 7386 JSON Merge Patch applied to the record's current value. Requires a live record at the address; otherwise this write's outcome is `notFound`. Mutually exclusive with `value`.";
|
|
563
|
+
};
|
|
564
|
+
readonly expectedVersion: {
|
|
565
|
+
readonly $ref: "#/$defs/ExpectedVersion";
|
|
566
|
+
readonly description: "This write's own precondition, evaluated independently of every other write in the batch. A positive value requires the record to be at exactly that version; 0 requires that no live record exists.";
|
|
567
|
+
};
|
|
568
|
+
};
|
|
569
|
+
};
|
|
570
|
+
readonly Response: {
|
|
571
|
+
readonly $anchor: "response";
|
|
572
|
+
readonly title: "VTA Application State Put-Many — response payload";
|
|
573
|
+
readonly description: "Success response to vta/app-state/put-many in `independent` mode. Type https://trusttasks.org/spec/vta/app-state/put-many/1.0#response. A response is returned even when some writes conflicted, because the task did what it promised — applied each write on its own merits — and the per-record outcomes are the answer rather than the failure. An `atomic` batch that does not apply is a trust-task-error carrying vta/app-state/put-many:atomicBatchRejected, whose details carry the same per-record outcomes.";
|
|
574
|
+
readonly type: "object";
|
|
575
|
+
readonly additionalProperties: false;
|
|
576
|
+
readonly required: readonly ["mode", "results"];
|
|
577
|
+
readonly properties: {
|
|
578
|
+
readonly mode: {
|
|
579
|
+
readonly type: "string";
|
|
580
|
+
readonly enum: readonly ["independent", "atomic"];
|
|
581
|
+
readonly description: "The mode the maintainer applied, echoed so a caller relying on the default sees what it got.";
|
|
582
|
+
};
|
|
583
|
+
readonly results: {
|
|
584
|
+
readonly type: "array";
|
|
585
|
+
readonly minItems: 1;
|
|
586
|
+
readonly maxItems: 64;
|
|
587
|
+
readonly items: {
|
|
588
|
+
readonly $ref: "#/$defs/WriteResult";
|
|
589
|
+
};
|
|
590
|
+
readonly description: "One result per requested write, in request order. Every write is accounted for.";
|
|
591
|
+
};
|
|
592
|
+
readonly highWatermark: {
|
|
593
|
+
readonly $ref: "#/$defs/Version";
|
|
594
|
+
readonly description: "The namespace's counter value after the batch. A writer that is also a sync consumer can adopt this instead of issuing a list call to discover where its own writes landed.";
|
|
595
|
+
};
|
|
596
|
+
readonly ext: {
|
|
597
|
+
readonly $ref: "#/$defs/Ext";
|
|
598
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
599
|
+
};
|
|
600
|
+
};
|
|
601
|
+
};
|
|
602
|
+
readonly Ext: {
|
|
603
|
+
readonly title: "Ext";
|
|
604
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
605
|
+
readonly type: "object";
|
|
606
|
+
readonly minProperties: 1;
|
|
607
|
+
readonly additionalProperties: true;
|
|
608
|
+
readonly propertyNames: {
|
|
609
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
610
|
+
};
|
|
611
|
+
};
|
|
612
|
+
readonly Version: {
|
|
613
|
+
readonly title: "Version";
|
|
614
|
+
readonly description: "A value of the namespace's monotonic write counter (see this schema's description). Server-assigned; a producer never chooses one.";
|
|
615
|
+
readonly type: "integer";
|
|
616
|
+
readonly minimum: 1;
|
|
617
|
+
};
|
|
618
|
+
readonly WriteResult: {
|
|
619
|
+
readonly title: "WriteResult";
|
|
620
|
+
readonly description: "The outcome of one write within a `vta/app-state/put-many` batch. Per-record rather than per-batch, because the default batch mode applies each write on its own merits: a caller flushing ten unrelated edits needs to know which one conflicted, not merely that something did.";
|
|
621
|
+
readonly type: "object";
|
|
622
|
+
readonly additionalProperties: false;
|
|
623
|
+
readonly required: readonly ["key", "outcome"];
|
|
624
|
+
readonly properties: {
|
|
625
|
+
readonly key: {
|
|
626
|
+
readonly $ref: "#/$defs/Key";
|
|
627
|
+
};
|
|
628
|
+
readonly outcome: {
|
|
629
|
+
readonly type: "string";
|
|
630
|
+
readonly enum: readonly ["written", "conflict", "tooLarge", "notFound", "skipped"];
|
|
631
|
+
readonly description: "`written`: applied, and `version` carries the new value. `conflict`: `expectedVersion` did not match; `currentVersion`, `currentValue` and `currentDeleted` carry the maintainer's view so the caller can resolve without a re-read. `tooLarge`: the value exceeded the per-record cap; `limitBytes` and `actualBytes` say by how much. `notFound`: a `mergePatch` write named an address with no live record. `skipped`: atomic mode only — this write was not attempted because another in the batch failed.";
|
|
632
|
+
};
|
|
633
|
+
readonly version: {
|
|
634
|
+
readonly $ref: "#/$defs/Version";
|
|
635
|
+
readonly description: "The new version, on `written`.";
|
|
636
|
+
};
|
|
637
|
+
readonly created: {
|
|
638
|
+
readonly type: "boolean";
|
|
639
|
+
readonly description: "On `written`: true when no live record existed at the address beforehand.";
|
|
640
|
+
};
|
|
641
|
+
readonly currentVersion: {
|
|
642
|
+
readonly $ref: "#/$defs/Version";
|
|
643
|
+
readonly description: "On `conflict`: the version the maintainer actually holds. Absent when the conflict is that no record exists (`expectedVersion` was positive and the address is empty).";
|
|
644
|
+
};
|
|
645
|
+
readonly currentValue: {
|
|
646
|
+
readonly description: "On `conflict`: the value the maintainer actually holds, returned WITH the rejection rather than left for the caller to re-read. A bare rejection has no fixed point under contention — between the rejection and the re-read the record can change again — so returning the winner's view removes the race rather than narrowing it. Absent when `currentDeleted` is true or no record exists.";
|
|
647
|
+
};
|
|
648
|
+
readonly currentDeleted: {
|
|
649
|
+
readonly type: "boolean";
|
|
650
|
+
readonly description: "On `conflict`: true when the address holds a tombstone rather than a live record.";
|
|
651
|
+
};
|
|
652
|
+
readonly limitBytes: {
|
|
653
|
+
readonly type: "integer";
|
|
654
|
+
readonly minimum: 0;
|
|
655
|
+
readonly description: "On `tooLarge`: the maintainer's per-record cap in bytes.";
|
|
656
|
+
};
|
|
657
|
+
readonly actualBytes: {
|
|
658
|
+
readonly type: "integer";
|
|
659
|
+
readonly minimum: 0;
|
|
660
|
+
readonly description: "On `tooLarge`: the size of the rejected value in bytes.";
|
|
661
|
+
};
|
|
662
|
+
};
|
|
663
|
+
};
|
|
664
|
+
readonly Key: {
|
|
665
|
+
readonly title: "Key";
|
|
666
|
+
readonly description: "Application-chosen identifier for a record within a namespace. Opaque to the maintainer: it MUST NOT be parsed, normalized, or case-folded, and prefix matching in `list` is a byte-prefix comparison over the UTF-8 encoding. Applications SHOULD use `/`-delimited hierarchical keys (`community/acme`, `contact/z6Mk…`) so that `prefix` can address a record family, but the delimiter is a convention between an application and itself — the maintainer attaches no meaning to it.";
|
|
667
|
+
readonly type: "string";
|
|
668
|
+
readonly minLength: 1;
|
|
669
|
+
readonly maxLength: 512;
|
|
670
|
+
readonly pattern: "^[^\\u0000]+$";
|
|
671
|
+
};
|
|
672
|
+
readonly ExpectedVersion: {
|
|
673
|
+
readonly title: "ExpectedVersion";
|
|
674
|
+
readonly description: "Optimistic-concurrency precondition on a write. A positive value requires that the record's current `version` equals it exactly. Zero means \"create only\" — the write applies only if no LIVE record exists at the address, which is what makes lease acquisition safe: without it two instances can each read \"absent\", each write, and each believe it won. A tombstone is not a live record, so `expectedVersion: 0` succeeds over one; the created record takes the namespace's next counter value, which is necessarily greater than the tombstone's.";
|
|
675
|
+
readonly type: "integer";
|
|
676
|
+
readonly minimum: 0;
|
|
677
|
+
};
|
|
678
|
+
readonly Namespace: {
|
|
679
|
+
readonly title: "Namespace";
|
|
680
|
+
readonly description: "Scopes one application's records within a context, so several tools can share a context without colliding — `openvtc`, `cnm`, an agent runtime. The maintainer MUST NOT interpret the value; it is an opaque partition name. Namespaces are first-come and unreserved, so an application SHOULD pick a stable, specific one: a future per-namespace ACL would grant on this exact string, which makes renaming a namespace a migration rather than an edit.";
|
|
681
|
+
readonly type: "string";
|
|
682
|
+
readonly minLength: 1;
|
|
683
|
+
readonly maxLength: 64;
|
|
684
|
+
readonly pattern: "^[a-z][a-z0-9]*(-[a-z0-9]+)*$";
|
|
685
|
+
};
|
|
686
|
+
};
|
|
687
|
+
};
|
|
688
|
+
};
|
|
689
|
+
/**
|
|
690
|
+
* SPEC.md §7.2 policy for the success-response variant. `isRecipientRequired`
|
|
691
|
+
* tracks the *issuer* party's requirement because a response swaps the
|
|
692
|
+
* parties (§7.3 item 5).
|
|
693
|
+
*/
|
|
694
|
+
export declare const RESPONSE_SPEC: {
|
|
695
|
+
readonly typeUri: "https://trusttasks.org/spec/vta/app-state/put-many/1.0#response";
|
|
696
|
+
readonly isBearer: false;
|
|
697
|
+
readonly isProofRequired: true;
|
|
698
|
+
readonly isRecipientRequired: true;
|
|
699
|
+
readonly payloadSchema: {
|
|
700
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
701
|
+
readonly $ref: "#/$defs/Response";
|
|
702
|
+
readonly $defs: {
|
|
703
|
+
readonly Write: {
|
|
704
|
+
readonly title: "Write";
|
|
705
|
+
readonly description: "One write within the batch. Shaped exactly like a vta/app-state/put payload minus the context and namespace, which the batch supplies.";
|
|
706
|
+
readonly type: "object";
|
|
707
|
+
readonly additionalProperties: false;
|
|
708
|
+
readonly required: readonly ["key"];
|
|
709
|
+
readonly oneOf: readonly [{
|
|
710
|
+
readonly required: readonly ["value"];
|
|
711
|
+
readonly not: {
|
|
712
|
+
readonly required: readonly ["mergePatch"];
|
|
713
|
+
};
|
|
714
|
+
}, {
|
|
715
|
+
readonly required: readonly ["mergePatch"];
|
|
716
|
+
readonly not: {
|
|
717
|
+
readonly required: readonly ["value"];
|
|
718
|
+
};
|
|
719
|
+
}];
|
|
720
|
+
readonly properties: {
|
|
721
|
+
readonly key: {
|
|
722
|
+
readonly $ref: "#/$defs/Key";
|
|
723
|
+
};
|
|
724
|
+
readonly value: {
|
|
725
|
+
readonly description: "The complete new value, replacing whatever the record held. Any JSON value, including `null`. Mutually exclusive with `mergePatch`.";
|
|
726
|
+
};
|
|
727
|
+
readonly mergePatch: {
|
|
728
|
+
readonly type: "object";
|
|
729
|
+
readonly description: "An RFC 7386 JSON Merge Patch applied to the record's current value. Requires a live record at the address; otherwise this write's outcome is `notFound`. Mutually exclusive with `value`.";
|
|
730
|
+
};
|
|
731
|
+
readonly expectedVersion: {
|
|
732
|
+
readonly $ref: "#/$defs/ExpectedVersion";
|
|
733
|
+
readonly description: "This write's own precondition, evaluated independently of every other write in the batch. A positive value requires the record to be at exactly that version; 0 requires that no live record exists.";
|
|
734
|
+
};
|
|
735
|
+
};
|
|
736
|
+
};
|
|
737
|
+
readonly Response: {
|
|
738
|
+
readonly $anchor: "response";
|
|
739
|
+
readonly title: "VTA Application State Put-Many — response payload";
|
|
740
|
+
readonly description: "Success response to vta/app-state/put-many in `independent` mode. Type https://trusttasks.org/spec/vta/app-state/put-many/1.0#response. A response is returned even when some writes conflicted, because the task did what it promised — applied each write on its own merits — and the per-record outcomes are the answer rather than the failure. An `atomic` batch that does not apply is a trust-task-error carrying vta/app-state/put-many:atomicBatchRejected, whose details carry the same per-record outcomes.";
|
|
741
|
+
readonly type: "object";
|
|
742
|
+
readonly additionalProperties: false;
|
|
743
|
+
readonly required: readonly ["mode", "results"];
|
|
744
|
+
readonly properties: {
|
|
745
|
+
readonly mode: {
|
|
746
|
+
readonly type: "string";
|
|
747
|
+
readonly enum: readonly ["independent", "atomic"];
|
|
748
|
+
readonly description: "The mode the maintainer applied, echoed so a caller relying on the default sees what it got.";
|
|
749
|
+
};
|
|
750
|
+
readonly results: {
|
|
751
|
+
readonly type: "array";
|
|
752
|
+
readonly minItems: 1;
|
|
753
|
+
readonly maxItems: 64;
|
|
754
|
+
readonly items: {
|
|
755
|
+
readonly $ref: "#/$defs/WriteResult";
|
|
756
|
+
};
|
|
757
|
+
readonly description: "One result per requested write, in request order. Every write is accounted for.";
|
|
758
|
+
};
|
|
759
|
+
readonly highWatermark: {
|
|
760
|
+
readonly $ref: "#/$defs/Version";
|
|
761
|
+
readonly description: "The namespace's counter value after the batch. A writer that is also a sync consumer can adopt this instead of issuing a list call to discover where its own writes landed.";
|
|
762
|
+
};
|
|
763
|
+
readonly ext: {
|
|
764
|
+
readonly $ref: "#/$defs/Ext";
|
|
765
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1.";
|
|
766
|
+
};
|
|
767
|
+
};
|
|
768
|
+
};
|
|
769
|
+
readonly Ext: {
|
|
770
|
+
readonly title: "Ext";
|
|
771
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
772
|
+
readonly type: "object";
|
|
773
|
+
readonly minProperties: 1;
|
|
774
|
+
readonly additionalProperties: true;
|
|
775
|
+
readonly propertyNames: {
|
|
776
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
777
|
+
};
|
|
778
|
+
};
|
|
779
|
+
readonly Version: {
|
|
780
|
+
readonly title: "Version";
|
|
781
|
+
readonly description: "A value of the namespace's monotonic write counter (see this schema's description). Server-assigned; a producer never chooses one.";
|
|
782
|
+
readonly type: "integer";
|
|
783
|
+
readonly minimum: 1;
|
|
784
|
+
};
|
|
785
|
+
readonly WriteResult: {
|
|
786
|
+
readonly title: "WriteResult";
|
|
787
|
+
readonly description: "The outcome of one write within a `vta/app-state/put-many` batch. Per-record rather than per-batch, because the default batch mode applies each write on its own merits: a caller flushing ten unrelated edits needs to know which one conflicted, not merely that something did.";
|
|
788
|
+
readonly type: "object";
|
|
789
|
+
readonly additionalProperties: false;
|
|
790
|
+
readonly required: readonly ["key", "outcome"];
|
|
791
|
+
readonly properties: {
|
|
792
|
+
readonly key: {
|
|
793
|
+
readonly $ref: "#/$defs/Key";
|
|
794
|
+
};
|
|
795
|
+
readonly outcome: {
|
|
796
|
+
readonly type: "string";
|
|
797
|
+
readonly enum: readonly ["written", "conflict", "tooLarge", "notFound", "skipped"];
|
|
798
|
+
readonly description: "`written`: applied, and `version` carries the new value. `conflict`: `expectedVersion` did not match; `currentVersion`, `currentValue` and `currentDeleted` carry the maintainer's view so the caller can resolve without a re-read. `tooLarge`: the value exceeded the per-record cap; `limitBytes` and `actualBytes` say by how much. `notFound`: a `mergePatch` write named an address with no live record. `skipped`: atomic mode only — this write was not attempted because another in the batch failed.";
|
|
799
|
+
};
|
|
800
|
+
readonly version: {
|
|
801
|
+
readonly $ref: "#/$defs/Version";
|
|
802
|
+
readonly description: "The new version, on `written`.";
|
|
803
|
+
};
|
|
804
|
+
readonly created: {
|
|
805
|
+
readonly type: "boolean";
|
|
806
|
+
readonly description: "On `written`: true when no live record existed at the address beforehand.";
|
|
807
|
+
};
|
|
808
|
+
readonly currentVersion: {
|
|
809
|
+
readonly $ref: "#/$defs/Version";
|
|
810
|
+
readonly description: "On `conflict`: the version the maintainer actually holds. Absent when the conflict is that no record exists (`expectedVersion` was positive and the address is empty).";
|
|
811
|
+
};
|
|
812
|
+
readonly currentValue: {
|
|
813
|
+
readonly description: "On `conflict`: the value the maintainer actually holds, returned WITH the rejection rather than left for the caller to re-read. A bare rejection has no fixed point under contention — between the rejection and the re-read the record can change again — so returning the winner's view removes the race rather than narrowing it. Absent when `currentDeleted` is true or no record exists.";
|
|
814
|
+
};
|
|
815
|
+
readonly currentDeleted: {
|
|
816
|
+
readonly type: "boolean";
|
|
817
|
+
readonly description: "On `conflict`: true when the address holds a tombstone rather than a live record.";
|
|
818
|
+
};
|
|
819
|
+
readonly limitBytes: {
|
|
820
|
+
readonly type: "integer";
|
|
821
|
+
readonly minimum: 0;
|
|
822
|
+
readonly description: "On `tooLarge`: the maintainer's per-record cap in bytes.";
|
|
823
|
+
};
|
|
824
|
+
readonly actualBytes: {
|
|
825
|
+
readonly type: "integer";
|
|
826
|
+
readonly minimum: 0;
|
|
827
|
+
readonly description: "On `tooLarge`: the size of the rejected value in bytes.";
|
|
828
|
+
};
|
|
829
|
+
};
|
|
830
|
+
};
|
|
831
|
+
readonly Key: {
|
|
832
|
+
readonly title: "Key";
|
|
833
|
+
readonly description: "Application-chosen identifier for a record within a namespace. Opaque to the maintainer: it MUST NOT be parsed, normalized, or case-folded, and prefix matching in `list` is a byte-prefix comparison over the UTF-8 encoding. Applications SHOULD use `/`-delimited hierarchical keys (`community/acme`, `contact/z6Mk…`) so that `prefix` can address a record family, but the delimiter is a convention between an application and itself — the maintainer attaches no meaning to it.";
|
|
834
|
+
readonly type: "string";
|
|
835
|
+
readonly minLength: 1;
|
|
836
|
+
readonly maxLength: 512;
|
|
837
|
+
readonly pattern: "^[^\\u0000]+$";
|
|
838
|
+
};
|
|
839
|
+
readonly ExpectedVersion: {
|
|
840
|
+
readonly title: "ExpectedVersion";
|
|
841
|
+
readonly description: "Optimistic-concurrency precondition on a write. A positive value requires that the record's current `version` equals it exactly. Zero means \"create only\" — the write applies only if no LIVE record exists at the address, which is what makes lease acquisition safe: without it two instances can each read \"absent\", each write, and each believe it won. A tombstone is not a live record, so `expectedVersion: 0` succeeds over one; the created record takes the namespace's next counter value, which is necessarily greater than the tombstone's.";
|
|
842
|
+
readonly type: "integer";
|
|
843
|
+
readonly minimum: 0;
|
|
844
|
+
};
|
|
845
|
+
readonly Namespace: {
|
|
846
|
+
readonly title: "Namespace";
|
|
847
|
+
readonly description: "Scopes one application's records within a context, so several tools can share a context without colliding — `openvtc`, `cnm`, an agent runtime. The maintainer MUST NOT interpret the value; it is an opaque partition name. Namespaces are first-come and unreserved, so an application SHOULD pick a stable, specific one: a future per-namespace ACL would grant on this exact string, which makes renaming a namespace a migration rather than an edit.";
|
|
848
|
+
readonly type: "string";
|
|
849
|
+
readonly minLength: 1;
|
|
850
|
+
readonly maxLength: 64;
|
|
851
|
+
readonly pattern: "^[a-z][a-z0-9]*(-[a-z0-9]+)*$";
|
|
852
|
+
};
|
|
853
|
+
};
|
|
854
|
+
};
|
|
855
|
+
};
|
|
856
|
+
//# sourceMappingURL=payload.d.ts.map
|