mcp-usage-control 1.0.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/LICENSE +201 -0
- package/README.md +141 -0
- package/dist/index.d.ts +533 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2131 -0
- package/dist/index.js.map +1 -0
- package/dist/observability.d.ts +154 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +171 -0
- package/dist/observability.js.map +1 -0
- package/dist/operational.d.ts +87 -0
- package/dist/operational.d.ts.map +1 -0
- package/dist/operational.js +193 -0
- package/dist/operational.js.map +1 -0
- package/dist/progressive-store-conformance.d.ts +4 -0
- package/dist/progressive-store-conformance.d.ts.map +1 -0
- package/dist/progressive-store-conformance.js +333 -0
- package/dist/progressive-store-conformance.js.map +1 -0
- package/dist/reconciliation-conformance.d.ts +36 -0
- package/dist/reconciliation-conformance.d.ts.map +1 -0
- package/dist/reconciliation-conformance.js +211 -0
- package/dist/reconciliation-conformance.js.map +1 -0
- package/dist/settlement-outcomes.d.ts +24 -0
- package/dist/settlement-outcomes.d.ts.map +1 -0
- package/dist/settlement-outcomes.js +68 -0
- package/dist/settlement-outcomes.js.map +1 -0
- package/dist/store-conformance.d.ts +50 -0
- package/dist/store-conformance.d.ts.map +1 -0
- package/dist/store-conformance.js +378 -0
- package/dist/store-conformance.js.map +1 -0
- package/dist/thresholds.d.ts +26 -0
- package/dist/thresholds.d.ts.map +1 -0
- package/dist/thresholds.js +56 -0
- package/dist/thresholds.js.map +1 -0
- package/dist/vector-store-conformance.d.ts +4 -0
- package/dist/vector-store-conformance.d.ts.map +1 -0
- package/dist/vector-store-conformance.js +297 -0
- package/dist/vector-store-conformance.js.map +1 -0
- package/dist/weighted-credits.d.ts +41 -0
- package/dist/weighted-credits.d.ts.map +1 -0
- package/dist/weighted-credits.js +143 -0
- package/dist/weighted-credits.js.map +1 -0
- package/dist/windowed-budget-keys.d.ts +36 -0
- package/dist/windowed-budget-keys.d.ts.map +1 -0
- package/dist/windowed-budget-keys.js +178 -0
- package/dist/windowed-budget-keys.js.map +1 -0
- package/package.json +113 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
export * from './reconciliation-conformance.js';
|
|
2
|
+
export * from './progressive-store-conformance.js';
|
|
3
|
+
export * from './vector-store-conformance.js';
|
|
4
|
+
export class UsageStoreConformanceError extends Error {
|
|
5
|
+
report;
|
|
6
|
+
constructor(report) {
|
|
7
|
+
const failed = report.cases.filter(result => !result.passed);
|
|
8
|
+
super(`UsageStore conformance failed: ${failed
|
|
9
|
+
.map(result => `${result.name}: ${result.error ?? 'unknown failure'}`)
|
|
10
|
+
.join('; ')}`);
|
|
11
|
+
this.report = report;
|
|
12
|
+
this.name = 'UsageStoreConformanceError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Run the portable, provider-neutral behavioral contract for a UsageStore.
|
|
17
|
+
*
|
|
18
|
+
* Passing this suite means that the public store semantics are compatible. It
|
|
19
|
+
* does not by itself prove persistence/HA, store-time authority, network ACK
|
|
20
|
+
* ambiguity behavior, or platform-specific fault tolerance. Those production
|
|
21
|
+
* safety requirements need adapter-specific evidence in addition to this suite.
|
|
22
|
+
*/
|
|
23
|
+
export async function runUsageStoreConformance(harness) {
|
|
24
|
+
const leaseTtlMs = harness.leaseTtlMs ?? 40;
|
|
25
|
+
const concurrency = harness.concurrency ?? 16;
|
|
26
|
+
assertPositiveInteger(leaseTtlMs, 'leaseTtlMs');
|
|
27
|
+
assertPositiveInteger(concurrency, 'concurrency');
|
|
28
|
+
const cases = [];
|
|
29
|
+
await runCase(harness, cases, 'atomic-multi-budget-denial', async (store) => {
|
|
30
|
+
const blocking = await store.reserve({
|
|
31
|
+
request: request('seed-blocking'),
|
|
32
|
+
units: 1,
|
|
33
|
+
budgets: [{ key: 'contract:blocking', limit: 1 }],
|
|
34
|
+
ttlMs: 5_000,
|
|
35
|
+
});
|
|
36
|
+
assertAccepted(blocking, 'seed reservation');
|
|
37
|
+
const denied = await store.reserve({
|
|
38
|
+
request: request('must-not-partially-reserve'),
|
|
39
|
+
units: 1,
|
|
40
|
+
budgets: [
|
|
41
|
+
{ key: 'contract:free', limit: 1 },
|
|
42
|
+
{ key: 'contract:blocking', limit: 1 },
|
|
43
|
+
],
|
|
44
|
+
ttlMs: 5_000,
|
|
45
|
+
});
|
|
46
|
+
assertDenied(denied, 'quota_exceeded', 'multi-budget denial');
|
|
47
|
+
const probe = await store.reserve({
|
|
48
|
+
request: request('probe-free-budget'),
|
|
49
|
+
units: 1,
|
|
50
|
+
budgets: [{ key: 'contract:free', limit: 1 }],
|
|
51
|
+
ttlMs: 5_000,
|
|
52
|
+
});
|
|
53
|
+
assertAccepted(probe, 'free budget after denied multi-budget reservation');
|
|
54
|
+
});
|
|
55
|
+
await runCase(harness, cases, 'concurrent-admission', async (store) => {
|
|
56
|
+
const results = await Promise.all(Array.from({ length: concurrency }, (_, index) => store.reserve({
|
|
57
|
+
request: request(`concurrent-${index}`, `user-${index}`),
|
|
58
|
+
units: 1,
|
|
59
|
+
budgets: [{ key: 'contract:shared-concurrent', limit: 1 }],
|
|
60
|
+
ttlMs: 5_000,
|
|
61
|
+
})));
|
|
62
|
+
const accepted = results.filter(result => result.accepted);
|
|
63
|
+
const denied = results.filter(result => !result.accepted);
|
|
64
|
+
assert(accepted.length === 1, `expected exactly one concurrent admission, got ${accepted.length}`);
|
|
65
|
+
assert(denied.length === concurrency - 1 &&
|
|
66
|
+
denied.every(result => result.reason === 'quota_exceeded'), 'all losing concurrent admissions must be quota_exceeded');
|
|
67
|
+
});
|
|
68
|
+
await runCase(harness, cases, 'mutable-limit-increase-preserves-usage', async (store) => {
|
|
69
|
+
const budgetKey = 'contract:mutable-increase';
|
|
70
|
+
const seed = await store.reserve({
|
|
71
|
+
request: request('mutable-increase-seed'),
|
|
72
|
+
units: 2,
|
|
73
|
+
budgets: [{ key: budgetKey, limit: 2 }],
|
|
74
|
+
ttlMs: 5_000,
|
|
75
|
+
});
|
|
76
|
+
assertAccepted(seed, 'initial full bucket');
|
|
77
|
+
const deniedAtOldLimit = await store.reserve({
|
|
78
|
+
request: request('mutable-increase-old-limit'),
|
|
79
|
+
units: 1,
|
|
80
|
+
budgets: [{ key: budgetKey, limit: 2 }],
|
|
81
|
+
ttlMs: 5_000,
|
|
82
|
+
});
|
|
83
|
+
assertDenied(deniedAtOldLimit, 'quota_exceeded', 'admission at old full limit');
|
|
84
|
+
const admittedAtHigherLimit = await store.reserve({
|
|
85
|
+
request: request('mutable-increase-new-limit'),
|
|
86
|
+
units: 1,
|
|
87
|
+
budgets: [{ key: budgetKey, limit: 3 }],
|
|
88
|
+
ttlMs: 5_000,
|
|
89
|
+
});
|
|
90
|
+
assertAccepted(admittedAtHigherLimit, 'admission after limit increase');
|
|
91
|
+
const exhaustedAtHigherLimit = await store.reserve({
|
|
92
|
+
request: request('mutable-increase-exhausted'),
|
|
93
|
+
units: 1,
|
|
94
|
+
budgets: [{ key: budgetKey, limit: 3 }],
|
|
95
|
+
ttlMs: 5_000,
|
|
96
|
+
});
|
|
97
|
+
assertDenied(exhaustedAtHigherLimit, 'quota_exceeded', 'existing usage must remain counted after limit increase');
|
|
98
|
+
});
|
|
99
|
+
await runCase(harness, cases, 'mutable-limit-decrease-preserves-active-and-used-state', async (store) => {
|
|
100
|
+
const budgetKey = 'contract:mutable-decrease';
|
|
101
|
+
const active = await store.reserve({
|
|
102
|
+
request: request('mutable-decrease-active'),
|
|
103
|
+
units: 2,
|
|
104
|
+
budgets: [{ key: budgetKey, limit: 3 }],
|
|
105
|
+
ttlMs: 5_000,
|
|
106
|
+
});
|
|
107
|
+
assertAccepted(active, 'active reservation before decrease');
|
|
108
|
+
const deniedWhilePending = await store.reserve({
|
|
109
|
+
request: request('mutable-decrease-pending-denied'),
|
|
110
|
+
units: 1,
|
|
111
|
+
budgets: [{ key: budgetKey, limit: 1 }],
|
|
112
|
+
ttlMs: 5_000,
|
|
113
|
+
});
|
|
114
|
+
assertDenied(deniedWhilePending, 'quota_exceeded', 'lower limit must not rewrite pending reserved usage');
|
|
115
|
+
await store.markLiable({ reservationId: active.reservation.id });
|
|
116
|
+
const deniedWhileLiable = await store.reserve({
|
|
117
|
+
request: request('mutable-decrease-liable-denied'),
|
|
118
|
+
units: 1,
|
|
119
|
+
budgets: [{ key: budgetKey, limit: 1 }],
|
|
120
|
+
ttlMs: 5_000,
|
|
121
|
+
});
|
|
122
|
+
assertDenied(deniedWhileLiable, 'quota_exceeded', 'lower limit must not rewrite cost-liable reserved usage');
|
|
123
|
+
await store.settle({
|
|
124
|
+
reservationId: active.reservation.id,
|
|
125
|
+
actualUnits: 2,
|
|
126
|
+
outcome: 'completed-under-lower-limit',
|
|
127
|
+
});
|
|
128
|
+
const deniedAfterSettlement = await store.reserve({
|
|
129
|
+
request: request('mutable-decrease-settled-denied'),
|
|
130
|
+
units: 1,
|
|
131
|
+
budgets: [{ key: budgetKey, limit: 1 }],
|
|
132
|
+
ttlMs: 5_000,
|
|
133
|
+
});
|
|
134
|
+
assertDenied(deniedAfterSettlement, 'quota_exceeded', 'limit decrease must not refund already-incurred usage');
|
|
135
|
+
const admittedWithRoom = await store.reserve({
|
|
136
|
+
request: request('mutable-decrease-room-restored'),
|
|
137
|
+
units: 1,
|
|
138
|
+
budgets: [{ key: budgetKey, limit: 3 }],
|
|
139
|
+
ttlMs: 5_000,
|
|
140
|
+
});
|
|
141
|
+
assertAccepted(admittedWithRoom, 'raising the effective limit must reuse the same bucket state');
|
|
142
|
+
});
|
|
143
|
+
await runCase(harness, cases, 'mutable-limit-concurrent-policy-views', async (store) => {
|
|
144
|
+
const budgetKey = 'contract:mutable-concurrent';
|
|
145
|
+
const seed = await store.reserve({
|
|
146
|
+
request: request('mutable-concurrent-seed'),
|
|
147
|
+
units: 1,
|
|
148
|
+
budgets: [{ key: budgetKey, limit: 2 }],
|
|
149
|
+
ttlMs: 5_000,
|
|
150
|
+
});
|
|
151
|
+
assertAccepted(seed, 'seed usage for concurrent policy views');
|
|
152
|
+
const [strictResult, staleHigherResult] = await Promise.all([
|
|
153
|
+
store.reserve({
|
|
154
|
+
request: request('mutable-concurrent-strict'),
|
|
155
|
+
units: 1,
|
|
156
|
+
budgets: [{ key: budgetKey, limit: 1 }],
|
|
157
|
+
ttlMs: 5_000,
|
|
158
|
+
}),
|
|
159
|
+
store.reserve({
|
|
160
|
+
request: request('mutable-concurrent-stale-higher'),
|
|
161
|
+
units: 1,
|
|
162
|
+
budgets: [{ key: budgetKey, limit: 2 }],
|
|
163
|
+
ttlMs: 5_000,
|
|
164
|
+
}),
|
|
165
|
+
]);
|
|
166
|
+
assertDenied(strictResult, 'quota_exceeded', 'caller using the stricter limit must deny when usage is already at that limit');
|
|
167
|
+
assertAccepted(staleHigherResult, 'caller still using the higher effective limit remains able to admit within that limit');
|
|
168
|
+
});
|
|
169
|
+
await runCase(harness, cases, 'logical-operation-replay-scope', async (store) => {
|
|
170
|
+
const base = {
|
|
171
|
+
request: request('same-operation', 'user-1', 'tenant-a', 'read'),
|
|
172
|
+
units: 0,
|
|
173
|
+
budgets: [{ key: 'contract:replay', limit: 1 }],
|
|
174
|
+
ttlMs: 5_000,
|
|
175
|
+
};
|
|
176
|
+
assertAccepted(await store.reserve(base), 'initial logical operation');
|
|
177
|
+
assertDenied(await store.reserve(base), 'duplicate_operation', 'duplicate logical operation');
|
|
178
|
+
assertAccepted(await store.reserve({
|
|
179
|
+
...base,
|
|
180
|
+
request: request('same-operation', 'user-1', 'tenant-b', 'read'),
|
|
181
|
+
}), 'same operationId in another tenant');
|
|
182
|
+
assertAccepted(await store.reserve({
|
|
183
|
+
...base,
|
|
184
|
+
request: request('same-operation', 'user-1', 'tenant-a', 'write'),
|
|
185
|
+
}), 'same operationId for another tool');
|
|
186
|
+
});
|
|
187
|
+
await runCase(harness, cases, 'liability-is-idempotent', async (store) => {
|
|
188
|
+
const admission = await store.reserve({
|
|
189
|
+
request: request('liable-idempotent'),
|
|
190
|
+
units: 1,
|
|
191
|
+
budgets: [{ key: 'contract:liability', limit: 1 }],
|
|
192
|
+
ttlMs: 5_000,
|
|
193
|
+
});
|
|
194
|
+
assertAccepted(admission, 'liability reservation');
|
|
195
|
+
const first = await store.markLiable({ reservationId: admission.reservation.id });
|
|
196
|
+
const second = await store.markLiable({ reservationId: admission.reservation.id });
|
|
197
|
+
assert(first.reservationId === admission.reservation.id, 'first liability result changed reservationId');
|
|
198
|
+
assert(second.reservationId === admission.reservation.id, 'replayed liability result changed reservationId');
|
|
199
|
+
assert(second.expiresAt === first.expiresAt, 'idempotent markLiable replay changed lease expiry');
|
|
200
|
+
});
|
|
201
|
+
await runCase(harness, cases, 'renew-active-lease', async (store) => {
|
|
202
|
+
const admission = await store.reserve({
|
|
203
|
+
request: request('renew-active'),
|
|
204
|
+
units: 1,
|
|
205
|
+
budgets: [{ key: 'contract:renew', limit: 1 }],
|
|
206
|
+
ttlMs: 1_000,
|
|
207
|
+
});
|
|
208
|
+
assertAccepted(admission, 'renew reservation');
|
|
209
|
+
const renewed = await store.renew({ reservationId: admission.reservation.id, ttlMs: 5_000 });
|
|
210
|
+
assert(renewed.reservationId === admission.reservation.id, 'renew changed reservationId');
|
|
211
|
+
assert(renewed.expiresAt >= admission.reservation.expiresAt, 'renew with a longer TTL moved expiry backwards');
|
|
212
|
+
await store.settle({
|
|
213
|
+
reservationId: admission.reservation.id,
|
|
214
|
+
actualUnits: 1,
|
|
215
|
+
outcome: 'renewed_then_completed',
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
await runCase(harness, cases, 'settlement-idempotency-and-conflict', async (store) => {
|
|
219
|
+
const admission = await store.reserve({
|
|
220
|
+
request: request('settlement-replay'),
|
|
221
|
+
units: 2,
|
|
222
|
+
budgets: [{ key: 'contract:settlement', limit: 2 }],
|
|
223
|
+
ttlMs: 5_000,
|
|
224
|
+
});
|
|
225
|
+
assertAccepted(admission, 'settlement reservation');
|
|
226
|
+
const input = {
|
|
227
|
+
reservationId: admission.reservation.id,
|
|
228
|
+
actualUnits: 1,
|
|
229
|
+
outcome: 'completed',
|
|
230
|
+
};
|
|
231
|
+
const first = await store.settle(input);
|
|
232
|
+
const replay = await store.settle(input);
|
|
233
|
+
assertSameSettlement(first, replay);
|
|
234
|
+
await assertRejects(() => store.settle({
|
|
235
|
+
reservationId: admission.reservation.id,
|
|
236
|
+
actualUnits: 0,
|
|
237
|
+
outcome: 'different',
|
|
238
|
+
}), 'conflicting settlement must fail');
|
|
239
|
+
});
|
|
240
|
+
await runCase(harness, cases, 'invalid-settlement-does-not-corrupt-state', async (store) => {
|
|
241
|
+
const admission = await store.reserve({
|
|
242
|
+
request: request('invalid-units'),
|
|
243
|
+
units: 1,
|
|
244
|
+
budgets: [{ key: 'contract:invalid-units', limit: 1 }],
|
|
245
|
+
ttlMs: 5_000,
|
|
246
|
+
});
|
|
247
|
+
assertAccepted(admission, 'invalid-units reservation');
|
|
248
|
+
await assertRejects(() => store.settle({
|
|
249
|
+
reservationId: admission.reservation.id,
|
|
250
|
+
actualUnits: 2,
|
|
251
|
+
outcome: 'invalid',
|
|
252
|
+
}), 'actualUnits above reservedUnits must fail');
|
|
253
|
+
const valid = await store.settle({
|
|
254
|
+
reservationId: admission.reservation.id,
|
|
255
|
+
actualUnits: 1,
|
|
256
|
+
outcome: 'valid-after-rejection',
|
|
257
|
+
});
|
|
258
|
+
assert(valid.actualUnits === 1, 'valid settlement failed after invalid attempt');
|
|
259
|
+
});
|
|
260
|
+
await runCase(harness, cases, 'pending-expiry-releases-capacity', async (store) => {
|
|
261
|
+
const first = await store.reserve({
|
|
262
|
+
request: request('pending-expiry'),
|
|
263
|
+
units: 1,
|
|
264
|
+
budgets: [{ key: 'contract:pending-expiry', limit: 1 }],
|
|
265
|
+
ttlMs: leaseTtlMs,
|
|
266
|
+
});
|
|
267
|
+
assertAccepted(first, 'pending-expiry reservation');
|
|
268
|
+
await harness.waitForLeaseExpiry(leaseTtlMs, 'pending-expiry-releases-capacity');
|
|
269
|
+
const replacement = await store.reserve({
|
|
270
|
+
request: request('pending-expiry-replacement'),
|
|
271
|
+
units: 1,
|
|
272
|
+
budgets: [{ key: 'contract:pending-expiry', limit: 1 }],
|
|
273
|
+
ttlMs: 5_000,
|
|
274
|
+
});
|
|
275
|
+
assertAccepted(replacement, 'replacement after pending expiry');
|
|
276
|
+
});
|
|
277
|
+
await runCase(harness, cases, 'liable-expiry-retains-charge-and-replay-protection', async (store) => {
|
|
278
|
+
const first = await store.reserve({
|
|
279
|
+
request: request('liable-expiry'),
|
|
280
|
+
units: 1,
|
|
281
|
+
budgets: [{ key: 'contract:liable-expiry', limit: 1 }],
|
|
282
|
+
ttlMs: leaseTtlMs,
|
|
283
|
+
});
|
|
284
|
+
assertAccepted(first, 'liable-expiry reservation');
|
|
285
|
+
await store.markLiable({ reservationId: first.reservation.id });
|
|
286
|
+
await harness.waitForLeaseExpiry(leaseTtlMs, 'liable-expiry-retains-charge-and-replay-protection');
|
|
287
|
+
const another = await store.reserve({
|
|
288
|
+
request: request('after-liable-expiry'),
|
|
289
|
+
units: 1,
|
|
290
|
+
budgets: [{ key: 'contract:liable-expiry', limit: 1 }],
|
|
291
|
+
ttlMs: 5_000,
|
|
292
|
+
});
|
|
293
|
+
assertDenied(another, 'quota_exceeded', 'new operation after liable expiry');
|
|
294
|
+
const replay = await store.reserve({
|
|
295
|
+
request: request('liable-expiry'),
|
|
296
|
+
units: 1,
|
|
297
|
+
budgets: [{ key: 'contract:liable-expiry', limit: 1 }],
|
|
298
|
+
ttlMs: 5_000,
|
|
299
|
+
});
|
|
300
|
+
assertDenied(replay, 'duplicate_operation', 'original operation after liable expiry');
|
|
301
|
+
});
|
|
302
|
+
return {
|
|
303
|
+
passed: cases.every(result => result.passed),
|
|
304
|
+
cases,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/** Run the suite and throw a single detailed error if any case fails. */
|
|
308
|
+
export async function assertUsageStoreConformance(harness) {
|
|
309
|
+
const report = await runUsageStoreConformance(harness);
|
|
310
|
+
if (!report.passed)
|
|
311
|
+
throw new UsageStoreConformanceError(report);
|
|
312
|
+
return report;
|
|
313
|
+
}
|
|
314
|
+
async function runCase(harness, results, name, body) {
|
|
315
|
+
try {
|
|
316
|
+
const store = await harness.createStore(name);
|
|
317
|
+
await body(store);
|
|
318
|
+
results.push({ name, passed: true });
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
results.push({ name, passed: false, error: errorMessage(error) });
|
|
322
|
+
}
|
|
323
|
+
finally {
|
|
324
|
+
try {
|
|
325
|
+
await harness.cleanup?.(name);
|
|
326
|
+
}
|
|
327
|
+
catch (error) {
|
|
328
|
+
results.push({ name: `${name}:cleanup`, passed: false, error: errorMessage(error) });
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function request(operationId, principalId = 'user-1', tenantId = 'tenant-1', tool = 'contract-tool') {
|
|
333
|
+
return {
|
|
334
|
+
operationId,
|
|
335
|
+
principal: { id: principalId, tenantId },
|
|
336
|
+
tool,
|
|
337
|
+
args: { conformance: true },
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function assertAccepted(result, context) {
|
|
341
|
+
assert(result.accepted, `${context}: expected accepted reservation`);
|
|
342
|
+
}
|
|
343
|
+
function assertDenied(result, reason, context) {
|
|
344
|
+
assert(!result.accepted, `${context}: expected denial`);
|
|
345
|
+
assert(result.reason === reason, `${context}: expected ${reason}, got ${result.reason}`);
|
|
346
|
+
}
|
|
347
|
+
function assertSameSettlement(left, right) {
|
|
348
|
+
assert(left.reservationId === right.reservationId, 'idempotent settlement changed reservationId');
|
|
349
|
+
assert(left.reservedUnits === right.reservedUnits, 'idempotent settlement changed reservedUnits');
|
|
350
|
+
assert(left.actualUnits === right.actualUnits, 'idempotent settlement changed actualUnits');
|
|
351
|
+
assert(left.releasedUnits === right.releasedUnits, 'idempotent settlement changed releasedUnits');
|
|
352
|
+
assert(left.outcome === right.outcome, 'idempotent settlement changed outcome');
|
|
353
|
+
}
|
|
354
|
+
async function assertRejects(action, message) {
|
|
355
|
+
let rejected = false;
|
|
356
|
+
try {
|
|
357
|
+
await action();
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
rejected = true;
|
|
361
|
+
}
|
|
362
|
+
assert(rejected, message);
|
|
363
|
+
}
|
|
364
|
+
function assert(condition, message) {
|
|
365
|
+
if (!condition)
|
|
366
|
+
throw new Error(message);
|
|
367
|
+
}
|
|
368
|
+
function assertPositiveInteger(value, name) {
|
|
369
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
370
|
+
throw new RangeError(`${name} must be a positive safe integer`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
function errorMessage(error) {
|
|
374
|
+
if (error instanceof Error)
|
|
375
|
+
return `${error.name}: ${error.message}`;
|
|
376
|
+
return String(error);
|
|
377
|
+
}
|
|
378
|
+
//# sourceMappingURL=store-conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-conformance.js","sourceRoot":"","sources":["../src/store-conformance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ScopedQuotaSnapshot } from './operational.js';
|
|
2
|
+
export type UsageQuotaThreshold = {
|
|
3
|
+
kind: 'remaining_units';
|
|
4
|
+
value: number;
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'remaining_ratio';
|
|
7
|
+
value: number;
|
|
8
|
+
};
|
|
9
|
+
export interface UsageQuotaThresholdEvaluation {
|
|
10
|
+
reached: boolean;
|
|
11
|
+
exhausted: boolean;
|
|
12
|
+
remaining: number;
|
|
13
|
+
remainingRatio: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Evaluate one threshold against one explicitly scoped authoritative quota snapshot.
|
|
17
|
+
* This helper is pure and owns no accounting-window or delivery state.
|
|
18
|
+
*/
|
|
19
|
+
export declare function evaluateUsageQuotaThreshold(quota: ScopedQuotaSnapshot, threshold: UsageQuotaThreshold): UsageQuotaThresholdEvaluation;
|
|
20
|
+
/**
|
|
21
|
+
* Return true only when the same scoped accounting window moves from above a threshold
|
|
22
|
+
* to at-or-below it. Replaying the same result therefore does not create another crossing.
|
|
23
|
+
* Applications remain responsible for resetting previous state when their window changes.
|
|
24
|
+
*/
|
|
25
|
+
export declare function didUsageQuotaThresholdCross(previous: ScopedQuotaSnapshot, current: ScopedQuotaSnapshot, threshold: UsageQuotaThreshold): boolean;
|
|
26
|
+
//# sourceMappingURL=thresholds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thresholds.d.ts","sourceRoot":"","sources":["../src/thresholds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,mBAAmB,GAC7B,6BAA6B,CAc/B;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,mBAAmB,EAC5B,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAUT"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluate one threshold against one explicitly scoped authoritative quota snapshot.
|
|
3
|
+
* This helper is pure and owns no accounting-window or delivery state.
|
|
4
|
+
*/
|
|
5
|
+
export function evaluateUsageQuotaThreshold(quota, threshold) {
|
|
6
|
+
validateQuota(quota);
|
|
7
|
+
validateThreshold(threshold);
|
|
8
|
+
const remainingRatio = quota.limit === 0 ? 0 : quota.remaining / quota.limit;
|
|
9
|
+
const reached = threshold.kind === 'remaining_units'
|
|
10
|
+
? quota.remaining <= threshold.value
|
|
11
|
+
: remainingRatio <= threshold.value;
|
|
12
|
+
return {
|
|
13
|
+
reached,
|
|
14
|
+
exhausted: quota.remaining === 0,
|
|
15
|
+
remaining: quota.remaining,
|
|
16
|
+
remainingRatio,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Return true only when the same scoped accounting window moves from above a threshold
|
|
21
|
+
* to at-or-below it. Replaying the same result therefore does not create another crossing.
|
|
22
|
+
* Applications remain responsible for resetting previous state when their window changes.
|
|
23
|
+
*/
|
|
24
|
+
export function didUsageQuotaThresholdCross(previous, current, threshold) {
|
|
25
|
+
validateQuota(previous);
|
|
26
|
+
validateQuota(current);
|
|
27
|
+
if (previous.limit !== current.limit) {
|
|
28
|
+
throw new RangeError('Threshold crossing requires snapshots from the same configured limit');
|
|
29
|
+
}
|
|
30
|
+
return (!evaluateUsageQuotaThreshold(previous, threshold).reached &&
|
|
31
|
+
evaluateUsageQuotaThreshold(current, threshold).reached);
|
|
32
|
+
}
|
|
33
|
+
function validateQuota(quota) {
|
|
34
|
+
if (!Number.isSafeInteger(quota.limit) ||
|
|
35
|
+
quota.limit < 0 ||
|
|
36
|
+
!Number.isSafeInteger(quota.remaining) ||
|
|
37
|
+
quota.remaining < 0 ||
|
|
38
|
+
quota.remaining > quota.limit) {
|
|
39
|
+
throw new RangeError('Quota snapshot must contain a valid non-negative limit and remaining value');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function validateThreshold(threshold) {
|
|
43
|
+
if (threshold.kind === 'remaining_units') {
|
|
44
|
+
if (!Number.isSafeInteger(threshold.value) || threshold.value < 0) {
|
|
45
|
+
throw new RangeError('remaining_units threshold must be a non-negative safe integer');
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (threshold.kind !== 'remaining_ratio' ||
|
|
50
|
+
!Number.isFinite(threshold.value) ||
|
|
51
|
+
threshold.value < 0 ||
|
|
52
|
+
threshold.value > 1) {
|
|
53
|
+
throw new RangeError('remaining_ratio threshold must be between 0 and 1');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=thresholds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thresholds.js","sourceRoot":"","sources":["../src/thresholds.ts"],"names":[],"mappings":"AAaA;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,KAA0B,EAC1B,SAA8B;IAE9B,aAAa,CAAC,KAAK,CAAC,CAAC;IACrB,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;IAC7E,MAAM,OAAO,GACX,SAAS,CAAC,IAAI,KAAK,iBAAiB;QAClC,CAAC,CAAC,KAAK,CAAC,SAAS,IAAI,SAAS,CAAC,KAAK;QACpC,CAAC,CAAC,cAAc,IAAI,SAAS,CAAC,KAAK,CAAC;IACxC,OAAO;QACL,OAAO;QACP,SAAS,EAAE,KAAK,CAAC,SAAS,KAAK,CAAC;QAChC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,cAAc;KACf,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CACzC,QAA6B,EAC7B,OAA4B,EAC5B,SAA8B;IAE9B,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,IAAI,QAAQ,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QACrC,MAAM,IAAI,UAAU,CAAC,sEAAsE,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,CACL,CAAC,2BAA2B,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,OAAO;QACzD,2BAA2B,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,OAAO,CACxD,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAA0B;IAC/C,IACE,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC;QAClC,KAAK,CAAC,KAAK,GAAG,CAAC;QACf,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC;QACtC,KAAK,CAAC,SAAS,GAAG,CAAC;QACnB,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,KAAK,EAC7B,CAAC;QACD,MAAM,IAAI,UAAU,CAAC,4EAA4E,CAAC,CAAC;IACrG,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,SAA8B;IACvD,IAAI,SAAS,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;QACzC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,UAAU,CAAC,+DAA+D,CAAC,CAAC;QACxF,CAAC;QACD,OAAO;IACT,CAAC;IACD,IACE,SAAS,CAAC,IAAI,KAAK,iBAAiB;QACpC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC;QACjC,SAAS,CAAC,KAAK,GAAG,CAAC;QACnB,SAAS,CAAC,KAAK,GAAG,CAAC,EACnB,CAAC;QACD,MAAM,IAAI,UAAU,CAAC,mDAAmD,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { UsageStoreConformanceHarness, UsageStoreConformanceReport } from './store-conformance.js';
|
|
2
|
+
/** Portable proof suite for the optional atomic heterogeneous usage capability. */
|
|
3
|
+
export declare function runVectorUsageStoreConformance(harness: UsageStoreConformanceHarness): Promise<UsageStoreConformanceReport>;
|
|
4
|
+
//# sourceMappingURL=vector-store-conformance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-store-conformance.d.ts","sourceRoot":"","sources":["../src/vector-store-conformance.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,4BAA4B,EAC5B,2BAA2B,EAC5B,MAAM,wBAAwB,CAAC;AAEhC,mFAAmF;AACnF,wBAAsB,8BAA8B,CAClD,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,2BAA2B,CAAC,CAsOtC"}
|