@substrat-run/control-plane-api 0.178.0 → 0.179.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aggregate-reads.d.ts.map +1 -1
- package/dist/aggregate-reads.js +4 -3
- package/dist/aggregate-reads.js.map +1 -1
- package/dist/aggregate-source.d.ts +8 -1
- package/dist/aggregate-source.d.ts.map +1 -1
- package/dist/aggregate-source.js +2 -1
- package/dist/aggregate-source.js.map +1 -1
- package/dist/api.d.ts +3 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +223 -148
- package/dist/api.js.map +1 -1
- package/dist/backups.d.ts +28 -5
- package/dist/backups.d.ts.map +1 -1
- package/dist/cf-observability.d.ts.map +1 -1
- package/dist/cf-observability.js +26 -16
- package/dist/cf-observability.js.map +1 -1
- package/dist/observability.d.ts +6 -1
- package/dist/observability.d.ts.map +1 -1
- package/dist/observability.js +8 -1
- package/dist/observability.js.map +1 -1
- package/dist/platform-entry.generated.d.ts +1 -1
- package/dist/platform-entry.generated.d.ts.map +1 -1
- package/dist/platform-entry.generated.js +2 -2
- package/dist/platform-entry.generated.js.map +1 -1
- package/dist/platform-scope-stores.d.ts +20 -22
- package/dist/platform-scope-stores.d.ts.map +1 -1
- package/dist/platform-scope-stores.js +16 -19
- package/dist/platform-scope-stores.js.map +1 -1
- package/dist/r2-backups.d.ts.map +1 -1
- package/dist/r2-backups.js +49 -13
- package/dist/r2-backups.js.map +1 -1
- package/dist/store-entry.generated.d.ts +2 -2
- package/dist/store-entry.generated.d.ts.map +1 -1
- package/dist/store-entry.generated.js +5 -5
- package/dist/store-entry.generated.js.map +1 -1
- package/dist/store-move-ends.d.ts +59 -0
- package/dist/store-move-ends.d.ts.map +1 -0
- package/dist/store-move-ends.js +114 -0
- package/dist/store-move-ends.js.map +1 -0
- package/dist/store-move.d.ts +65 -0
- package/dist/store-move.d.ts.map +1 -0
- package/dist/store-move.js +107 -0
- package/dist/store-move.js.map +1 -0
- package/dist/tenant-request-query.d.ts.map +1 -1
- package/dist/tenant-request-query.js +5 -0
- package/dist/tenant-request-query.js.map +1 -1
- package/package.json +8 -8
package/dist/r2-backups.js
CHANGED
|
@@ -33,16 +33,30 @@ function entryKey(tenantId, scopeId, capturedAt, stageId, seq) {
|
|
|
33
33
|
function scopePrefix(tenantId, scopeId) {
|
|
34
34
|
return `scopes/${tenantId}/${scopeId}/`;
|
|
35
35
|
}
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* A backup's manifest: the dump without its tables, where its entries are, and where each store's
|
|
38
|
+
* pages are (D-69). `storeEntries` defaults to none, so a manifest written before it (#2839) reads as
|
|
39
|
+
* before, its stores inline in `stores`.
|
|
40
|
+
*/
|
|
37
41
|
const backupManifest = scopeDump.omit({ tables: true }).extend({
|
|
38
42
|
format: z.literal('paged'),
|
|
39
43
|
stageId: z.string().min(1),
|
|
40
44
|
entries: z.number().int().positive(),
|
|
41
45
|
tables: z.number().int().nonnegative(),
|
|
46
|
+
storeEntries: z
|
|
47
|
+
.array(z.object({
|
|
48
|
+
binding: z.string().min(1),
|
|
49
|
+
driver: z.string().min(1),
|
|
50
|
+
stageId: z.string().min(1),
|
|
51
|
+
entries: z.number().int().positive(),
|
|
52
|
+
revision: z.string().min(1),
|
|
53
|
+
}))
|
|
54
|
+
.default([]),
|
|
42
55
|
});
|
|
43
56
|
const backupEntry = z.discriminatedUnion('kind', [
|
|
44
57
|
z.object({ kind: z.literal('page'), tables: z.array(scopeDumpPageTable) }),
|
|
45
58
|
z.object({ kind: z.literal('changes'), tables: z.array(scopeDumpChange) }),
|
|
59
|
+
z.object({ kind: z.literal('store-page'), tables: z.array(scopeDumpPageTable) }),
|
|
46
60
|
]);
|
|
47
61
|
/** Byte length, not string length: a size is the stored object's, and non-ASCII would under-report. */
|
|
48
62
|
const byteLength = (body) => new TextEncoder().encode(body).length;
|
|
@@ -69,14 +83,18 @@ export function createR2BackupStore(bucket) {
|
|
|
69
83
|
written.delete(stageId);
|
|
70
84
|
await Promise.all(sizes.map((_, seq) => r2.delete(entryKey(tenantId, scopeId, capturedAt, stageId, seq)).catch(() => undefined)));
|
|
71
85
|
},
|
|
72
|
-
async commit({ stageId, entries, tables }) {
|
|
73
|
-
|
|
74
|
-
for (
|
|
75
|
-
|
|
76
|
-
|
|
86
|
+
async commit({ stageId, entries, tables, storeEntries }) {
|
|
87
|
+
let size = 0;
|
|
88
|
+
for (const part of [{ stageId, entries }, ...storeEntries]) {
|
|
89
|
+
const sizes = written.get(part.stageId) ?? [];
|
|
90
|
+
for (let seq = 0; seq < part.entries; seq++) {
|
|
91
|
+
if (sizes[seq] === undefined)
|
|
92
|
+
throw new Error(`backup entry ${seq} of ${part.entries} under ${part.stageId} was never written`);
|
|
93
|
+
size += sizes[seq];
|
|
94
|
+
}
|
|
77
95
|
}
|
|
78
|
-
const body = JSON.stringify({ ...header, format: 'paged', stageId, entries, tables });
|
|
79
|
-
|
|
96
|
+
const body = JSON.stringify({ ...header, format: 'paged', stageId, entries, tables, storeEntries });
|
|
97
|
+
size += byteLength(body);
|
|
80
98
|
const backup = { tenantId, scopeId, vertical, capturedAt, size, tables };
|
|
81
99
|
await r2.put(backupKey(tenantId, scopeId, capturedAt), body, {
|
|
82
100
|
httpMetadata: { contentType: 'application/json' },
|
|
@@ -145,17 +163,35 @@ export function createR2BackupStore(bucket) {
|
|
|
145
163
|
throw new Error(`backup ${capturedAt} of scope ${scopeId} has one entry`);
|
|
146
164
|
return { kind: 'page', tables };
|
|
147
165
|
},
|
|
166
|
+
storeEntries: [],
|
|
167
|
+
storePage: async () => {
|
|
168
|
+
throw new Error(`backup ${capturedAt} of scope ${scopeId} holds its stores inline`);
|
|
169
|
+
},
|
|
148
170
|
};
|
|
149
171
|
}
|
|
150
|
-
const { format: _, stageId, entries, tables: __, ...header } = backupManifest.parse(raw);
|
|
172
|
+
const { format: _, stageId, entries, tables: __, storeEntries, ...header } = backupManifest.parse(raw);
|
|
173
|
+
const read = async (at, index) => {
|
|
174
|
+
const part = await r2.get(entryKey(tenantId, scopeId, capturedAt, at, index));
|
|
175
|
+
if (!part)
|
|
176
|
+
throw new Error(`backup ${capturedAt} of scope ${scopeId} is missing entry ${index} of ${at}`);
|
|
177
|
+
return backupEntry.parse(JSON.parse(await part.text()));
|
|
178
|
+
};
|
|
151
179
|
return {
|
|
152
180
|
header,
|
|
153
181
|
entries,
|
|
182
|
+
// A store's page and a scope's share a shape, so the kind is what says which this is.
|
|
154
183
|
entry: async (index) => {
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
157
|
-
throw new Error(`backup ${capturedAt} of scope ${scopeId}
|
|
158
|
-
return
|
|
184
|
+
const entry = await read(stageId, index);
|
|
185
|
+
if (entry.kind === 'store-page')
|
|
186
|
+
throw new Error(`backup ${capturedAt} of scope ${scopeId} holds a store page where its entry ${index} belongs`);
|
|
187
|
+
return entry;
|
|
188
|
+
},
|
|
189
|
+
storeEntries,
|
|
190
|
+
storePage: async (store, seq) => {
|
|
191
|
+
const entry = await read(store.stageId, seq);
|
|
192
|
+
if (entry.kind !== 'store-page')
|
|
193
|
+
throw new Error(`backup ${capturedAt} of scope ${scopeId} holds a '${entry.kind}' entry where a store page belongs`);
|
|
194
|
+
return entry.tables;
|
|
159
195
|
},
|
|
160
196
|
};
|
|
161
197
|
},
|
package/dist/r2-backups.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"r2-backups.js","sourceRoot":"","sources":["../src/r2-backups.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"r2-backups.js","sourceRoot":"","sources":["../src/r2-backups.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,7 +44,7 @@ export declare const STORE_SCRIPT_VAR = "SUBSTRAT_STORE_SCRIPT";
|
|
|
44
44
|
* it, so both entries run one verifier. Reserved.
|
|
45
45
|
*/
|
|
46
46
|
export declare const STORE_VERIFIER_MODULE = "substrat-store-verify.js";
|
|
47
|
-
/** The entry itself —
|
|
47
|
+
/** The entry itself — 13911 bytes of ESM. */
|
|
48
48
|
export declare const STORE_ENTRY_SOURCE: string;
|
|
49
49
|
/**
|
|
50
50
|
* The Python entry (#2290), uploaded as `substrat_store_entry.py`. The driver module's
|
|
@@ -54,7 +54,7 @@ export declare const STORE_ENTRY_SOURCE: string;
|
|
|
54
54
|
export declare const STORE_ENTRY_PYTHON_SOURCE: string;
|
|
55
55
|
/**
|
|
56
56
|
* The verifier the Python entry imports, uploaded beside it as `substrat-store-verify.js`
|
|
57
|
-
* (an ES module). It is `packages/control-plane-api/store-entry/verify.ts`, the check the JavaScript entry runs —
|
|
57
|
+
* (an ES module). It is `packages/control-plane-api/store-entry/verify.ts`, the check the JavaScript entry runs — 11756 bytes.
|
|
58
58
|
*/
|
|
59
59
|
export declare const STORE_ENTRY_PYTHON_VERIFIER_SOURCE: string;
|
|
60
60
|
//# sourceMappingURL=store-entry.generated.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-entry.generated.d.ts","sourceRoot":"","sources":["../src/store-entry.generated.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAElE,2FAA2F;AAC3F,eAAO,MAAM,uBAAuB,6BAA6B,CAAC;AAElE,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,8BAA8B,CAAC;AAEpE,4GAA4G;AAC5G,eAAO,MAAM,kBAAkB,4BAA4B,CAAC;AAE5D;;;GAGG;AACH,eAAO,MAAM,yBAAyB,4BAA4B,CAAC;AAEnE,wDAAwD;AACxD,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AAErD,gGAAgG;AAChG,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AAExD,+DAA+D;AAC/D,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAEtE;;;GAGG;AACH,eAAO,MAAM,+BAA+B,eAAe,CAAC;AAE5D,6GAA6G;AAC7G,eAAO,MAAM,gCAAgC,UAAqB,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,6BAA6B,mBAAmB,CAAC;AAE9D,mGAAmG;AACnG,eAAO,MAAM,sBAAsB,UAAmF,CAAC;AAEvH,8FAA8F;AAC9F,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,6BAA6B,CAAC;AAEhE,6CAA6C;AAC7C,eAAO,MAAM,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"store-entry.generated.d.ts","sourceRoot":"","sources":["../src/store-entry.generated.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAElE,2FAA2F;AAC3F,eAAO,MAAM,uBAAuB,6BAA6B,CAAC;AAElE,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,8BAA8B,CAAC;AAEpE,4GAA4G;AAC5G,eAAO,MAAM,kBAAkB,4BAA4B,CAAC;AAE5D;;;GAGG;AACH,eAAO,MAAM,yBAAyB,4BAA4B,CAAC;AAEnE,wDAAwD;AACxD,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AAErD,gGAAgG;AAChG,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AAExD,+DAA+D;AAC/D,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAEtE;;;GAGG;AACH,eAAO,MAAM,+BAA+B,eAAe,CAAC;AAE5D,6GAA6G;AAC7G,eAAO,MAAM,gCAAgC,UAAqB,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,6BAA6B,mBAAmB,CAAC;AAE9D,mGAAmG;AACnG,eAAO,MAAM,sBAAsB,UAAmF,CAAC;AAEvH,8FAA8F;AAC9F,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,6BAA6B,CAAC;AAEhE,6CAA6C;AAC7C,eAAO,MAAM,kBAAkB,EAAE,MAAgqc,CAAC;AAElsc;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAs1M,CAAC;AAE/3M;;;GAGG;AACH,eAAO,MAAM,kCAAkC,EAAE,MAAg/X,CAAC"}
|
|
@@ -46,17 +46,17 @@ export const STORE_SCRIPT_VAR = "SUBSTRAT_STORE_SCRIPT";
|
|
|
46
46
|
* it, so both entries run one verifier. Reserved.
|
|
47
47
|
*/
|
|
48
48
|
export const STORE_VERIFIER_MODULE = "substrat-store-verify.js";
|
|
49
|
-
/** The entry itself —
|
|
50
|
-
export const STORE_ENTRY_SOURCE = "// packages/control-plane-api/store-entry/entry.ts\nimport { DurableObject } from \"cloudflare:workers\";\nimport * as driverModule from \"__SUBSTRAT_STORE_DRIVER__\";\n\n// packages/control-plane-api/store-entry/names.ts\nvar STORE_OBJECT_BINDING = \"SUBSTRAT_STORE\";\nvar STORE_SCRIPT_VAR = \"SUBSTRAT_STORE_SCRIPT\";\nvar STORE_CALLER_KEYS_VAR = \"SUBSTRAT_STORE_CALLER_KEYS\";\nvar STORE_PLATFORM_KEYS_VAR = \"SUBSTRAT_STORE_PLATFORM_KEYS\";\nvar STORE_RESERVED_BINDING_PREFIX = \"SUBSTRAT_STORE\";\n\n// packages/contracts/dist/scope-store-envelope.js\nvar SCOPE_STORE_ENVELOPE_WINDOW_SECONDS = 60;\nvar SCOPE_STORE_ENVELOPE_HEADER = \"x-substrat-store-envelope\";\nvar SCOPE_STORE_SIGNATURE_HEADER = \"x-substrat-store-signature\";\nvar RESERVED_STORE_OPERATIONS = [\n \"substrat.export-page\",\n \"substrat.stage-page\",\n \"substrat.commit-stage\",\n \"substrat.discard-stage\",\n \"substrat.size\",\n \"substrat.wipe\",\n \"substrat.erase\",\n \"substrat.selfcheck\"\n];\nvar STORE_STAGE_MAX_AGE_MS = 6 * 36e5 + 3 * 30 * 6e4;\nvar STORE_CALL_MAX_BYTES = 4 * 1024 * 1024;\nvar STORE_DUMP_PAGE_MAX_BYTES = 3 * 1024 * 1024;\nvar ADMITTED = {\n \"1\": {\n platform: (op) => RESERVED_STORE_OPERATIONS.includes(op),\n caller: (op) => !op.startsWith(\"substrat.\")\n }\n};\nfunction scopeStoreEnvelopeAdmits(v, aud, op) {\n const byAudience = Object.hasOwn(ADMITTED, String(v)) ? ADMITTED[String(v)] : void 0;\n if (!byAudience || !Object.hasOwn(byAudience, aud))\n return false;\n return byAudience[aud](op);\n}\nfunction bytesToBase64Url(bytes) {\n let binary = \"\";\n for (const byte of bytes)\n binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\nfunction base64UrlToBytes(value) {\n if (!/^[A-Za-z0-9_-]+$/.test(value))\n return void 0;\n const padded = value.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\") + \"=\".repeat((4 - value.length % 4) % 4);\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return bytes;\n } catch {\n return void 0;\n }\n}\nfunction copyBytes(bytes) {\n const copy = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(copy).set(bytes);\n return copy;\n}\nfunction isCanonicalBase64Url(text, length) {\n const bytes = base64UrlToBytes(text);\n return bytes?.length === length && bytesToBase64Url(bytes) === text;\n}\nvar NONCE = /^[A-Za-z0-9_-]{22}$/;\nvar KID = /^[A-Za-z0-9_-]{11}$/;\nvar DIGEST = /^[0-9a-f]{64}$/;\nvar IAT = /^(0|[1-9]\\d{0,14})$/;\nfunction parseScopeStoreEnvelope(canonical) {\n const lines = canonical.split(\"\\n\");\n if (lines.length !== 9)\n return void 0;\n const [version, aud, kid, script, name, op, digest, iatText, nonce] = lines;\n if (version !== \"1\" || aud !== \"caller\" && aud !== \"platform\")\n return void 0;\n if (!script || !name || !op)\n return void 0;\n if (!KID.test(kid) || !DIGEST.test(digest) || !IAT.test(iatText) || !NONCE.test(nonce))\n return void 0;\n if (!isCanonicalBase64Url(kid, 8) || !isCanonicalBase64Url(nonce, 16))\n return void 0;\n return { v: 1, aud, kid, script, name, op, digest, iat: Number(iatText), nonce };\n}\nasync function scopeStoreBodyDigest(body) {\n const hash = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(body));\n return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\nfunction scopeStoreEnvelopeFresh(iat, nowSeconds, windowSeconds = SCOPE_STORE_ENVELOPE_WINDOW_SECONDS) {\n return Math.abs(nowSeconds - iat) <= windowSeconds;\n}\nvar SMALL_ORDER_KEYS = [\n \"0000000000000000000000000000000000000000000000000000000000000000\",\n // y = 0, order 4\n \"0100000000000000000000000000000000000000000000000000000000000000\",\n // the identity, order 1\n \"26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05\",\n // order 8\n \"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a\",\n // order 8\n \"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p - 1, order 2\n \"edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p, a non-canonical 0\n \"eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\"\n // y = p + 1, a non-canonical identity\n];\nfunction isSmallOrderKey(bytes) {\n const unsigned = Uint8Array.from(bytes);\n unsigned[31] = unsigned[31] & 127;\n const hex = [...unsigned].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return SMALL_ORDER_KEYS.includes(hex);\n}\nasync function scopeStoreKeyId(publicKey) {\n const bytes = base64UrlToBytes(publicKey);\n if (!bytes || bytes.length !== 32)\n throw new Error(\"a store public key is not 32 bytes of base64url\");\n if (isSmallOrderKey(bytes))\n throw new Error(\"a store public key is a small-order point\");\n const hash = await crypto.subtle.digest(\"SHA-256\", copyBytes(bytes));\n return bytesToBase64Url(new Uint8Array(hash).slice(0, 8));\n}\nfunction scopeStorePublicKeyProblem(key) {\n if (key.length === 0)\n return \"empty\";\n const bytes = base64UrlToBytes(key);\n if (bytes?.length !== 32)\n return \"length\";\n if (isSmallOrderKey(bytes))\n return \"small-order\";\n if (bytesToBase64Url(bytes) !== key)\n return \"non-canonical\";\n return void 0;\n}\nvar PUBLIC_KEY_PROBLEM = {\n empty: \"a store public key list is empty or has an empty entry\",\n length: \"a store public key is not 32 bytes of base64url\",\n \"small-order\": \"a store public key is a small-order point\",\n \"non-canonical\": \"a store public key is not canonical base64url\"\n};\nfunction parseScopeStorePublicKeys(text) {\n const keys = text.split(\",\").map((key) => key.trim());\n if (keys.some((key) => key.length === 0))\n throw new Error(PUBLIC_KEY_PROBLEM.empty);\n const seen = /* @__PURE__ */ new Set();\n for (const key of keys) {\n const problem = scopeStorePublicKeyProblem(key);\n if (problem)\n throw new Error(PUBLIC_KEY_PROBLEM[problem]);\n if (seen.has(key))\n throw new Error(\"a store public key is listed twice\");\n seen.add(key);\n }\n return keys;\n}\nfunction scopeStorePublicKeysFrom(config) {\n const caller = parseScopeStorePublicKeys(config.caller);\n const platform = parseScopeStorePublicKeys(config.platform);\n if (caller.some((key) => platform.includes(key))) {\n throw new Error(\"a store public key is listed for both audiences\");\n }\n return { caller, platform };\n}\nasync function verifyScopeStoreEnvelope(publicKey, canonical, signature) {\n const keyBytes = base64UrlToBytes(publicKey);\n const sigBytes = base64UrlToBytes(signature);\n if (!keyBytes || !sigBytes || sigBytes.length !== 64)\n return false;\n try {\n const key = await crypto.subtle.importKey(\"raw\", copyBytes(keyBytes), { name: \"Ed25519\" }, false, [\"verify\"]);\n return await crypto.subtle.verify(\"Ed25519\", key, copyBytes(sigBytes), new TextEncoder().encode(canonical));\n } catch {\n return false;\n }\n}\nasync function verifyScopeStoreCall(input) {\n const refuse = (refusal2) => ({ ok: false, refusal: refusal2 });\n if (!input.envelope || !input.signature)\n return refuse(\"missing\");\n const bytes = base64UrlToBytes(input.envelope);\n if (!bytes)\n return refuse(\"malformed\");\n let canonical;\n try {\n canonical = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n } catch {\n return refuse(\"malformed\");\n }\n const envelope = parseScopeStoreEnvelope(canonical);\n if (!envelope)\n return refuse(\"malformed\");\n if (!scopeStoreEnvelopeAdmits(envelope.v, envelope.aud, envelope.op))\n return refuse(\"audience\");\n const kidsOf = async (keys) => {\n const kids = /* @__PURE__ */ new Map();\n for (const key of keys) {\n try {\n kids.set(await scopeStoreKeyId(key), key);\n } catch {\n }\n }\n return kids;\n };\n const own = await kidsOf(input.keys[envelope.aud]);\n const other = await kidsOf(input.keys[envelope.aud === \"caller\" ? \"platform\" : \"caller\"]);\n if ([...own.keys()].some((kid) => other.has(kid)))\n return refuse(\"keys\");\n const publicKey = own.get(envelope.kid);\n if (!publicKey)\n return refuse(\"kid\");\n if (!await verifyScopeStoreEnvelope(publicKey, canonical, input.signature))\n return refuse(\"signature\");\n if (envelope.digest !== await scopeStoreBodyDigest(input.body))\n return refuse(\"digest\");\n if (!scopeStoreEnvelopeFresh(envelope.iat, input.nowSeconds, input.windowSeconds))\n return refuse(\"stale\");\n if (envelope.script !== input.script)\n return refuse(\"script\");\n let parsed;\n try {\n parsed = JSON.parse(input.body);\n } catch {\n return refuse(\"body\");\n }\n const field = (key) => typeof parsed === \"object\" && parsed !== null ? Reflect.get(parsed, key) : void 0;\n if (field(\"operation\") !== envelope.op || field(\"objectName\") !== envelope.name)\n return refuse(\"body\");\n return { ok: true, envelope };\n}\n\n// packages/control-plane-api/store-entry/verify.ts\nvar tooLarge = { ok: false, status: 413, message: `payload too large: at most ${STORE_CALL_MAX_BYTES} bytes` };\nfunction storeCallDeclaredRefusal(headers) {\n const declared = headers.get(\"content-length\");\n return declared !== null && /^\\d+$/.test(declared.trim()) && Number(declared) > STORE_CALL_MAX_BYTES ? tooLarge : void 0;\n}\nasync function boundedBody(body) {\n if (!body) return new Uint8Array(0);\n const reader = body.getReader();\n const chunks = [];\n let total = 0;\n for (; ; ) {\n const { done, value } = await reader.read();\n if (done || !value) break;\n total += value.byteLength;\n if (total > STORE_CALL_MAX_BYTES) {\n await reader.cancel().catch(() => void 0);\n return tooLarge;\n }\n chunks.push(value);\n }\n const bytes = new Uint8Array(total);\n let at = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, at);\n at += chunk.byteLength;\n }\n return bytes;\n}\nasync function verifiedStoreCall(request, env) {\n const declared = storeCallDeclaredRefusal(request.headers);\n if (declared) return declared;\n const bytes = await boundedBody(request.body);\n if (!(bytes instanceof Uint8Array)) return bytes;\n let text;\n try {\n text = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(bytes);\n } catch {\n return { ok: false, status: 401, message: \"unauthorized: digest\" };\n }\n const verdict = await storeCallVerdict(request.headers, text, env);\n return verdict.ok ? { ok: true, envelope: verdict.envelope, body: bytes.buffer } : verdict;\n}\nasync function storeCallVerdict(headers, body, env) {\n const script = env[STORE_SCRIPT_VAR];\n let keys;\n try {\n if (typeof script !== \"string\" || script.length === 0) throw new Error(\"no script name\");\n keys = scopeStorePublicKeysFrom({\n caller: String(env[STORE_CALLER_KEYS_VAR] ?? \"\"),\n platform: String(env[STORE_PLATFORM_KEYS_VAR] ?? \"\")\n });\n } catch {\n return { ok: false, status: 503, message: \"this store script is not configured\" };\n }\n const verdict = await verifyScopeStoreCall({\n envelope: headers.get(SCOPE_STORE_ENVELOPE_HEADER),\n signature: headers.get(SCOPE_STORE_SIGNATURE_HEADER),\n body,\n keys,\n script,\n nowSeconds: Math.floor(Date.now() / 1e3)\n });\n return verdict.ok ? verdict : { ok: false, status: 401, message: `unauthorized: ${verdict.refusal}` };\n}\n\n// packages/control-plane-api/store-entry/entry.ts\nvar Driver = driverModule[\"__SUBSTRAT_STORE_CLASS__\"];\nvar refusal = ({ status, message }) => new Response(message, { status });\nfunction driverEnvOf(env) {\n return Object.fromEntries(Object.entries(env).filter(([name]) => !name.startsWith(STORE_RESERVED_BINDING_PREFIX)));\n}\nasync function verified(request, env) {\n const call = await verifiedStoreCall(request, env);\n return call.ok ? call : refusal(call);\n}\nvar SubstratStoreObject = class extends DurableObject {\n #driver;\n /** Constructed once per object instance, on first use, so the driver keeps its in-memory state. */\n #driverObject() {\n this.#driver ??= new Driver(this.ctx, driverEnvOf(this.env));\n return this.#driver;\n }\n async fetch(request) {\n const call = await verified(request, this.env);\n if (call instanceof Response) return call;\n const ns = this.env[STORE_OBJECT_BINDING];\n if (!this.ctx.id.equals(ns.idFromName(call.envelope.name))) return new Response(\"unauthorized: object\", { status: 401 });\n return this.#driverObject().fetch(\n new Request(request.url, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: call.body })\n );\n }\n /** An alarm is the object's own timer, which only the driver sets. It goes to the driver. */\n async alarm(alarmInfo) {\n const driver = this.#driverObject();\n if (typeof driver.alarm === \"function\") await driver.alarm(alarmInfo);\n }\n};\nvar entry_default = {\n async fetch(request, env) {\n const call = await verified(request, env);\n if (call instanceof Response) return call;\n const ns = env[STORE_OBJECT_BINDING];\n return ns.get(ns.idFromName(call.envelope.name)).fetch(\n new Request(request.url, { method: \"POST\", headers: request.headers, body: call.body })\n );\n }\n};\nexport {\n SubstratStoreObject,\n entry_default as default\n};\n";
|
|
49
|
+
/** The entry itself — 13911 bytes of ESM. */
|
|
50
|
+
export const STORE_ENTRY_SOURCE = "// packages/control-plane-api/store-entry/entry.ts\nimport { DurableObject } from \"cloudflare:workers\";\nimport * as driverModule from \"__SUBSTRAT_STORE_DRIVER__\";\n\n// packages/control-plane-api/store-entry/names.ts\nvar STORE_OBJECT_BINDING = \"SUBSTRAT_STORE\";\nvar STORE_SCRIPT_VAR = \"SUBSTRAT_STORE_SCRIPT\";\nvar STORE_CALLER_KEYS_VAR = \"SUBSTRAT_STORE_CALLER_KEYS\";\nvar STORE_PLATFORM_KEYS_VAR = \"SUBSTRAT_STORE_PLATFORM_KEYS\";\nvar STORE_RESERVED_BINDING_PREFIX = \"SUBSTRAT_STORE\";\n\n// packages/contracts/dist/scope-store-envelope.js\nvar SCOPE_STORE_ENVELOPE_WINDOW_SECONDS = 60;\nvar SCOPE_STORE_ENVELOPE_HEADER = \"x-substrat-store-envelope\";\nvar SCOPE_STORE_SIGNATURE_HEADER = \"x-substrat-store-signature\";\nvar RESERVED_STORE_OPERATIONS = [\n \"substrat.export-page\",\n \"substrat.stage-page\",\n \"substrat.commit-stage\",\n \"substrat.discard-stage\",\n \"substrat.size\",\n \"substrat.wipe\",\n \"substrat.erase\",\n \"substrat.selfcheck\"\n];\nvar STORE_STAGE_MAX_AGE_MS = 6 * 36e5 + 3 * 30 * 6e4;\nvar STORE_CALL_MAX_BYTES = 4 * 1024 * 1024;\nvar STORE_DUMP_PAGE_MAX_BYTES = 3 * 1024 * 1024;\nvar ADMITTED = {\n \"1\": {\n platform: (op) => RESERVED_STORE_OPERATIONS.includes(op),\n caller: (op) => !op.startsWith(\"substrat.\")\n }\n};\nfunction scopeStoreEnvelopeAdmits(v, aud, op) {\n const byAudience = Object.hasOwn(ADMITTED, String(v)) ? ADMITTED[String(v)] : void 0;\n if (!byAudience || !Object.hasOwn(byAudience, aud))\n return false;\n return byAudience[aud](op);\n}\nfunction bytesToBase64Url(bytes) {\n let binary = \"\";\n for (const byte of bytes)\n binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\nfunction base64UrlToBytes(value) {\n if (!/^[A-Za-z0-9_-]+$/.test(value))\n return void 0;\n const padded = value.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\") + \"=\".repeat((4 - value.length % 4) % 4);\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return bytes;\n } catch {\n return void 0;\n }\n}\nfunction copyBytes(bytes) {\n const copy = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(copy).set(bytes);\n return copy;\n}\nfunction isCanonicalBase64Url(text, length) {\n const bytes = base64UrlToBytes(text);\n return bytes?.length === length && bytesToBase64Url(bytes) === text;\n}\nvar NONCE = /^[A-Za-z0-9_-]{22}$/;\nvar KID = /^[A-Za-z0-9_-]{11}$/;\nvar DIGEST = /^[0-9a-f]{64}$/;\nvar IAT = /^(0|[1-9]\\d{0,14})$/;\nfunction parseScopeStoreEnvelope(canonical) {\n const lines = canonical.split(\"\\n\");\n if (lines.length !== 9)\n return void 0;\n const [version, aud, kid, script, name, op, digest, iatText, nonce] = lines;\n if (version !== \"1\" || aud !== \"caller\" && aud !== \"platform\")\n return void 0;\n if (!script || !name || !op)\n return void 0;\n if (!KID.test(kid) || !DIGEST.test(digest) || !IAT.test(iatText) || !NONCE.test(nonce))\n return void 0;\n if (!isCanonicalBase64Url(kid, 8) || !isCanonicalBase64Url(nonce, 16))\n return void 0;\n return { v: 1, aud, kid, script, name, op, digest, iat: Number(iatText), nonce };\n}\nasync function scopeStoreBodyDigest(body) {\n const hash = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(body));\n return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\nfunction scopeStoreEnvelopeFresh(iat, nowSeconds, windowSeconds = SCOPE_STORE_ENVELOPE_WINDOW_SECONDS) {\n return Math.abs(nowSeconds - iat) <= windowSeconds;\n}\nvar SMALL_ORDER_KEYS = [\n \"0000000000000000000000000000000000000000000000000000000000000000\",\n // y = 0, order 4\n \"0100000000000000000000000000000000000000000000000000000000000000\",\n // the identity, order 1\n \"26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05\",\n // order 8\n \"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a\",\n // order 8\n \"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p - 1, order 2\n \"edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p, a non-canonical 0\n \"eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\"\n // y = p + 1, a non-canonical identity\n];\nfunction isSmallOrderKey(bytes) {\n const unsigned = Uint8Array.from(bytes);\n unsigned[31] = unsigned[31] & 127;\n const hex = [...unsigned].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return SMALL_ORDER_KEYS.includes(hex);\n}\nasync function scopeStoreKeyId(publicKey) {\n const bytes = base64UrlToBytes(publicKey);\n if (!bytes || bytes.length !== 32)\n throw new Error(\"a store public key is not 32 bytes of base64url\");\n if (isSmallOrderKey(bytes))\n throw new Error(\"a store public key is a small-order point\");\n const hash = await crypto.subtle.digest(\"SHA-256\", copyBytes(bytes));\n return bytesToBase64Url(new Uint8Array(hash).slice(0, 8));\n}\nfunction scopeStorePublicKeyProblem(key) {\n if (key.length === 0)\n return \"empty\";\n const bytes = base64UrlToBytes(key);\n if (bytes?.length !== 32)\n return \"length\";\n if (isSmallOrderKey(bytes))\n return \"small-order\";\n if (bytesToBase64Url(bytes) !== key)\n return \"non-canonical\";\n return void 0;\n}\nvar PUBLIC_KEY_PROBLEM = {\n empty: \"a store public key list is empty or has an empty entry\",\n length: \"a store public key is not 32 bytes of base64url\",\n \"small-order\": \"a store public key is a small-order point\",\n \"non-canonical\": \"a store public key is not canonical base64url\"\n};\nfunction parseScopeStorePublicKeys(text) {\n const keys = text.split(\",\").map((key) => key.trim());\n if (keys.some((key) => key.length === 0))\n throw new Error(PUBLIC_KEY_PROBLEM.empty);\n const seen = /* @__PURE__ */ new Set();\n for (const key of keys) {\n const problem = scopeStorePublicKeyProblem(key);\n if (problem)\n throw new Error(PUBLIC_KEY_PROBLEM[problem]);\n if (seen.has(key))\n throw new Error(\"a store public key is listed twice\");\n seen.add(key);\n }\n return keys;\n}\nfunction scopeStorePublicKeysFrom(config) {\n const caller = parseScopeStorePublicKeys(config.caller);\n const platform = parseScopeStorePublicKeys(config.platform);\n if (caller.some((key) => platform.includes(key))) {\n throw new Error(\"a store public key is listed for both audiences\");\n }\n return { caller, platform };\n}\nasync function verifyScopeStoreEnvelope(publicKey, canonical, signature) {\n const keyBytes = base64UrlToBytes(publicKey);\n const sigBytes = base64UrlToBytes(signature);\n if (!keyBytes || !sigBytes || sigBytes.length !== 64)\n return false;\n try {\n const key = await crypto.subtle.importKey(\"raw\", copyBytes(keyBytes), { name: \"Ed25519\" }, false, [\"verify\"]);\n return await crypto.subtle.verify(\"Ed25519\", key, copyBytes(sigBytes), new TextEncoder().encode(canonical));\n } catch {\n return false;\n }\n}\nasync function verifyScopeStoreCall(input) {\n const refuse = (refusal2) => ({ ok: false, refusal: refusal2 });\n if (!input.envelope || !input.signature)\n return refuse(\"missing\");\n const bytes = base64UrlToBytes(input.envelope);\n if (!bytes)\n return refuse(\"malformed\");\n let canonical;\n try {\n canonical = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n } catch {\n return refuse(\"malformed\");\n }\n const envelope = parseScopeStoreEnvelope(canonical);\n if (!envelope)\n return refuse(\"malformed\");\n if (!scopeStoreEnvelopeAdmits(envelope.v, envelope.aud, envelope.op))\n return refuse(\"audience\");\n const kidsOf = async (keys) => {\n const kids = /* @__PURE__ */ new Map();\n for (const key of keys) {\n try {\n kids.set(await scopeStoreKeyId(key), key);\n } catch {\n }\n }\n return kids;\n };\n const own = await kidsOf(input.keys[envelope.aud]);\n const other = await kidsOf(input.keys[envelope.aud === \"caller\" ? \"platform\" : \"caller\"]);\n if ([...own.keys()].some((kid) => other.has(kid)))\n return refuse(\"keys\");\n const publicKey = own.get(envelope.kid);\n if (!publicKey)\n return refuse(\"kid\");\n if (!await verifyScopeStoreEnvelope(publicKey, canonical, input.signature))\n return refuse(\"signature\");\n if (envelope.digest !== await scopeStoreBodyDigest(input.body))\n return refuse(\"digest\");\n if (!scopeStoreEnvelopeFresh(envelope.iat, input.nowSeconds, input.windowSeconds))\n return refuse(\"stale\");\n if (envelope.script !== input.script)\n return refuse(\"script\");\n let parsed;\n try {\n parsed = JSON.parse(input.body);\n } catch {\n return refuse(\"body\");\n }\n const field = (key) => typeof parsed === \"object\" && parsed !== null ? Reflect.get(parsed, key) : void 0;\n if (field(\"operation\") !== envelope.op || field(\"objectName\") !== envelope.name)\n return refuse(\"body\");\n return { ok: true, envelope };\n}\n\n// packages/control-plane-api/store-entry/verify.ts\nvar tooLarge = { ok: false, status: 413, message: `payload too large: at most ${STORE_CALL_MAX_BYTES} bytes` };\nfunction storeCallDeclaredRefusal(headers) {\n const declared = headers.get(\"content-length\");\n return declared !== null && /^\\d+$/.test(declared.trim()) && Number(declared) > STORE_CALL_MAX_BYTES ? tooLarge : void 0;\n}\nasync function boundedBody(body) {\n if (!body) return new Uint8Array(0);\n const reader = body.getReader();\n const chunks = [];\n let total = 0;\n for (; ; ) {\n const { done, value } = await reader.read();\n if (done || !value) break;\n total += value.byteLength;\n if (total > STORE_CALL_MAX_BYTES) {\n await reader.cancel().catch(() => void 0);\n return tooLarge;\n }\n chunks.push(value);\n }\n const bytes = new Uint8Array(total);\n let at = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, at);\n at += chunk.byteLength;\n }\n return bytes;\n}\nasync function verifiedStoreCall(request, env) {\n const declared = storeCallDeclaredRefusal(request.headers);\n if (declared) return declared;\n const bytes = await boundedBody(request.body);\n if (!(bytes instanceof Uint8Array)) return bytes;\n let text;\n try {\n text = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(bytes);\n } catch {\n return { ok: false, status: 401, message: \"unauthorized: digest\" };\n }\n const verdict = await storeCallVerdict(request.headers, text, env);\n return verdict.ok ? { ok: true, envelope: verdict.envelope, body: bytes.buffer } : verdict;\n}\nvar STORE_NONCE_KEY_PREFIX = \"substrat.store-nonce/\";\nvar STORE_NONCE_PRUNE_BATCH = 64;\nvar nonceKey = (iat) => `${STORE_NONCE_KEY_PREFIX}${String(iat).padStart(15, \"0\")}/`;\nfunction spendStoreNonce(storage, envelope, nowSeconds) {\n const { kv } = storage;\n const expired = nonceKey(nowSeconds - SCOPE_STORE_ENVELOPE_WINDOW_SECONDS);\n for (const [key2] of kv.list({ prefix: STORE_NONCE_KEY_PREFIX, end: expired, limit: STORE_NONCE_PRUNE_BATCH })) kv.delete(key2);\n if (!scopeStoreEnvelopeFresh(envelope.iat, nowSeconds)) return false;\n const key = `${nonceKey(envelope.iat)}${envelope.nonce}`;\n if (kv.get(key) !== void 0) return false;\n kv.put(key, 1);\n return true;\n}\nvar spentNonce = { ok: false, status: 401, message: \"unauthorized: nonce\" };\nasync function storeCallVerdict(headers, body, env) {\n const script = env[STORE_SCRIPT_VAR];\n let keys;\n try {\n if (typeof script !== \"string\" || script.length === 0) throw new Error(\"no script name\");\n keys = scopeStorePublicKeysFrom({\n caller: String(env[STORE_CALLER_KEYS_VAR] ?? \"\"),\n platform: String(env[STORE_PLATFORM_KEYS_VAR] ?? \"\")\n });\n } catch {\n return { ok: false, status: 503, message: \"this store script is not configured\" };\n }\n const verdict = await verifyScopeStoreCall({\n envelope: headers.get(SCOPE_STORE_ENVELOPE_HEADER),\n signature: headers.get(SCOPE_STORE_SIGNATURE_HEADER),\n body,\n keys,\n script,\n nowSeconds: Math.floor(Date.now() / 1e3)\n });\n return verdict.ok ? verdict : { ok: false, status: 401, message: `unauthorized: ${verdict.refusal}` };\n}\n\n// packages/control-plane-api/store-entry/entry.ts\nvar Driver = driverModule[\"__SUBSTRAT_STORE_CLASS__\"];\nvar refusal = ({ status, message }) => new Response(message, { status });\nfunction driverEnvOf(env) {\n return Object.fromEntries(Object.entries(env).filter(([name]) => !name.startsWith(STORE_RESERVED_BINDING_PREFIX)));\n}\nasync function verified(request, env) {\n const call = await verifiedStoreCall(request, env);\n return call.ok ? call : refusal(call);\n}\nvar SubstratStoreObject = class extends DurableObject {\n #driver;\n /** Constructed once per object instance, on first use, so the driver keeps its in-memory state. */\n #driverObject() {\n this.#driver ??= new Driver(this.ctx, driverEnvOf(this.env));\n return this.#driver;\n }\n async fetch(request) {\n const call = await verified(request, this.env);\n if (call instanceof Response) return call;\n const ns = this.env[STORE_OBJECT_BINDING];\n if (!this.ctx.id.equals(ns.idFromName(call.envelope.name))) return new Response(\"unauthorized: object\", { status: 401 });\n if (!spendStoreNonce(this.ctx.storage, call.envelope, Math.floor(Date.now() / 1e3))) return refusal(spentNonce);\n return this.#driverObject().fetch(\n new Request(request.url, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: call.body })\n );\n }\n /** An alarm is the object's own timer, which only the driver sets. It goes to the driver. */\n async alarm(alarmInfo) {\n const driver = this.#driverObject();\n if (typeof driver.alarm === \"function\") await driver.alarm(alarmInfo);\n }\n};\nvar entry_default = {\n async fetch(request, env) {\n const call = await verified(request, env);\n if (call instanceof Response) return call;\n const ns = env[STORE_OBJECT_BINDING];\n return ns.get(ns.idFromName(call.envelope.name)).fetch(\n new Request(request.url, { method: \"POST\", headers: request.headers, body: call.body })\n );\n }\n};\nexport {\n SubstratStoreObject,\n entry_default as default\n};\n";
|
|
51
51
|
/**
|
|
52
52
|
* The Python entry (#2290), uploaded as `substrat_store_entry.py`. The driver module's
|
|
53
53
|
* name (a Python module name, no `.py`) replaces `__SUBSTRAT_STORE_DRIVER__` and its class
|
|
54
54
|
* name replaces `__SUBSTRAT_STORE_CLASS__`, as in the JavaScript entry.
|
|
55
55
|
*/
|
|
56
|
-
export const STORE_ENTRY_PYTHON_SOURCE = "\"\"\"The platform's Python store entry (#2290), the twin of store-entry/entry.ts.\n\nUploaded as the store script's main module when the driver is Python. The driver's class is\nimported through the two placeholders below, which the upload replaces with the driver's module\nname and class name, as it does for the JavaScript entry. The driver is reached only through\nthis module, after the call is verified.\n\nThere is one verifier. Every call is checked by store-entry/verify.ts, bundled as an ES module\nthe upload ships beside this one and imported through the runtime's JavaScript bridge. It runs\ncontracts' verifyScopeStoreCall (RFC scope-stores section 10.3, checks 1-4) against the script\nname and both audiences' public keys this upload was given. This module parses no envelope, so\nit cannot disagree with the JavaScript entry about one. The default entrypoint addresses\nSubstratStoreObject by idFromName of the signed name. The object checks the call again, and\nrefuses unless its own id is the id of that name (check 5), before the driver is constructed: an\nobject is bound to one name by construction, with nothing stored that the driver could rewrite.\n\nThe body stays in JavaScript (#2811). The verifier module reads it once, bounded by STORE_CALL_MAX_BYTES\n(a declared Content-Length over the limit is refused with 413 before the body is read, and a stream\nthat goes past it is refused at the limit), verifies it as the text those bytes decode to, and hands\nback the bytes as an ArrayBuffer. That buffer is what the default entrypoint forwards to the object\nand what the driver's Request is built over, so this module makes no Python string of the body: the\ndriver reads it as text only if it asks for text. The body used to be read twice and copied to Python\neach time, which failed with exceededMemory from about 6 MB.\nThe driver is constructed once per object instance with the object's ctx and an env with none of\nthe entry's SUBSTRAT_STORE* bindings. The upload sets disallow_importable_env and\ndisable_ctx_exports, and both apply to a Python script: `from workers import env` then reads an\nempty env, and ctx.exports is absent.\n\nWhat this is not: a boundary against a hostile driver, and it is weaker here than in JavaScript.\nPython has no private fields. The driver's module is imported by this one, before this module's\nbody has finished, and runs in the same interpreter: it can reach this module through\nsys.modules and replace its functions, and it can reach the entry's object, its full env and the\nstore namespace in it, through the garbage collector. The env strip and the cached driver keep a\ncareless driver away from the entry's bindings, not a hostile one. A driver written to interfere is\nstopped by the review of its release (D-63), not by this module.\n\"\"\"\n\nfrom workers import DurableObject, Request, Response, WorkerEntrypoint, import_from_javascript\nfrom js import Object\n\nfrom __SUBSTRAT_STORE_DRIVER__ import __SUBSTRAT_STORE_CLASS__ as StoreDriver\n\n# Each of these is a name in store-entry/names.ts; test/python-entry.test.ts holds them equal.\nVERIFIER_MODULE = \"./substrat-store-verify.js\"\nOBJECT_BINDING = \"SUBSTRAT_STORE\"\nRESERVED_BINDING_PREFIX = \"SUBSTRAT_STORE\"\n\n\ndef _raw_env(env):\n \"\"\"The JavaScript env the runtime handed over. The SDK wraps it, and has no public unwrap.\"\"\"\n return env._env\n\n\ndef _driver_env(env):\n \"\"\"The env the driver is constructed with: everything but the entry's own bindings.\"\"\"\n entries = [entry for entry in Object.entries(_raw_env(env)) if not str(entry[0]).startswith(RESERVED_BINDING_PREFIX)]\n return Object.fromEntries(entries)\n\n\ndef _refusal(verified):\n \"\"\"The response for a refused call: its status and its plain-text message.\"\"\"\n return Response(verified.message, status=verified.status)\n\n\nasync def _verified(request, env):\n \"\"\"The call read once and verified (its envelope and its body as a JavaScript ArrayBuffer), or the refusal.\"\"\"\n verifier = import_from_javascript(VERIFIER_MODULE)\n verified = await verifier.verifiedStoreCall(request.js_object, _raw_env(env))\n return verified if verified.ok else _refusal(verified)\n\n\ndef _driver_request(url, body):\n return Request(url, method=\"POST\", headers={\"content-type\": \"application/json\"}, body=body)\n\n\nclass SubstratStoreObject(DurableObject):\n def __init__(self, ctx, env):\n super().__init__(ctx, env)\n self._driver = None\n\n def _driver_object(self):\n \"\"\"Constructed once per object instance, on first use, so the driver keeps its in-memory state.\"\"\"\n if self._driver is None:\n self._driver = StoreDriver(self.ctx, _driver_env(self.env))\n return self._driver\n\n async def fetch(self, request):\n call = await _verified(request, self.env)\n if isinstance(call, Response):\n return call\n namespace = getattr(self.env, OBJECT_BINDING)\n if not self.ctx.id.equals(namespace.idFromName(call.envelope.name)):\n return Response(\"unauthorized: object\", status=401)\n return await self._driver_object().fetch(_driver_request(request.url, call.body))\n\n async def alarm(self, alarm_info=None):\n \"\"\"An alarm is the object's own timer, which only the driver sets. It goes to the driver.\"\"\"\n driver = self._driver_object()\n if hasattr(driver, \"alarm\"):\n await driver.alarm(alarm_info)\n\n\nclass Default(WorkerEntrypoint):\n async def fetch(self, request):\n call = await _verified(request, self.env)\n if isinstance(call, Response):\n return call\n namespace = getattr(self.env, OBJECT_BINDING)\n stub = namespace.get(namespace.idFromName(call.envelope.name))\n return await stub.fetch(request.url, method=\"POST\", headers=request.js_object.headers, body=call.body)\n";
|
|
56
|
+
export const STORE_ENTRY_PYTHON_SOURCE = "\"\"\"The platform's Python store entry (#2290), the twin of store-entry/entry.ts.\n\nUploaded as the store script's main module when the driver is Python. The driver's class is\nimported through the two placeholders below, which the upload replaces with the driver's module\nname and class name, as it does for the JavaScript entry. The driver is reached only through\nthis module, after the call is verified.\n\nThere is one verifier. Every call is checked by store-entry/verify.ts, bundled as an ES module\nthe upload ships beside this one and imported through the runtime's JavaScript bridge. It runs\ncontracts' verifyScopeStoreCall (RFC scope-stores section 10.3, checks 1-4) against the script\nname and both audiences' public keys this upload was given. This module parses no envelope, so\nit cannot disagree with the JavaScript entry about one. The default entrypoint addresses\nSubstratStoreObject by idFromName of the signed name. The object checks the call again, and\nrefuses unless its own id is the id of that name (check 5), before the driver is constructed: an\nobject is bound to one name by construction, with nothing stored that the driver could rewrite. It\nthen spends the envelope's nonce through the verifier's spendStoreNonce (K-59), so one envelope is\nadmitted once.\n\nThe body stays in JavaScript (#2811). The verifier module reads it once, bounded by STORE_CALL_MAX_BYTES\n(a declared Content-Length over the limit is refused with 413 before the body is read, and a stream\nthat goes past it is refused at the limit), verifies it as the text those bytes decode to, and hands\nback the bytes as an ArrayBuffer. That buffer is what the default entrypoint forwards to the object\nand what the driver's Request is built over, so this module makes no Python string of the body: the\ndriver reads it as text only if it asks for text. The body used to be read twice and copied to Python\neach time, which failed with exceededMemory from about 6 MB.\nThe driver is constructed once per object instance with the object's ctx and an env with none of\nthe entry's SUBSTRAT_STORE* bindings. The upload sets disallow_importable_env and\ndisable_ctx_exports, and both apply to a Python script: `from workers import env` then reads an\nempty env, and ctx.exports is absent.\n\nWhat this is not: a boundary against a hostile driver, and it is weaker here than in JavaScript.\nPython has no private fields. The driver's module is imported by this one, before this module's\nbody has finished, and runs in the same interpreter: it can reach this module through\nsys.modules and replace its functions, and it can reach the entry's object, its full env and the\nstore namespace in it, through the garbage collector. The env strip and the cached driver keep a\ncareless driver away from the entry's bindings, not a hostile one. A driver written to interfere is\nstopped by the review of its release (D-63), not by this module.\n\"\"\"\n\nfrom workers import DurableObject, Request, Response, WorkerEntrypoint, import_from_javascript\nfrom js import Date, Object\n\nfrom __SUBSTRAT_STORE_DRIVER__ import __SUBSTRAT_STORE_CLASS__ as StoreDriver\n\n# Each of these is a name in store-entry/names.ts; test/python-entry.test.ts holds them equal.\nVERIFIER_MODULE = \"./substrat-store-verify.js\"\nOBJECT_BINDING = \"SUBSTRAT_STORE\"\nRESERVED_BINDING_PREFIX = \"SUBSTRAT_STORE\"\n\n\ndef _raw_env(env):\n \"\"\"The JavaScript env the runtime handed over. The SDK wraps it, and has no public unwrap.\"\"\"\n return env._env\n\n\ndef _raw_storage(ctx):\n \"\"\"The object's JavaScript storage. The SDK wraps ctx and its storage, and has no public unwrap.\"\"\"\n return ctx._ctx.storage\n\n\ndef _driver_env(env):\n \"\"\"The env the driver is constructed with: everything but the entry's own bindings.\"\"\"\n entries = [entry for entry in Object.entries(_raw_env(env)) if not str(entry[0]).startswith(RESERVED_BINDING_PREFIX)]\n return Object.fromEntries(entries)\n\n\ndef _refusal(verified):\n \"\"\"The response for a refused call: its status and its plain-text message.\"\"\"\n return Response(verified.message, status=verified.status)\n\n\nasync def _verified(request, env):\n \"\"\"The call read once and verified (its envelope and its body as a JavaScript ArrayBuffer), or the refusal.\"\"\"\n verifier = import_from_javascript(VERIFIER_MODULE)\n verified = await verifier.verifiedStoreCall(request.js_object, _raw_env(env))\n return verified if verified.ok else _refusal(verified)\n\n\ndef _driver_request(url, body):\n return Request(url, method=\"POST\", headers={\"content-type\": \"application/json\"}, body=body)\n\n\nclass SubstratStoreObject(DurableObject):\n def __init__(self, ctx, env):\n super().__init__(ctx, env)\n self._driver = None\n\n def _driver_object(self):\n \"\"\"Constructed once per object instance, on first use, so the driver keeps its in-memory state.\"\"\"\n if self._driver is None:\n self._driver = StoreDriver(self.ctx, _driver_env(self.env))\n return self._driver\n\n async def fetch(self, request):\n call = await _verified(request, self.env)\n if isinstance(call, Response):\n return call\n namespace = getattr(self.env, OBJECT_BINDING)\n if not self.ctx.id.equals(namespace.idFromName(call.envelope.name)):\n return Response(\"unauthorized: object\", status=401)\n verifier = import_from_javascript(VERIFIER_MODULE)\n if not verifier.spendStoreNonce(_raw_storage(self.ctx), call.envelope, int(Date.now() // 1000)):\n return _refusal(verifier.spentNonce)\n return await self._driver_object().fetch(_driver_request(request.url, call.body))\n\n async def alarm(self, alarm_info=None):\n \"\"\"An alarm is the object's own timer, which only the driver sets. It goes to the driver.\"\"\"\n driver = self._driver_object()\n if hasattr(driver, \"alarm\"):\n await driver.alarm(alarm_info)\n\n\nclass Default(WorkerEntrypoint):\n async def fetch(self, request):\n call = await _verified(request, self.env)\n if isinstance(call, Response):\n return call\n namespace = getattr(self.env, OBJECT_BINDING)\n stub = namespace.get(namespace.idFromName(call.envelope.name))\n return await stub.fetch(request.url, method=\"POST\", headers=request.js_object.headers, body=call.body)\n";
|
|
57
57
|
/**
|
|
58
58
|
* The verifier the Python entry imports, uploaded beside it as `substrat-store-verify.js`
|
|
59
|
-
* (an ES module). It is `packages/control-plane-api/store-entry/verify.ts`, the check the JavaScript entry runs —
|
|
59
|
+
* (an ES module). It is `packages/control-plane-api/store-entry/verify.ts`, the check the JavaScript entry runs — 11756 bytes.
|
|
60
60
|
*/
|
|
61
|
-
export const STORE_ENTRY_PYTHON_VERIFIER_SOURCE = "// packages/contracts/dist/scope-store-envelope.js\nvar SCOPE_STORE_ENVELOPE_WINDOW_SECONDS = 60;\nvar SCOPE_STORE_ENVELOPE_HEADER = \"x-substrat-store-envelope\";\nvar SCOPE_STORE_SIGNATURE_HEADER = \"x-substrat-store-signature\";\nvar RESERVED_STORE_OPERATIONS = [\n \"substrat.export-page\",\n \"substrat.stage-page\",\n \"substrat.commit-stage\",\n \"substrat.discard-stage\",\n \"substrat.size\",\n \"substrat.wipe\",\n \"substrat.erase\",\n \"substrat.selfcheck\"\n];\nvar STORE_STAGE_MAX_AGE_MS = 6 * 36e5 + 3 * 30 * 6e4;\nvar STORE_CALL_MAX_BYTES = 4 * 1024 * 1024;\nvar STORE_DUMP_PAGE_MAX_BYTES = 3 * 1024 * 1024;\nvar ADMITTED = {\n \"1\": {\n platform: (op) => RESERVED_STORE_OPERATIONS.includes(op),\n caller: (op) => !op.startsWith(\"substrat.\")\n }\n};\nfunction scopeStoreEnvelopeAdmits(v, aud, op) {\n const byAudience = Object.hasOwn(ADMITTED, String(v)) ? ADMITTED[String(v)] : void 0;\n if (!byAudience || !Object.hasOwn(byAudience, aud))\n return false;\n return byAudience[aud](op);\n}\nfunction bytesToBase64Url(bytes) {\n let binary = \"\";\n for (const byte of bytes)\n binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\nfunction base64UrlToBytes(value) {\n if (!/^[A-Za-z0-9_-]+$/.test(value))\n return void 0;\n const padded = value.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\") + \"=\".repeat((4 - value.length % 4) % 4);\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return bytes;\n } catch {\n return void 0;\n }\n}\nfunction copyBytes(bytes) {\n const copy = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(copy).set(bytes);\n return copy;\n}\nfunction isCanonicalBase64Url(text, length) {\n const bytes = base64UrlToBytes(text);\n return bytes?.length === length && bytesToBase64Url(bytes) === text;\n}\nvar NONCE = /^[A-Za-z0-9_-]{22}$/;\nvar KID = /^[A-Za-z0-9_-]{11}$/;\nvar DIGEST = /^[0-9a-f]{64}$/;\nvar IAT = /^(0|[1-9]\\d{0,14})$/;\nfunction parseScopeStoreEnvelope(canonical) {\n const lines = canonical.split(\"\\n\");\n if (lines.length !== 9)\n return void 0;\n const [version, aud, kid, script, name, op, digest, iatText, nonce] = lines;\n if (version !== \"1\" || aud !== \"caller\" && aud !== \"platform\")\n return void 0;\n if (!script || !name || !op)\n return void 0;\n if (!KID.test(kid) || !DIGEST.test(digest) || !IAT.test(iatText) || !NONCE.test(nonce))\n return void 0;\n if (!isCanonicalBase64Url(kid, 8) || !isCanonicalBase64Url(nonce, 16))\n return void 0;\n return { v: 1, aud, kid, script, name, op, digest, iat: Number(iatText), nonce };\n}\nasync function scopeStoreBodyDigest(body) {\n const hash = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(body));\n return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\nfunction scopeStoreEnvelopeFresh(iat, nowSeconds, windowSeconds = SCOPE_STORE_ENVELOPE_WINDOW_SECONDS) {\n return Math.abs(nowSeconds - iat) <= windowSeconds;\n}\nvar SMALL_ORDER_KEYS = [\n \"0000000000000000000000000000000000000000000000000000000000000000\",\n // y = 0, order 4\n \"0100000000000000000000000000000000000000000000000000000000000000\",\n // the identity, order 1\n \"26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05\",\n // order 8\n \"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a\",\n // order 8\n \"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p - 1, order 2\n \"edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p, a non-canonical 0\n \"eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\"\n // y = p + 1, a non-canonical identity\n];\nfunction isSmallOrderKey(bytes) {\n const unsigned = Uint8Array.from(bytes);\n unsigned[31] = unsigned[31] & 127;\n const hex = [...unsigned].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return SMALL_ORDER_KEYS.includes(hex);\n}\nasync function scopeStoreKeyId(publicKey) {\n const bytes = base64UrlToBytes(publicKey);\n if (!bytes || bytes.length !== 32)\n throw new Error(\"a store public key is not 32 bytes of base64url\");\n if (isSmallOrderKey(bytes))\n throw new Error(\"a store public key is a small-order point\");\n const hash = await crypto.subtle.digest(\"SHA-256\", copyBytes(bytes));\n return bytesToBase64Url(new Uint8Array(hash).slice(0, 8));\n}\nfunction scopeStorePublicKeyProblem(key) {\n if (key.length === 0)\n return \"empty\";\n const bytes = base64UrlToBytes(key);\n if (bytes?.length !== 32)\n return \"length\";\n if (isSmallOrderKey(bytes))\n return \"small-order\";\n if (bytesToBase64Url(bytes) !== key)\n return \"non-canonical\";\n return void 0;\n}\nvar PUBLIC_KEY_PROBLEM = {\n empty: \"a store public key list is empty or has an empty entry\",\n length: \"a store public key is not 32 bytes of base64url\",\n \"small-order\": \"a store public key is a small-order point\",\n \"non-canonical\": \"a store public key is not canonical base64url\"\n};\nfunction parseScopeStorePublicKeys(text) {\n const keys = text.split(\",\").map((key) => key.trim());\n if (keys.some((key) => key.length === 0))\n throw new Error(PUBLIC_KEY_PROBLEM.empty);\n const seen = /* @__PURE__ */ new Set();\n for (const key of keys) {\n const problem = scopeStorePublicKeyProblem(key);\n if (problem)\n throw new Error(PUBLIC_KEY_PROBLEM[problem]);\n if (seen.has(key))\n throw new Error(\"a store public key is listed twice\");\n seen.add(key);\n }\n return keys;\n}\nfunction scopeStorePublicKeysFrom(config) {\n const caller = parseScopeStorePublicKeys(config.caller);\n const platform = parseScopeStorePublicKeys(config.platform);\n if (caller.some((key) => platform.includes(key))) {\n throw new Error(\"a store public key is listed for both audiences\");\n }\n return { caller, platform };\n}\nasync function verifyScopeStoreEnvelope(publicKey, canonical, signature) {\n const keyBytes = base64UrlToBytes(publicKey);\n const sigBytes = base64UrlToBytes(signature);\n if (!keyBytes || !sigBytes || sigBytes.length !== 64)\n return false;\n try {\n const key = await crypto.subtle.importKey(\"raw\", copyBytes(keyBytes), { name: \"Ed25519\" }, false, [\"verify\"]);\n return await crypto.subtle.verify(\"Ed25519\", key, copyBytes(sigBytes), new TextEncoder().encode(canonical));\n } catch {\n return false;\n }\n}\nasync function verifyScopeStoreCall(input) {\n const refuse = (refusal) => ({ ok: false, refusal });\n if (!input.envelope || !input.signature)\n return refuse(\"missing\");\n const bytes = base64UrlToBytes(input.envelope);\n if (!bytes)\n return refuse(\"malformed\");\n let canonical;\n try {\n canonical = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n } catch {\n return refuse(\"malformed\");\n }\n const envelope = parseScopeStoreEnvelope(canonical);\n if (!envelope)\n return refuse(\"malformed\");\n if (!scopeStoreEnvelopeAdmits(envelope.v, envelope.aud, envelope.op))\n return refuse(\"audience\");\n const kidsOf = async (keys) => {\n const kids = /* @__PURE__ */ new Map();\n for (const key of keys) {\n try {\n kids.set(await scopeStoreKeyId(key), key);\n } catch {\n }\n }\n return kids;\n };\n const own = await kidsOf(input.keys[envelope.aud]);\n const other = await kidsOf(input.keys[envelope.aud === \"caller\" ? \"platform\" : \"caller\"]);\n if ([...own.keys()].some((kid) => other.has(kid)))\n return refuse(\"keys\");\n const publicKey = own.get(envelope.kid);\n if (!publicKey)\n return refuse(\"kid\");\n if (!await verifyScopeStoreEnvelope(publicKey, canonical, input.signature))\n return refuse(\"signature\");\n if (envelope.digest !== await scopeStoreBodyDigest(input.body))\n return refuse(\"digest\");\n if (!scopeStoreEnvelopeFresh(envelope.iat, input.nowSeconds, input.windowSeconds))\n return refuse(\"stale\");\n if (envelope.script !== input.script)\n return refuse(\"script\");\n let parsed;\n try {\n parsed = JSON.parse(input.body);\n } catch {\n return refuse(\"body\");\n }\n const field = (key) => typeof parsed === \"object\" && parsed !== null ? Reflect.get(parsed, key) : void 0;\n if (field(\"operation\") !== envelope.op || field(\"objectName\") !== envelope.name)\n return refuse(\"body\");\n return { ok: true, envelope };\n}\n\n// packages/control-plane-api/store-entry/names.ts\nvar STORE_SCRIPT_VAR = \"SUBSTRAT_STORE_SCRIPT\";\nvar STORE_CALLER_KEYS_VAR = \"SUBSTRAT_STORE_CALLER_KEYS\";\nvar STORE_PLATFORM_KEYS_VAR = \"SUBSTRAT_STORE_PLATFORM_KEYS\";\n\n// packages/control-plane-api/store-entry/verify.ts\nvar tooLarge = { ok: false, status: 413, message: `payload too large: at most ${STORE_CALL_MAX_BYTES} bytes` };\nfunction storeCallDeclaredRefusal(headers) {\n const declared = headers.get(\"content-length\");\n return declared !== null && /^\\d+$/.test(declared.trim()) && Number(declared) > STORE_CALL_MAX_BYTES ? tooLarge : void 0;\n}\nasync function boundedBody(body) {\n if (!body) return new Uint8Array(0);\n const reader = body.getReader();\n const chunks = [];\n let total = 0;\n for (; ; ) {\n const { done, value } = await reader.read();\n if (done || !value) break;\n total += value.byteLength;\n if (total > STORE_CALL_MAX_BYTES) {\n await reader.cancel().catch(() => void 0);\n return tooLarge;\n }\n chunks.push(value);\n }\n const bytes = new Uint8Array(total);\n let at = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, at);\n at += chunk.byteLength;\n }\n return bytes;\n}\nasync function verifiedStoreCall(request, env) {\n const declared = storeCallDeclaredRefusal(request.headers);\n if (declared) return declared;\n const bytes = await boundedBody(request.body);\n if (!(bytes instanceof Uint8Array)) return bytes;\n let text;\n try {\n text = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(bytes);\n } catch {\n return { ok: false, status: 401, message: \"unauthorized: digest\" };\n }\n const verdict = await storeCallVerdict(request.headers, text, env);\n return verdict.ok ? { ok: true, envelope: verdict.envelope, body: bytes.buffer } : verdict;\n}\nasync function storeCallVerdict(headers, body, env) {\n const script = env[STORE_SCRIPT_VAR];\n let keys;\n try {\n if (typeof script !== \"string\" || script.length === 0) throw new Error(\"no script name\");\n keys = scopeStorePublicKeysFrom({\n caller: String(env[STORE_CALLER_KEYS_VAR] ?? \"\"),\n platform: String(env[STORE_PLATFORM_KEYS_VAR] ?? \"\")\n });\n } catch {\n return { ok: false, status: 503, message: \"this store script is not configured\" };\n }\n const verdict = await verifyScopeStoreCall({\n envelope: headers.get(SCOPE_STORE_ENVELOPE_HEADER),\n signature: headers.get(SCOPE_STORE_SIGNATURE_HEADER),\n body,\n keys,\n script,\n nowSeconds: Math.floor(Date.now() / 1e3)\n });\n return verdict.ok ? verdict : { ok: false, status: 401, message: `unauthorized: ${verdict.refusal}` };\n}\nexport {\n storeCallDeclaredRefusal,\n storeCallVerdict,\n verifiedStoreCall\n};\n";
|
|
61
|
+
export const STORE_ENTRY_PYTHON_VERIFIER_SOURCE = "// packages/contracts/dist/scope-store-envelope.js\nvar SCOPE_STORE_ENVELOPE_WINDOW_SECONDS = 60;\nvar SCOPE_STORE_ENVELOPE_HEADER = \"x-substrat-store-envelope\";\nvar SCOPE_STORE_SIGNATURE_HEADER = \"x-substrat-store-signature\";\nvar RESERVED_STORE_OPERATIONS = [\n \"substrat.export-page\",\n \"substrat.stage-page\",\n \"substrat.commit-stage\",\n \"substrat.discard-stage\",\n \"substrat.size\",\n \"substrat.wipe\",\n \"substrat.erase\",\n \"substrat.selfcheck\"\n];\nvar STORE_STAGE_MAX_AGE_MS = 6 * 36e5 + 3 * 30 * 6e4;\nvar STORE_CALL_MAX_BYTES = 4 * 1024 * 1024;\nvar STORE_DUMP_PAGE_MAX_BYTES = 3 * 1024 * 1024;\nvar ADMITTED = {\n \"1\": {\n platform: (op) => RESERVED_STORE_OPERATIONS.includes(op),\n caller: (op) => !op.startsWith(\"substrat.\")\n }\n};\nfunction scopeStoreEnvelopeAdmits(v, aud, op) {\n const byAudience = Object.hasOwn(ADMITTED, String(v)) ? ADMITTED[String(v)] : void 0;\n if (!byAudience || !Object.hasOwn(byAudience, aud))\n return false;\n return byAudience[aud](op);\n}\nfunction bytesToBase64Url(bytes) {\n let binary = \"\";\n for (const byte of bytes)\n binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\nfunction base64UrlToBytes(value) {\n if (!/^[A-Za-z0-9_-]+$/.test(value))\n return void 0;\n const padded = value.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\") + \"=\".repeat((4 - value.length % 4) % 4);\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return bytes;\n } catch {\n return void 0;\n }\n}\nfunction copyBytes(bytes) {\n const copy = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(copy).set(bytes);\n return copy;\n}\nfunction isCanonicalBase64Url(text, length) {\n const bytes = base64UrlToBytes(text);\n return bytes?.length === length && bytesToBase64Url(bytes) === text;\n}\nvar NONCE = /^[A-Za-z0-9_-]{22}$/;\nvar KID = /^[A-Za-z0-9_-]{11}$/;\nvar DIGEST = /^[0-9a-f]{64}$/;\nvar IAT = /^(0|[1-9]\\d{0,14})$/;\nfunction parseScopeStoreEnvelope(canonical) {\n const lines = canonical.split(\"\\n\");\n if (lines.length !== 9)\n return void 0;\n const [version, aud, kid, script, name, op, digest, iatText, nonce] = lines;\n if (version !== \"1\" || aud !== \"caller\" && aud !== \"platform\")\n return void 0;\n if (!script || !name || !op)\n return void 0;\n if (!KID.test(kid) || !DIGEST.test(digest) || !IAT.test(iatText) || !NONCE.test(nonce))\n return void 0;\n if (!isCanonicalBase64Url(kid, 8) || !isCanonicalBase64Url(nonce, 16))\n return void 0;\n return { v: 1, aud, kid, script, name, op, digest, iat: Number(iatText), nonce };\n}\nasync function scopeStoreBodyDigest(body) {\n const hash = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(body));\n return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\nfunction scopeStoreEnvelopeFresh(iat, nowSeconds, windowSeconds = SCOPE_STORE_ENVELOPE_WINDOW_SECONDS) {\n return Math.abs(nowSeconds - iat) <= windowSeconds;\n}\nvar SMALL_ORDER_KEYS = [\n \"0000000000000000000000000000000000000000000000000000000000000000\",\n // y = 0, order 4\n \"0100000000000000000000000000000000000000000000000000000000000000\",\n // the identity, order 1\n \"26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05\",\n // order 8\n \"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a\",\n // order 8\n \"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p - 1, order 2\n \"edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p, a non-canonical 0\n \"eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\"\n // y = p + 1, a non-canonical identity\n];\nfunction isSmallOrderKey(bytes) {\n const unsigned = Uint8Array.from(bytes);\n unsigned[31] = unsigned[31] & 127;\n const hex = [...unsigned].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return SMALL_ORDER_KEYS.includes(hex);\n}\nasync function scopeStoreKeyId(publicKey) {\n const bytes = base64UrlToBytes(publicKey);\n if (!bytes || bytes.length !== 32)\n throw new Error(\"a store public key is not 32 bytes of base64url\");\n if (isSmallOrderKey(bytes))\n throw new Error(\"a store public key is a small-order point\");\n const hash = await crypto.subtle.digest(\"SHA-256\", copyBytes(bytes));\n return bytesToBase64Url(new Uint8Array(hash).slice(0, 8));\n}\nfunction scopeStorePublicKeyProblem(key) {\n if (key.length === 0)\n return \"empty\";\n const bytes = base64UrlToBytes(key);\n if (bytes?.length !== 32)\n return \"length\";\n if (isSmallOrderKey(bytes))\n return \"small-order\";\n if (bytesToBase64Url(bytes) !== key)\n return \"non-canonical\";\n return void 0;\n}\nvar PUBLIC_KEY_PROBLEM = {\n empty: \"a store public key list is empty or has an empty entry\",\n length: \"a store public key is not 32 bytes of base64url\",\n \"small-order\": \"a store public key is a small-order point\",\n \"non-canonical\": \"a store public key is not canonical base64url\"\n};\nfunction parseScopeStorePublicKeys(text) {\n const keys = text.split(\",\").map((key) => key.trim());\n if (keys.some((key) => key.length === 0))\n throw new Error(PUBLIC_KEY_PROBLEM.empty);\n const seen = /* @__PURE__ */ new Set();\n for (const key of keys) {\n const problem = scopeStorePublicKeyProblem(key);\n if (problem)\n throw new Error(PUBLIC_KEY_PROBLEM[problem]);\n if (seen.has(key))\n throw new Error(\"a store public key is listed twice\");\n seen.add(key);\n }\n return keys;\n}\nfunction scopeStorePublicKeysFrom(config) {\n const caller = parseScopeStorePublicKeys(config.caller);\n const platform = parseScopeStorePublicKeys(config.platform);\n if (caller.some((key) => platform.includes(key))) {\n throw new Error(\"a store public key is listed for both audiences\");\n }\n return { caller, platform };\n}\nasync function verifyScopeStoreEnvelope(publicKey, canonical, signature) {\n const keyBytes = base64UrlToBytes(publicKey);\n const sigBytes = base64UrlToBytes(signature);\n if (!keyBytes || !sigBytes || sigBytes.length !== 64)\n return false;\n try {\n const key = await crypto.subtle.importKey(\"raw\", copyBytes(keyBytes), { name: \"Ed25519\" }, false, [\"verify\"]);\n return await crypto.subtle.verify(\"Ed25519\", key, copyBytes(sigBytes), new TextEncoder().encode(canonical));\n } catch {\n return false;\n }\n}\nasync function verifyScopeStoreCall(input) {\n const refuse = (refusal) => ({ ok: false, refusal });\n if (!input.envelope || !input.signature)\n return refuse(\"missing\");\n const bytes = base64UrlToBytes(input.envelope);\n if (!bytes)\n return refuse(\"malformed\");\n let canonical;\n try {\n canonical = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n } catch {\n return refuse(\"malformed\");\n }\n const envelope = parseScopeStoreEnvelope(canonical);\n if (!envelope)\n return refuse(\"malformed\");\n if (!scopeStoreEnvelopeAdmits(envelope.v, envelope.aud, envelope.op))\n return refuse(\"audience\");\n const kidsOf = async (keys) => {\n const kids = /* @__PURE__ */ new Map();\n for (const key of keys) {\n try {\n kids.set(await scopeStoreKeyId(key), key);\n } catch {\n }\n }\n return kids;\n };\n const own = await kidsOf(input.keys[envelope.aud]);\n const other = await kidsOf(input.keys[envelope.aud === \"caller\" ? \"platform\" : \"caller\"]);\n if ([...own.keys()].some((kid) => other.has(kid)))\n return refuse(\"keys\");\n const publicKey = own.get(envelope.kid);\n if (!publicKey)\n return refuse(\"kid\");\n if (!await verifyScopeStoreEnvelope(publicKey, canonical, input.signature))\n return refuse(\"signature\");\n if (envelope.digest !== await scopeStoreBodyDigest(input.body))\n return refuse(\"digest\");\n if (!scopeStoreEnvelopeFresh(envelope.iat, input.nowSeconds, input.windowSeconds))\n return refuse(\"stale\");\n if (envelope.script !== input.script)\n return refuse(\"script\");\n let parsed;\n try {\n parsed = JSON.parse(input.body);\n } catch {\n return refuse(\"body\");\n }\n const field = (key) => typeof parsed === \"object\" && parsed !== null ? Reflect.get(parsed, key) : void 0;\n if (field(\"operation\") !== envelope.op || field(\"objectName\") !== envelope.name)\n return refuse(\"body\");\n return { ok: true, envelope };\n}\n\n// packages/control-plane-api/store-entry/names.ts\nvar STORE_SCRIPT_VAR = \"SUBSTRAT_STORE_SCRIPT\";\nvar STORE_CALLER_KEYS_VAR = \"SUBSTRAT_STORE_CALLER_KEYS\";\nvar STORE_PLATFORM_KEYS_VAR = \"SUBSTRAT_STORE_PLATFORM_KEYS\";\n\n// packages/control-plane-api/store-entry/verify.ts\nvar tooLarge = { ok: false, status: 413, message: `payload too large: at most ${STORE_CALL_MAX_BYTES} bytes` };\nfunction storeCallDeclaredRefusal(headers) {\n const declared = headers.get(\"content-length\");\n return declared !== null && /^\\d+$/.test(declared.trim()) && Number(declared) > STORE_CALL_MAX_BYTES ? tooLarge : void 0;\n}\nasync function boundedBody(body) {\n if (!body) return new Uint8Array(0);\n const reader = body.getReader();\n const chunks = [];\n let total = 0;\n for (; ; ) {\n const { done, value } = await reader.read();\n if (done || !value) break;\n total += value.byteLength;\n if (total > STORE_CALL_MAX_BYTES) {\n await reader.cancel().catch(() => void 0);\n return tooLarge;\n }\n chunks.push(value);\n }\n const bytes = new Uint8Array(total);\n let at = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, at);\n at += chunk.byteLength;\n }\n return bytes;\n}\nasync function verifiedStoreCall(request, env) {\n const declared = storeCallDeclaredRefusal(request.headers);\n if (declared) return declared;\n const bytes = await boundedBody(request.body);\n if (!(bytes instanceof Uint8Array)) return bytes;\n let text;\n try {\n text = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(bytes);\n } catch {\n return { ok: false, status: 401, message: \"unauthorized: digest\" };\n }\n const verdict = await storeCallVerdict(request.headers, text, env);\n return verdict.ok ? { ok: true, envelope: verdict.envelope, body: bytes.buffer } : verdict;\n}\nvar STORE_NONCE_KEY_PREFIX = \"substrat.store-nonce/\";\nvar STORE_NONCE_PRUNE_BATCH = 64;\nvar nonceKey = (iat) => `${STORE_NONCE_KEY_PREFIX}${String(iat).padStart(15, \"0\")}/`;\nfunction spendStoreNonce(storage, envelope, nowSeconds) {\n const { kv } = storage;\n const expired = nonceKey(nowSeconds - SCOPE_STORE_ENVELOPE_WINDOW_SECONDS);\n for (const [key2] of kv.list({ prefix: STORE_NONCE_KEY_PREFIX, end: expired, limit: STORE_NONCE_PRUNE_BATCH })) kv.delete(key2);\n if (!scopeStoreEnvelopeFresh(envelope.iat, nowSeconds)) return false;\n const key = `${nonceKey(envelope.iat)}${envelope.nonce}`;\n if (kv.get(key) !== void 0) return false;\n kv.put(key, 1);\n return true;\n}\nvar spentNonce = { ok: false, status: 401, message: \"unauthorized: nonce\" };\nasync function storeCallVerdict(headers, body, env) {\n const script = env[STORE_SCRIPT_VAR];\n let keys;\n try {\n if (typeof script !== \"string\" || script.length === 0) throw new Error(\"no script name\");\n keys = scopeStorePublicKeysFrom({\n caller: String(env[STORE_CALLER_KEYS_VAR] ?? \"\"),\n platform: String(env[STORE_PLATFORM_KEYS_VAR] ?? \"\")\n });\n } catch {\n return { ok: false, status: 503, message: \"this store script is not configured\" };\n }\n const verdict = await verifyScopeStoreCall({\n envelope: headers.get(SCOPE_STORE_ENVELOPE_HEADER),\n signature: headers.get(SCOPE_STORE_SIGNATURE_HEADER),\n body,\n keys,\n script,\n nowSeconds: Math.floor(Date.now() / 1e3)\n });\n return verdict.ok ? verdict : { ok: false, status: 401, message: `unauthorized: ${verdict.refusal}` };\n}\nexport {\n spendStoreNonce,\n spentNonce,\n storeCallDeclaredRefusal,\n storeCallVerdict,\n verifiedStoreCall\n};\n";
|
|
62
62
|
//# sourceMappingURL=store-entry.generated.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-entry.generated.js","sourceRoot":"","sources":["../src/store-entry.generated.ts"],"names":[],"mappings":"AAAA,oOAAoO;AACpO,mEAAmE;AAEnE;;;;;GAKG;AAEH,oFAAoF;AACpF,MAAM,CAAC,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAElE,2FAA2F;AAC3F,MAAM,CAAC,MAAM,uBAAuB,GAAG,0BAA0B,CAAC;AAElE,+EAA+E;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,2BAA2B,CAAC;AAEpE,4GAA4G;AAC5G,MAAM,CAAC,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;AAE5D;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAEnE,wDAAwD;AACxD,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAErD,gGAAgG;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;AAExD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,uBAAuB,GAAG,8BAA8B,CAAC;AAEtE;;;GAGG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,YAAY,CAAC;AAE5D,6GAA6G;AAC7G,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAEnE;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,gBAAgB,CAAC;AAE9D,mGAAmG;AACnG,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,yBAAyB,EAAC,yBAAyB,EAAC,0BAA0B,CAAC,CAAC;AAEvH,8FAA8F;AAC9F,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,0BAA0B,CAAC;AAEhE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAW,
|
|
1
|
+
{"version":3,"file":"store-entry.generated.js","sourceRoot":"","sources":["../src/store-entry.generated.ts"],"names":[],"mappings":"AAAA,oOAAoO;AACpO,mEAAmE;AAEnE;;;;;GAKG;AAEH,oFAAoF;AACpF,MAAM,CAAC,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAElE,2FAA2F;AAC3F,MAAM,CAAC,MAAM,uBAAuB,GAAG,0BAA0B,CAAC;AAElE,+EAA+E;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,2BAA2B,CAAC;AAEpE,4GAA4G;AAC5G,MAAM,CAAC,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;AAE5D;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAEnE,wDAAwD;AACxD,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAErD,gGAAgG;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;AAExD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,uBAAuB,GAAG,8BAA8B,CAAC;AAEtE;;;GAGG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,YAAY,CAAC;AAE5D,6GAA6G;AAC7G,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAEnE;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,gBAAgB,CAAC;AAE9D,mGAAmG;AACnG,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,yBAAyB,EAAC,yBAAyB,EAAC,0BAA0B,CAAC,CAAC;AAEvH,8FAA8F;AAC9F,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,0BAA0B,CAAC;AAEhE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAW,upcAAupc,CAAC;AAElsc;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAW,60MAA60M,CAAC;AAE/3M;;;GAGG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAW,u+XAAu+X,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type ScopeDumpPageTable, type ScopeDumpTable } from '@substrat-run/contracts';
|
|
2
|
+
import { ControlPlaneError } from '@substrat-run/control-plane-client';
|
|
3
|
+
import type { ScopeBackupWriter } from './backups.js';
|
|
4
|
+
import type { DeclaredScopeStore, PlatformScopeStores } from './platform-scope-stores.js';
|
|
5
|
+
import { type MovedStore, type StorePlanEnds } from './store-move.js';
|
|
6
|
+
/** Where a scope's stores are: the store of each binding is one object of this scope. */
|
|
7
|
+
export interface StorePlace {
|
|
8
|
+
tenantId: string;
|
|
9
|
+
scopeId: string;
|
|
10
|
+
vertical: string;
|
|
11
|
+
}
|
|
12
|
+
/** A snapshot's ends: the source's store, page by page, into a stage at the fork's. */
|
|
13
|
+
export declare const snapshotEnds: (caller: PlatformScopeStores, from: StorePlace, to: StorePlace) => StorePlanEnds;
|
|
14
|
+
/** A backup's ends: the store's chain into `store-page` entries of the backup being written, under the move's id. */
|
|
15
|
+
export declare const backupEnds: (caller: PlatformScopeStores, place: StorePlace, writer: ScopeBackupWriter) => StorePlanEnds;
|
|
16
|
+
/** A store's pages as a restore reads them: a backup's `store-page` entries, or an inline dump cut into pages. */
|
|
17
|
+
export interface StoreSource {
|
|
18
|
+
pages: number;
|
|
19
|
+
revision: string;
|
|
20
|
+
page(seq: number): Promise<ScopeDumpPageTable[]>;
|
|
21
|
+
}
|
|
22
|
+
/** One store a restore loads: its binding, its driver, and where its pages come from. */
|
|
23
|
+
export interface RestoreStore extends DeclaredScopeStore {
|
|
24
|
+
source: StoreSource;
|
|
25
|
+
}
|
|
26
|
+
/** An inline store (an older backup's, or an uploaded dump's) as a source: cut at its driver's page size. */
|
|
27
|
+
export declare const inlineStoreSource: (store: {
|
|
28
|
+
driver: string;
|
|
29
|
+
tables: readonly ScopeDumpTable[];
|
|
30
|
+
}) => StoreSource;
|
|
31
|
+
/**
|
|
32
|
+
* A restore's ends: each store's source into a stage at the destination. A page that cannot be read
|
|
33
|
+
* or parsed refuses before any commit, so the store stays as it was.
|
|
34
|
+
*/
|
|
35
|
+
export declare const restoreEnds: (caller: PlatformScopeStores, to: StorePlace, sourceOf: (binding: string) => StoreSource) => StorePlanEnds;
|
|
36
|
+
/**
|
|
37
|
+
* A store's landing that failed once a commit was attempted: which bindings were committed, and
|
|
38
|
+
* which were not. The commit of `failed` may have run with its answer lost, so the store under it is
|
|
39
|
+
* either. The route replays erasures even so, since a store replaced by an old copy holds subjects
|
|
40
|
+
* erased since, and running the restore again converges: every commit is a whole replace.
|
|
41
|
+
*/
|
|
42
|
+
export declare class StoreLandFailure extends ControlPlaneError {
|
|
43
|
+
readonly committed: readonly string[];
|
|
44
|
+
readonly uncommitted: readonly string[];
|
|
45
|
+
constructor(cause: unknown, committed: readonly string[], uncommitted: readonly string[]);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Commit each moved store's stage, comparing each count with what was sent. The contract makes a
|
|
49
|
+
* commit asked again answer the same count and change nothing, so a transient fault is retried. Any
|
|
50
|
+
* failure throws a `StoreLandFailure`, and the stages not committed are discarded, best effort.
|
|
51
|
+
*/
|
|
52
|
+
export declare function commitStages(caller: PlatformScopeStores, place: StorePlace, moved: readonly MovedStore[], retry: <T>(run: () => Promise<T>) => Promise<T>): Promise<string[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Whether a store holds any row, read at the smallest page the contract allows and stopped at the
|
|
55
|
+
* first row, so a store of any size costs one call to answer yes. A write during the scan cannot make
|
|
56
|
+
* this wrong for the caller: it asks about a binding no running version writes.
|
|
57
|
+
*/
|
|
58
|
+
export declare function storeHoldsRows(caller: PlatformScopeStores, place: StorePlace, store: DeclaredScopeStore): Promise<boolean>;
|
|
59
|
+
//# sourceMappingURL=store-move-ends.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-move-ends.d.ts","sourceRoot":"","sources":["../src/store-move-ends.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEjH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EAAwB,KAAK,UAAU,EAAqB,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE/G,yFAAyF;AACzF,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoBD,uFAAuF;AACvF,eAAO,MAAM,YAAY,WAAY,mBAAmB,QAAQ,UAAU,MAAM,UAAU,KAAG,aAG3F,CAAC;AAEH,qHAAqH;AACrH,eAAO,MAAM,UAAU,WAAY,mBAAmB,SAAS,UAAU,UAAU,iBAAiB,KAAG,aAIrG,CAAC;AAEH,kHAAkH;AAClH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;CAClD;AAED,yFAAyF;AACzF,MAAM,WAAW,YAAa,SAAQ,kBAAkB;IACtD,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,6GAA6G;AAC7G,eAAO,MAAM,iBAAiB,UAAW;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAA;CAAE,KAAG,WAGhG,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,WAAY,mBAAmB,MAAM,UAAU,YAAY,CAAC,OAAO,EAAE,MAAM,KAAK,WAAW,KAAG,aAUnH,CAAC;AAEJ;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,iBAAiB;IAGnD,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE;IACrC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE;IAHzC,YACE,KAAK,EAAE,OAAO,EACL,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,WAAW,EAAE,SAAS,MAAM,EAAE,EAQxC;CACF;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,KAAK,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9C,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBnB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAchI"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { storeDriverDumpPageBytes } from '@substrat-run/contracts';
|
|
2
|
+
import { storeDumpPages } from '@substrat-run/kernel';
|
|
3
|
+
import { ControlPlaneError } from '@substrat-run/control-plane-client';
|
|
4
|
+
import { STORE_MOVE_MAX_PAGES } from './store-move.js';
|
|
5
|
+
const callAt = (caller, place, store) => caller.callStore({ ...place, ...store });
|
|
6
|
+
/** A store's chain as a move reads it: the driver's declared page size, nothing else asked. */
|
|
7
|
+
const chainRead = (call, driver) => (cursor) => call('substrat.export-page', { cursor, maxBytes: storeDriverDumpPageBytes(driver) });
|
|
8
|
+
/** A store's stage as a move writes it. Each page goes once under a fresh id, so `staged: false` is the driver's fault. */
|
|
9
|
+
const stageEnds = (call, binding) => ({
|
|
10
|
+
write: async (moveId, seq, tables) => {
|
|
11
|
+
const { staged } = await call('substrat.stage-page', { stageId: moveId, seq, tables });
|
|
12
|
+
if (!staged)
|
|
13
|
+
throw new ControlPlaneError(502, `scope store '${binding}' held page ${seq} of a stage it was only just given`);
|
|
14
|
+
},
|
|
15
|
+
discard: async (moveId) => {
|
|
16
|
+
await call('substrat.discard-stage', { stageId: moveId });
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
/** A snapshot's ends: the source's store, page by page, into a stage at the fork's. */
|
|
20
|
+
export const snapshotEnds = (caller, from, to) => (store) => ({
|
|
21
|
+
read: chainRead(callAt(caller, from, store), store.driver),
|
|
22
|
+
...stageEnds(callAt(caller, to, store), store.binding),
|
|
23
|
+
});
|
|
24
|
+
/** A backup's ends: the store's chain into `store-page` entries of the backup being written, under the move's id. */
|
|
25
|
+
export const backupEnds = (caller, place, writer) => (store) => ({
|
|
26
|
+
read: chainRead(callAt(caller, place, store), store.driver),
|
|
27
|
+
write: (moveId, seq, tables) => writer.put(moveId, seq, { kind: 'store-page', tables }),
|
|
28
|
+
discard: (moveId) => writer.discard(moveId),
|
|
29
|
+
});
|
|
30
|
+
/** An inline store (an older backup's, or an uploaded dump's) as a source: cut at its driver's page size. */
|
|
31
|
+
export const inlineStoreSource = (store) => {
|
|
32
|
+
const pages = storeDumpPages(store.tables, storeDriverDumpPageBytes(store.driver));
|
|
33
|
+
return { pages: pages.length, revision: 'inline', page: async (seq) => pages[seq] };
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* A restore's ends: each store's source into a stage at the destination. A page that cannot be read
|
|
37
|
+
* or parsed refuses before any commit, so the store stays as it was.
|
|
38
|
+
*/
|
|
39
|
+
export const restoreEnds = (caller, to, sourceOf) => (store) => {
|
|
40
|
+
const source = sourceOf(store.binding);
|
|
41
|
+
return {
|
|
42
|
+
read: async (cursor) => {
|
|
43
|
+
const seq = cursor === null ? 0 : Number(cursor);
|
|
44
|
+
return { tables: await source.page(seq), next: seq + 1 < source.pages ? String(seq + 1) : null, revision: source.revision };
|
|
45
|
+
},
|
|
46
|
+
...stageEnds(callAt(caller, to, store), store.binding),
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* A store's landing that failed once a commit was attempted: which bindings were committed, and
|
|
51
|
+
* which were not. The commit of `failed` may have run with its answer lost, so the store under it is
|
|
52
|
+
* either. The route replays erasures even so, since a store replaced by an old copy holds subjects
|
|
53
|
+
* erased since, and running the restore again converges: every commit is a whole replace.
|
|
54
|
+
*/
|
|
55
|
+
export class StoreLandFailure extends ControlPlaneError {
|
|
56
|
+
committed;
|
|
57
|
+
uncommitted;
|
|
58
|
+
constructor(cause, committed, uncommitted) {
|
|
59
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
60
|
+
super(cause instanceof ControlPlaneError ? cause.status : 502, `${message}. The scope's stores were committed in part: ${committed.length ? committed.join(', ') : 'none'} committed, ` +
|
|
61
|
+
`${uncommitted.join(', ')} not known to be; restore again to finish`);
|
|
62
|
+
this.committed = committed;
|
|
63
|
+
this.uncommitted = uncommitted;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Commit each moved store's stage, comparing each count with what was sent. The contract makes a
|
|
68
|
+
* commit asked again answer the same count and change nothing, so a transient fault is retried. Any
|
|
69
|
+
* failure throws a `StoreLandFailure`, and the stages not committed are discarded, best effort.
|
|
70
|
+
*/
|
|
71
|
+
export async function commitStages(caller, place, moved, retry) {
|
|
72
|
+
const committed = [];
|
|
73
|
+
for (const [at, store] of moved.entries()) {
|
|
74
|
+
const call = callAt(caller, place, store);
|
|
75
|
+
try {
|
|
76
|
+
const answer = await retry(() => call('substrat.commit-stage', { stageId: store.moveId }));
|
|
77
|
+
if (answer.tables !== store.tables) {
|
|
78
|
+
throw new ControlPlaneError(502, `scope store '${store.binding}' committed ${answer.tables} tables of the ${store.tables} it was sent`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
const rest = moved.slice(at);
|
|
83
|
+
for (const left of rest.slice(1))
|
|
84
|
+
await callAt(caller, place, left)('substrat.discard-stage', { stageId: left.moveId }).catch(() => undefined);
|
|
85
|
+
throw new StoreLandFailure(e, committed, rest.map((s) => s.binding));
|
|
86
|
+
}
|
|
87
|
+
committed.push(store.binding);
|
|
88
|
+
}
|
|
89
|
+
return committed;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Whether a store holds any row, read at the smallest page the contract allows and stopped at the
|
|
93
|
+
* first row, so a store of any size costs one call to answer yes. A write during the scan cannot make
|
|
94
|
+
* this wrong for the caller: it asks about a binding no running version writes.
|
|
95
|
+
*/
|
|
96
|
+
export async function storeHoldsRows(caller, place, store) {
|
|
97
|
+
const call = callAt(caller, place, store);
|
|
98
|
+
const asked = new Set();
|
|
99
|
+
let cursor = null;
|
|
100
|
+
for (let pages = 1;; pages += 1) {
|
|
101
|
+
const page = await call('substrat.export-page', { cursor, maxBytes: 1 });
|
|
102
|
+
if (page.tables.some((table) => table.rows.length > 0))
|
|
103
|
+
return true;
|
|
104
|
+
if (page.next === null)
|
|
105
|
+
return false;
|
|
106
|
+
if (cursor !== null)
|
|
107
|
+
asked.add(cursor);
|
|
108
|
+
if (asked.has(page.next) || page.next === cursor || pages >= STORE_MOVE_MAX_PAGES) {
|
|
109
|
+
throw new ControlPlaneError(502, `scope store '${store.binding}' answered a chain that does not end`);
|
|
110
|
+
}
|
|
111
|
+
cursor = page.next;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=store-move-ends.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-move-ends.js","sourceRoot":"","sources":["../src/store-move-ends.ts"],"names":[],"mappings":"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"}
|