@emilia-protocol/gate 0.17.0 → 0.18.1
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/CHANGELOG.md +43 -0
- package/README.md +51 -0
- package/admission-store-postgres.js +4 -0
- package/admission-store.js +4 -0
- package/dist/admission-store-postgres.d.ts +66 -0
- package/dist/admission-store-postgres.d.ts.map +1 -0
- package/dist/admission-store-postgres.js +537 -0
- package/dist/admission-store-postgres.js.map +1 -0
- package/dist/admission-store.d.ts +292 -0
- package/dist/admission-store.d.ts.map +1 -0
- package/dist/admission-store.js +777 -0
- package/dist/admission-store.js.map +1 -0
- package/dist/gate-qualification-v2.d.ts +225 -0
- package/dist/gate-qualification-v2.d.ts.map +1 -0
- package/dist/gate-qualification-v2.js +1011 -0
- package/dist/gate-qualification-v2.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/gate-qualification-v2.js +4 -0
- package/package.json +19 -3
- package/src/admission-store-postgres.ts +695 -0
- package/src/admission-store.ts +1065 -0
- package/src/gate-qualification-v2.ts +1534 -0
- package/src/index.ts +3 -0
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Deployment-bound PostgreSQL Admission Store.
|
|
5
|
+
*
|
|
6
|
+
* Every mutation is one PostgreSQL function call. The SQL functions use
|
|
7
|
+
* explicit row locks and permanent unique fences; this adapter retries only
|
|
8
|
+
* SQLSTATE 40001 (serialization failure) and 40P01 (deadlock), with the same
|
|
9
|
+
* caller-generated capabilities. It never retries an ambiguous provider
|
|
10
|
+
* effect. A lost beginInvocation acknowledgement is recovered only when an
|
|
11
|
+
* authoritative read proves that this exact invocation-token digest committed.
|
|
12
|
+
*/
|
|
13
|
+
import crypto from 'node:crypto';
|
|
14
|
+
import { ADMISSION_JOURNAL_VERSION, ADMISSION_RECORD_VERSION, createAdmissionSnapshot, verifyAdmissionJournal, } from './admission-store.js';
|
|
15
|
+
export const ADMISSION_POSTGRES_SQL = Object.freeze({
|
|
16
|
+
reserve: 'SELECT public.ep_gate_admission_reserve($1::text, $2::text, $3::jsonb, $4::text) AS result',
|
|
17
|
+
release: 'SELECT public.ep_gate_admission_release($1::text, $2::text, $3::text, $4::bigint, $5::text, $6::text) AS result',
|
|
18
|
+
expire: 'SELECT public.ep_gate_admission_expire($1::text, $2::text, $3::text, $4::bigint, $5::text) AS result',
|
|
19
|
+
supersede: 'SELECT public.ep_gate_admission_supersede($1::text, $2::text, $3::text, $4::bigint, $5::text, $6::jsonb, $7::text) AS result',
|
|
20
|
+
beginInvocation: 'SELECT public.ep_gate_admission_begin_invocation($1::text, $2::text, $3::text, $4::bigint, $5::text, $6::text) AS result',
|
|
21
|
+
recoverIndeterminate: 'SELECT public.ep_gate_admission_recover_indeterminate($1::text, $2::text, $3::text, $4::text, $5::text) AS result',
|
|
22
|
+
recordProviderOutcome: 'SELECT public.ep_gate_admission_record_provider_outcome($1::text, $2::text, $3::text, $4::bigint, $5::text, $6::text, $7::text, $8::text, $9::text) AS result',
|
|
23
|
+
recordEffectRelation: 'SELECT public.ep_gate_admission_record_effect_relation($1::text, $2::text, $3::text, $4::bigint, $5::text, $6::text, $7::text, $8::text, $9::text) AS result',
|
|
24
|
+
read: 'SELECT public.ep_gate_admission_read($1::text, $2::text, $3::text) AS result',
|
|
25
|
+
readByOperation: 'SELECT public.ep_gate_admission_read_by_operation($1::text, $2::text, $3::text) AS result',
|
|
26
|
+
readSnapshot: 'SELECT public.ep_gate_admission_read_snapshot($1::text, $2::text, $3::text) AS result',
|
|
27
|
+
journal: 'SELECT public.ep_gate_admission_journal($1::text, $2::text, $3::text) AS result',
|
|
28
|
+
checkInvariants: 'SELECT public.ep_gate_admission_check_invariants($1::text, $2::text) AS result',
|
|
29
|
+
});
|
|
30
|
+
const IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9:_.@/-]{0,511}$/;
|
|
31
|
+
const OWNER_TOKEN = /^admission-owner:v2:[A-Za-z0-9_-]{32,128}$/;
|
|
32
|
+
const SHA256 = /^sha256:[0-9a-f]{64}$/;
|
|
33
|
+
const RFC3339 = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
34
|
+
const RETRYABLE_SQLSTATES = new Set(['40001', '40P01']);
|
|
35
|
+
export class AdmissionPostgresProtocolError extends Error {
|
|
36
|
+
constructor(message, options) {
|
|
37
|
+
super(message, options);
|
|
38
|
+
this.name = 'AdmissionPostgresProtocolError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export class AdmissionPostgresAmbiguousBeginError extends Error {
|
|
42
|
+
admissionId;
|
|
43
|
+
constructor(admissionId, message, options) {
|
|
44
|
+
super(message, options);
|
|
45
|
+
this.name = 'AdmissionPostgresAmbiguousBeginError';
|
|
46
|
+
this.admissionId = admissionId;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function plain(value) {
|
|
50
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
51
|
+
return false;
|
|
52
|
+
const prototype = Object.getPrototypeOf(value);
|
|
53
|
+
return prototype === Object.prototype || prototype === null;
|
|
54
|
+
}
|
|
55
|
+
function canonical(value) {
|
|
56
|
+
if (value === null || typeof value === 'boolean' || typeof value === 'string') {
|
|
57
|
+
return JSON.stringify(value);
|
|
58
|
+
}
|
|
59
|
+
if (typeof value === 'number') {
|
|
60
|
+
if (!Number.isFinite(value))
|
|
61
|
+
throw new AdmissionPostgresProtocolError('non-finite JSON number');
|
|
62
|
+
return JSON.stringify(value);
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(value))
|
|
65
|
+
return `[${value.map(canonical).join(',')}]`;
|
|
66
|
+
if (!plain(value))
|
|
67
|
+
throw new AdmissionPostgresProtocolError('non-plain JSON object');
|
|
68
|
+
return `{${Object.keys(value).sort().map((key) => (`${JSON.stringify(key)}:${canonical(value[key])}`)).join(',')}}`;
|
|
69
|
+
}
|
|
70
|
+
function hash(domain, value) {
|
|
71
|
+
return `sha256:${crypto.createHash('sha256')
|
|
72
|
+
.update(domain)
|
|
73
|
+
.update('\0')
|
|
74
|
+
.update(canonical(value))
|
|
75
|
+
.digest('hex')}`;
|
|
76
|
+
}
|
|
77
|
+
function tokenDigest(token) {
|
|
78
|
+
return hash(`${ADMISSION_RECORD_VERSION}:TOKEN`, token);
|
|
79
|
+
}
|
|
80
|
+
function deepFreeze(value) {
|
|
81
|
+
if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
|
|
82
|
+
for (const child of Object.values(value))
|
|
83
|
+
deepFreeze(child);
|
|
84
|
+
Object.freeze(value);
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
function detached(value) {
|
|
89
|
+
return deepFreeze(structuredClone(value));
|
|
90
|
+
}
|
|
91
|
+
function identifier(value, field) {
|
|
92
|
+
if (typeof value !== 'string' || !IDENTIFIER.test(value)) {
|
|
93
|
+
throw new TypeError(`${field} is invalid`);
|
|
94
|
+
}
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
function digest(value, field) {
|
|
98
|
+
if (typeof value !== 'string' || !SHA256.test(value)) {
|
|
99
|
+
throw new TypeError(`${field} is invalid`);
|
|
100
|
+
}
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
function revision(value) {
|
|
104
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
105
|
+
throw new TypeError('expected_revision is invalid');
|
|
106
|
+
}
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
function ownerToken(value) {
|
|
110
|
+
if (typeof value !== 'string' || !OWNER_TOKEN.test(value)) {
|
|
111
|
+
throw new TypeError('owner_token is invalid');
|
|
112
|
+
}
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
function invocationToken(value) {
|
|
116
|
+
if (typeof value !== 'string' || value.length < 48) {
|
|
117
|
+
throw new TypeError('invocation_token is invalid');
|
|
118
|
+
}
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
function instant(value, field) {
|
|
122
|
+
if (typeof value !== 'string' || !RFC3339.test(value))
|
|
123
|
+
throw new TypeError(`${field} is invalid`);
|
|
124
|
+
const milliseconds = Date.parse(value);
|
|
125
|
+
if (!Number.isFinite(milliseconds))
|
|
126
|
+
throw new TypeError(`${field} is invalid`);
|
|
127
|
+
return new Date(milliseconds).toISOString();
|
|
128
|
+
}
|
|
129
|
+
function defaultOwnerToken() {
|
|
130
|
+
return `admission-owner:v2:${crypto.randomBytes(32).toString('base64url')}`;
|
|
131
|
+
}
|
|
132
|
+
function defaultInvocationToken() {
|
|
133
|
+
return `admission-invocation:v2:${crypto.randomBytes(32).toString('base64url')}`;
|
|
134
|
+
}
|
|
135
|
+
function parseJson(value, operation) {
|
|
136
|
+
if (typeof value !== 'string')
|
|
137
|
+
return value;
|
|
138
|
+
try {
|
|
139
|
+
return JSON.parse(value);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
throw new AdmissionPostgresProtocolError(`${operation}: malformed JSON result`, { cause: error });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function validateSnapshot(value, operation) {
|
|
146
|
+
if (!plain(value) || !plain(value.body)) {
|
|
147
|
+
throw new AdmissionPostgresProtocolError(`${operation}: malformed snapshot`);
|
|
148
|
+
}
|
|
149
|
+
const recreated = createAdmissionSnapshot(value.body);
|
|
150
|
+
if (value.snapshot_digest !== recreated.snapshot_digest) {
|
|
151
|
+
throw new AdmissionPostgresProtocolError(`${operation}: snapshot digest mismatch`);
|
|
152
|
+
}
|
|
153
|
+
return recreated;
|
|
154
|
+
}
|
|
155
|
+
function validateRecord(value, operation, tenantId) {
|
|
156
|
+
if (!plain(value)
|
|
157
|
+
|| value['@version'] !== ADMISSION_RECORD_VERSION
|
|
158
|
+
|| value.tenant_id !== tenantId
|
|
159
|
+
|| !IDENTIFIER.test(String(value.admission_id ?? ''))
|
|
160
|
+
|| !IDENTIFIER.test(String(value.operation_id ?? ''))
|
|
161
|
+
|| !Number.isSafeInteger(value.revision)
|
|
162
|
+
|| value.revision < 0
|
|
163
|
+
|| !Array.isArray(value.resources)
|
|
164
|
+
|| !SHA256.test(String(value.record_digest ?? ''))) {
|
|
165
|
+
throw new AdmissionPostgresProtocolError(`${operation}: malformed admission record`);
|
|
166
|
+
}
|
|
167
|
+
const { record_digest: recordDigest, ...body } = value;
|
|
168
|
+
if (hash(`${ADMISSION_RECORD_VERSION}:DIGEST`, body) !== recordDigest) {
|
|
169
|
+
throw new AdmissionPostgresProtocolError(`${operation}: admission record digest mismatch`);
|
|
170
|
+
}
|
|
171
|
+
return detached(value);
|
|
172
|
+
}
|
|
173
|
+
function validateJournal(value, operation, tenantId, admissionId) {
|
|
174
|
+
if (!Array.isArray(value)) {
|
|
175
|
+
throw new AdmissionPostgresProtocolError(`${operation}: malformed journal`);
|
|
176
|
+
}
|
|
177
|
+
for (const entry of value) {
|
|
178
|
+
if (!plain(entry)
|
|
179
|
+
|| entry['@version'] !== ADMISSION_JOURNAL_VERSION
|
|
180
|
+
|| entry.tenant_id !== tenantId
|
|
181
|
+
|| entry.admission_id !== admissionId) {
|
|
182
|
+
throw new AdmissionPostgresProtocolError(`${operation}: malformed journal entry`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const checked = verifyAdmissionJournal(value);
|
|
186
|
+
if (!checked.ok) {
|
|
187
|
+
throw new AdmissionPostgresProtocolError(`${operation}: invalid journal at ${checked.at}: ${checked.reason}`);
|
|
188
|
+
}
|
|
189
|
+
return detached(value);
|
|
190
|
+
}
|
|
191
|
+
function sqlState(error) {
|
|
192
|
+
return plain(error) && typeof error.code === 'string' ? error.code : null;
|
|
193
|
+
}
|
|
194
|
+
function normalizeResultObject(value, operation) {
|
|
195
|
+
const parsed = parseJson(value, operation);
|
|
196
|
+
if (!plain(parsed) || typeof parsed.ok !== 'boolean') {
|
|
197
|
+
throw new AdmissionPostgresProtocolError(`${operation}: malformed PostgreSQL result`);
|
|
198
|
+
}
|
|
199
|
+
return parsed;
|
|
200
|
+
}
|
|
201
|
+
function validateReference(input) {
|
|
202
|
+
return {
|
|
203
|
+
tenant_id: identifier(input.tenant_id, 'tenant_id'),
|
|
204
|
+
admission_id: identifier(input.admission_id, 'admission_id'),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function validateOperationReference(input) {
|
|
208
|
+
return {
|
|
209
|
+
tenant_id: identifier(input.tenant_id, 'tenant_id'),
|
|
210
|
+
operation_id: identifier(input.operation_id, 'operation_id'),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function validateCas(input) {
|
|
214
|
+
return {
|
|
215
|
+
...validateReference(input),
|
|
216
|
+
expected_revision: revision(input.expected_revision),
|
|
217
|
+
owner_token: ownerToken(input.owner_token),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Creates a durable single-tenant store bound to one installed deployment row.
|
|
222
|
+
* The SQL deliberately has no session-user-to-tenant mapping: database access
|
|
223
|
+
* is the deployment boundary and every RPC rechecks the singleton binding.
|
|
224
|
+
*/
|
|
225
|
+
export function createAdmissionPostgresStore(options) {
|
|
226
|
+
if (!plain(options) || typeof options.query !== 'function') {
|
|
227
|
+
throw new TypeError('createAdmissionPostgresStore requires an async pg-style query function');
|
|
228
|
+
}
|
|
229
|
+
const query = options.query;
|
|
230
|
+
const deploymentId = identifier(options.deploymentId, 'deploymentId');
|
|
231
|
+
const tenantId = identifier(options.tenantId, 'tenantId');
|
|
232
|
+
const ownerFactory = options.ownerTokenFactory ?? defaultOwnerToken;
|
|
233
|
+
const invocationFactory = options.invocationTokenFactory ?? defaultInvocationToken;
|
|
234
|
+
const maxTransactionRetries = options.maxTransactionRetries ?? 3;
|
|
235
|
+
if (!Number.isSafeInteger(maxTransactionRetries)
|
|
236
|
+
|| maxTransactionRetries < 0
|
|
237
|
+
|| maxTransactionRetries > 16) {
|
|
238
|
+
throw new TypeError('maxTransactionRetries must be an integer from 0 through 16');
|
|
239
|
+
}
|
|
240
|
+
function assertTenant(value) {
|
|
241
|
+
if (value !== tenantId)
|
|
242
|
+
throw new TypeError('tenant_id does not match the deployment binding');
|
|
243
|
+
}
|
|
244
|
+
async function rpc(operation, text, params) {
|
|
245
|
+
for (let attempt = 0;; attempt += 1) {
|
|
246
|
+
try {
|
|
247
|
+
const result = await query(text, params);
|
|
248
|
+
if (!result
|
|
249
|
+
|| result.rowCount !== 1
|
|
250
|
+
|| !Array.isArray(result.rows)
|
|
251
|
+
|| result.rows.length !== 1
|
|
252
|
+
|| !Object.hasOwn(result.rows[0], 'result')) {
|
|
253
|
+
throw new AdmissionPostgresProtocolError(`${operation}: malformed PostgreSQL result`);
|
|
254
|
+
}
|
|
255
|
+
return parseJson(result.rows[0].result, operation);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
if (attempt < maxTransactionRetries && RETRYABLE_SQLSTATES.has(sqlState(error) ?? '')) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function transitionResult(value, operation) {
|
|
266
|
+
const result = normalizeResultObject(value, operation);
|
|
267
|
+
if (!result.ok)
|
|
268
|
+
return detached(result);
|
|
269
|
+
return {
|
|
270
|
+
ok: true,
|
|
271
|
+
record: validateRecord(result.record, operation, tenantId),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
async function read(input) {
|
|
275
|
+
const reference = validateReference(input);
|
|
276
|
+
assertTenant(reference.tenant_id);
|
|
277
|
+
const value = await rpc('admission read', ADMISSION_POSTGRES_SQL.read, [
|
|
278
|
+
deploymentId,
|
|
279
|
+
tenantId,
|
|
280
|
+
reference.admission_id,
|
|
281
|
+
]);
|
|
282
|
+
return value === null ? null : validateRecord(value, 'admission read', tenantId);
|
|
283
|
+
}
|
|
284
|
+
async function readSnapshot(snapshotDigest) {
|
|
285
|
+
const normalized = digest(snapshotDigest, 'snapshot_digest');
|
|
286
|
+
const value = await rpc('admission snapshot read', ADMISSION_POSTGRES_SQL.readSnapshot, [
|
|
287
|
+
deploymentId,
|
|
288
|
+
tenantId,
|
|
289
|
+
normalized,
|
|
290
|
+
]);
|
|
291
|
+
return value === null ? null : validateSnapshot(value, 'admission snapshot read');
|
|
292
|
+
}
|
|
293
|
+
const store = {
|
|
294
|
+
durable: true,
|
|
295
|
+
atomic: true,
|
|
296
|
+
compareAndSwap: true,
|
|
297
|
+
appendOnlyJournal: true,
|
|
298
|
+
exclusiveActuation: true,
|
|
299
|
+
transactionalCurrentness: true,
|
|
300
|
+
guaranteeClass: 'local_atomic',
|
|
301
|
+
singleTenant: true,
|
|
302
|
+
deploymentBound: true,
|
|
303
|
+
managedTenantPrincipalMapping: false,
|
|
304
|
+
maxTransactionRetries,
|
|
305
|
+
async reserve(raw) {
|
|
306
|
+
const snapshot = plain(raw) && Object.hasOwn(raw, 'snapshot_digest')
|
|
307
|
+
? validateSnapshot(raw, 'admission reserve input')
|
|
308
|
+
: createAdmissionSnapshot(raw);
|
|
309
|
+
assertTenant(snapshot.body.tenant_id);
|
|
310
|
+
const generatedOwner = ownerToken(ownerFactory());
|
|
311
|
+
const value = await rpc('admission reserve', ADMISSION_POSTGRES_SQL.reserve, [
|
|
312
|
+
deploymentId,
|
|
313
|
+
tenantId,
|
|
314
|
+
JSON.stringify(snapshot),
|
|
315
|
+
tokenDigest(generatedOwner),
|
|
316
|
+
]);
|
|
317
|
+
const result = normalizeResultObject(value, 'admission reserve');
|
|
318
|
+
if (!result.ok)
|
|
319
|
+
return detached(result);
|
|
320
|
+
return {
|
|
321
|
+
ok: true,
|
|
322
|
+
snapshot: validateSnapshot(result.snapshot, 'admission reserve'),
|
|
323
|
+
record: validateRecord(result.record, 'admission reserve', tenantId),
|
|
324
|
+
owner_token: generatedOwner,
|
|
325
|
+
};
|
|
326
|
+
},
|
|
327
|
+
async release(input, reason = 'released_before_invocation') {
|
|
328
|
+
const cas = validateCas(input);
|
|
329
|
+
assertTenant(cas.tenant_id);
|
|
330
|
+
return transitionResult(await rpc('admission release', ADMISSION_POSTGRES_SQL.release, [
|
|
331
|
+
deploymentId,
|
|
332
|
+
tenantId,
|
|
333
|
+
cas.admission_id,
|
|
334
|
+
cas.expected_revision,
|
|
335
|
+
tokenDigest(cas.owner_token),
|
|
336
|
+
reason,
|
|
337
|
+
]), 'admission release');
|
|
338
|
+
},
|
|
339
|
+
async expire(input) {
|
|
340
|
+
const cas = validateCas(input);
|
|
341
|
+
assertTenant(cas.tenant_id);
|
|
342
|
+
return transitionResult(await rpc('admission expire', ADMISSION_POSTGRES_SQL.expire, [
|
|
343
|
+
deploymentId,
|
|
344
|
+
tenantId,
|
|
345
|
+
cas.admission_id,
|
|
346
|
+
cas.expected_revision,
|
|
347
|
+
tokenDigest(cas.owner_token),
|
|
348
|
+
]), 'admission expire');
|
|
349
|
+
},
|
|
350
|
+
async supersede(input) {
|
|
351
|
+
const cas = validateCas(input);
|
|
352
|
+
assertTenant(cas.tenant_id);
|
|
353
|
+
const successor = createAdmissionSnapshot({
|
|
354
|
+
...input.successor,
|
|
355
|
+
supersedes_admission_id: cas.admission_id,
|
|
356
|
+
remedy_for: null,
|
|
357
|
+
});
|
|
358
|
+
assertTenant(successor.body.tenant_id);
|
|
359
|
+
const successorOwner = ownerToken(ownerFactory());
|
|
360
|
+
const value = await rpc('admission supersede', ADMISSION_POSTGRES_SQL.supersede, [
|
|
361
|
+
deploymentId,
|
|
362
|
+
tenantId,
|
|
363
|
+
cas.admission_id,
|
|
364
|
+
cas.expected_revision,
|
|
365
|
+
tokenDigest(cas.owner_token),
|
|
366
|
+
JSON.stringify(successor),
|
|
367
|
+
tokenDigest(successorOwner),
|
|
368
|
+
]);
|
|
369
|
+
const result = normalizeResultObject(value, 'admission supersede');
|
|
370
|
+
if (!result.ok)
|
|
371
|
+
return detached(result);
|
|
372
|
+
return {
|
|
373
|
+
ok: true,
|
|
374
|
+
predecessor_record: validateRecord(result.predecessor_record, 'admission supersede predecessor', tenantId),
|
|
375
|
+
successor_snapshot: validateSnapshot(result.successor_snapshot, 'admission supersede successor'),
|
|
376
|
+
successor_record: validateRecord(result.successor_record, 'admission supersede successor', tenantId),
|
|
377
|
+
successor_owner_token: successorOwner,
|
|
378
|
+
};
|
|
379
|
+
},
|
|
380
|
+
async beginInvocation(input) {
|
|
381
|
+
const cas = validateCas(input);
|
|
382
|
+
assertTenant(cas.tenant_id);
|
|
383
|
+
const generatedInvocation = invocationToken(invocationFactory());
|
|
384
|
+
const generatedDigest = tokenDigest(generatedInvocation);
|
|
385
|
+
try {
|
|
386
|
+
const value = await rpc('admission begin invocation', ADMISSION_POSTGRES_SQL.beginInvocation, [
|
|
387
|
+
deploymentId,
|
|
388
|
+
tenantId,
|
|
389
|
+
cas.admission_id,
|
|
390
|
+
cas.expected_revision,
|
|
391
|
+
tokenDigest(cas.owner_token),
|
|
392
|
+
generatedDigest,
|
|
393
|
+
]);
|
|
394
|
+
const result = normalizeResultObject(value, 'admission begin invocation');
|
|
395
|
+
if (!result.ok)
|
|
396
|
+
return detached(result);
|
|
397
|
+
return {
|
|
398
|
+
ok: true,
|
|
399
|
+
snapshot: validateSnapshot(result.snapshot, 'admission begin invocation'),
|
|
400
|
+
record: validateRecord(result.record, 'admission begin invocation', tenantId),
|
|
401
|
+
invocation_token: generatedInvocation,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
catch (error) {
|
|
405
|
+
// The write acknowledgement can be lost after commit. Only the exact
|
|
406
|
+
// token digest generated above can turn readback into a successful begin.
|
|
407
|
+
let current;
|
|
408
|
+
try {
|
|
409
|
+
current = await read(cas);
|
|
410
|
+
}
|
|
411
|
+
catch (readError) {
|
|
412
|
+
throw new AdmissionPostgresAmbiguousBeginError(cas.admission_id, 'beginInvocation acknowledgement and authoritative readback are both unavailable', { cause: readError });
|
|
413
|
+
}
|
|
414
|
+
if (current
|
|
415
|
+
&& current.revision === cas.expected_revision + 1
|
|
416
|
+
&& current.state === 'INVOKING'
|
|
417
|
+
&& current.execution_right === 'CONSUMED'
|
|
418
|
+
&& current.provider_attempt === 'INVOKING'
|
|
419
|
+
&& current.owner_digest === tokenDigest(cas.owner_token)
|
|
420
|
+
&& current.invocation_token_digest === generatedDigest) {
|
|
421
|
+
const snapshot = await readSnapshot(current.snapshot_digest);
|
|
422
|
+
if (!snapshot) {
|
|
423
|
+
throw new AdmissionPostgresAmbiguousBeginError(cas.admission_id, 'beginInvocation committed but its authoritative snapshot is unavailable', { cause: error });
|
|
424
|
+
}
|
|
425
|
+
return {
|
|
426
|
+
ok: true,
|
|
427
|
+
snapshot,
|
|
428
|
+
record: current,
|
|
429
|
+
invocation_token: generatedInvocation,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
if (current
|
|
433
|
+
&& current.revision === cas.expected_revision
|
|
434
|
+
&& current.state === 'RESERVED'
|
|
435
|
+
&& current.execution_right === 'RESERVED') {
|
|
436
|
+
throw error;
|
|
437
|
+
}
|
|
438
|
+
throw new AdmissionPostgresAmbiguousBeginError(cas.admission_id, 'beginInvocation outcome is not provably attributable to this invocation token', { cause: error });
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
async recoverIndeterminate(input) {
|
|
442
|
+
const reference = validateReference(input);
|
|
443
|
+
assertTenant(reference.tenant_id);
|
|
444
|
+
const recoveryOwner = ownerToken(input.owner_token);
|
|
445
|
+
const reconciliationToken = invocationToken(invocationFactory());
|
|
446
|
+
const value = await rpc('admission recover indeterminate', ADMISSION_POSTGRES_SQL.recoverIndeterminate, [
|
|
447
|
+
deploymentId,
|
|
448
|
+
tenantId,
|
|
449
|
+
reference.admission_id,
|
|
450
|
+
tokenDigest(recoveryOwner),
|
|
451
|
+
tokenDigest(reconciliationToken),
|
|
452
|
+
]);
|
|
453
|
+
const result = normalizeResultObject(value, 'admission recover indeterminate');
|
|
454
|
+
if (!result.ok)
|
|
455
|
+
return detached(result);
|
|
456
|
+
const record = validateRecord(result.record, 'admission recover indeterminate', tenantId);
|
|
457
|
+
if (record.invocation_token_digest !== tokenDigest(reconciliationToken)) {
|
|
458
|
+
throw new AdmissionPostgresProtocolError('admission recover indeterminate: reconciliation token digest mismatch');
|
|
459
|
+
}
|
|
460
|
+
return { ok: true, record, reconciliation_token: reconciliationToken };
|
|
461
|
+
},
|
|
462
|
+
async recordProviderOutcome(input) {
|
|
463
|
+
const cas = validateCas(input);
|
|
464
|
+
assertTenant(cas.tenant_id);
|
|
465
|
+
const token = invocationToken(input.invocation_token);
|
|
466
|
+
const evidence = input.evidence_digest === null
|
|
467
|
+
? null
|
|
468
|
+
: digest(input.evidence_digest, 'evidence_digest');
|
|
469
|
+
const observed = instant(input.observed_at, 'observed_at');
|
|
470
|
+
return transitionResult(await rpc('admission provider outcome', ADMISSION_POSTGRES_SQL.recordProviderOutcome, [
|
|
471
|
+
deploymentId,
|
|
472
|
+
tenantId,
|
|
473
|
+
cas.admission_id,
|
|
474
|
+
cas.expected_revision,
|
|
475
|
+
tokenDigest(cas.owner_token),
|
|
476
|
+
tokenDigest(token),
|
|
477
|
+
input.value,
|
|
478
|
+
evidence,
|
|
479
|
+
observed,
|
|
480
|
+
]), 'admission provider outcome');
|
|
481
|
+
},
|
|
482
|
+
async recordEffectRelation(input) {
|
|
483
|
+
const cas = validateCas(input);
|
|
484
|
+
assertTenant(cas.tenant_id);
|
|
485
|
+
const token = invocationToken(input.invocation_token);
|
|
486
|
+
const evidence = input.evidence_digest === null
|
|
487
|
+
? null
|
|
488
|
+
: digest(input.evidence_digest, 'evidence_digest');
|
|
489
|
+
const observed = instant(input.observed_at, 'observed_at');
|
|
490
|
+
return transitionResult(await rpc('admission effect relation', ADMISSION_POSTGRES_SQL.recordEffectRelation, [
|
|
491
|
+
deploymentId,
|
|
492
|
+
tenantId,
|
|
493
|
+
cas.admission_id,
|
|
494
|
+
cas.expected_revision,
|
|
495
|
+
tokenDigest(cas.owner_token),
|
|
496
|
+
tokenDigest(token),
|
|
497
|
+
input.value,
|
|
498
|
+
evidence,
|
|
499
|
+
observed,
|
|
500
|
+
]), 'admission effect relation');
|
|
501
|
+
},
|
|
502
|
+
read,
|
|
503
|
+
async readByOperation(input) {
|
|
504
|
+
const reference = validateOperationReference(input);
|
|
505
|
+
assertTenant(reference.tenant_id);
|
|
506
|
+
const value = await rpc('admission operation read', ADMISSION_POSTGRES_SQL.readByOperation, [deploymentId, tenantId, reference.operation_id]);
|
|
507
|
+
return value === null
|
|
508
|
+
? null
|
|
509
|
+
: validateRecord(value, 'admission operation read', tenantId);
|
|
510
|
+
},
|
|
511
|
+
readSnapshot,
|
|
512
|
+
async journal(input) {
|
|
513
|
+
const reference = validateReference(input);
|
|
514
|
+
assertTenant(reference.tenant_id);
|
|
515
|
+
const value = await rpc('admission journal', ADMISSION_POSTGRES_SQL.journal, [
|
|
516
|
+
deploymentId,
|
|
517
|
+
tenantId,
|
|
518
|
+
reference.admission_id,
|
|
519
|
+
]);
|
|
520
|
+
return validateJournal(value, 'admission journal', tenantId, reference.admission_id);
|
|
521
|
+
},
|
|
522
|
+
async checkInvariants() {
|
|
523
|
+
const value = normalizeResultObject(await rpc('admission invariant check', ADMISSION_POSTGRES_SQL.checkInvariants, [deploymentId, tenantId]), 'admission invariant check');
|
|
524
|
+
if (!Array.isArray(value.violations)
|
|
525
|
+
|| value.violations.some((violation) => typeof violation !== 'string')
|
|
526
|
+
|| value.ok !== (value.violations.length === 0)) {
|
|
527
|
+
throw new AdmissionPostgresProtocolError('admission invariant check: malformed result');
|
|
528
|
+
}
|
|
529
|
+
return detached(value);
|
|
530
|
+
},
|
|
531
|
+
};
|
|
532
|
+
return Object.freeze(store);
|
|
533
|
+
}
|
|
534
|
+
/** Compatibility alias following the noun-first naming used by some stores. */
|
|
535
|
+
export const createPostgresAdmissionStore = createAdmissionPostgresStore;
|
|
536
|
+
export default createAdmissionPostgresStore;
|
|
537
|
+
//# sourceMappingURL=admission-store-postgres.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission-store-postgres.js","sourceRoot":"","sources":["../src/admission-store-postgres.ts"],"names":[],"mappings":"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"}
|