@substrat-run/contracts 0.146.0 → 0.148.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/assistant-stream.d.ts +311 -0
- package/dist/assistant-stream.d.ts.map +1 -0
- package/dist/assistant-stream.js +360 -0
- package/dist/assistant-stream.js.map +1 -0
- package/dist/attachments.d.ts +153 -0
- package/dist/attachments.d.ts.map +1 -1
- package/dist/attachments.js +115 -1
- package/dist/attachments.js.map +1 -1
- package/dist/control-plane.d.ts +88 -2
- package/dist/control-plane.d.ts.map +1 -1
- package/dist/control-plane.js +74 -7
- package/dist/control-plane.js.map +1 -1
- package/dist/deploy.d.ts +304 -0
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +339 -1
- package/dist/deploy.js.map +1 -1
- package/dist/errors.d.ts +49 -14
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +82 -7
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/introspection.d.ts +29 -1
- package/dist/introspection.d.ts.map +1 -1
- package/dist/introspection.js +11 -0
- package/dist/introspection.js.map +1 -1
- package/dist/kernel-events.d.ts.map +1 -1
- package/dist/kernel-events.js +4 -1
- package/dist/kernel-events.js.map +1 -1
- package/dist/lake.d.ts +109 -0
- package/dist/lake.d.ts.map +1 -0
- package/dist/lake.js +85 -0
- package/dist/lake.js.map +1 -0
- package/dist/manifest.d.ts +4 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +5 -0
- package/dist/manifest.js.map +1 -1
- package/dist/model.d.ts +4 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js.map +1 -1
- package/dist/routing.d.ts +4 -0
- package/dist/routing.d.ts.map +1 -1
- package/dist/routing.js +7 -0
- package/dist/routing.js.map +1 -1
- package/dist/scope-store-envelope.d.ts +167 -0
- package/dist/scope-store-envelope.d.ts.map +1 -0
- package/dist/scope-store-envelope.js +390 -0
- package/dist/scope-store-envelope.js.map +1 -0
- package/dist/scope-store-transport.d.ts +47 -0
- package/dist/scope-store-transport.d.ts.map +1 -0
- package/dist/scope-store-transport.js +58 -0
- package/dist/scope-store-transport.js.map +1 -0
- package/dist/script-names.d.ts +36 -1
- package/dist/script-names.d.ts.map +1 -1
- package/dist/script-names.js +53 -1
- package/dist/script-names.js.map +1 -1
- package/dist/sql-in-list.d.ts +39 -0
- package/dist/sql-in-list.d.ts.map +1 -0
- package/dist/sql-in-list.js +10 -0
- package/dist/sql-in-list.js.map +1 -0
- package/dist/tenancy.d.ts +1 -1
- package/dist/tenancy.d.ts.map +1 -1
- package/dist/tenancy.js +10 -1
- package/dist/tenancy.js.map +1 -1
- package/package.json +9 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signed envelope a scope-store call carries (#2287, RFC scope-stores §10.3).
|
|
3
|
+
*
|
|
4
|
+
* Ed25519 over a canonical encoding of every field the store acts on. The router signs
|
|
5
|
+
* audience `caller` and the control plane signs audience `platform`, each with its own
|
|
6
|
+
* private key. A store script holds only public keys, a list per audience, so a key can be
|
|
7
|
+
* rotated without a moment where no key verifies. The encoding is nine lines joined by
|
|
8
|
+
* `\n`, with no trailing newline, so a verifier in another language can rebuild it:
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* 1
|
|
12
|
+
* caller|platform
|
|
13
|
+
* <kid: base64url of the first 8 bytes of SHA-256 over the raw public key>
|
|
14
|
+
* <store script name>
|
|
15
|
+
* <object name>
|
|
16
|
+
* <operation>
|
|
17
|
+
* <sha256 hex of the exact request body>
|
|
18
|
+
* <iat, unix seconds>
|
|
19
|
+
* <nonce, base64url of 16 bytes>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* The signature is base64url over those exact UTF-8 bytes. An envelope is fresh for
|
|
23
|
+
* {@link SCOPE_STORE_ENVELOPE_WINDOW_SECONDS} on either side of the verifier's clock. A
|
|
24
|
+
* store does not remember nonces (RFC Q2): an envelope replayed inside the window, at the
|
|
25
|
+
* same script and object with the same body, is accepted again. The reserved operations are
|
|
26
|
+
* idempotent, and a kind operation's retry safety is the vertical's.
|
|
27
|
+
*
|
|
28
|
+
* The script line is an opaque string compared for equality: the signer builds it, the
|
|
29
|
+
* verifier is told its own. Nothing here parses it.
|
|
30
|
+
*
|
|
31
|
+
* This module imports nothing, so a store entry can load it as one file.
|
|
32
|
+
*/
|
|
33
|
+
export declare const SCOPE_STORE_ENVELOPE_VERSION = 1;
|
|
34
|
+
export declare const SCOPE_STORE_ENVELOPE_WINDOW_SECONDS = 60;
|
|
35
|
+
/** The request header carrying base64url of the canonical bytes. */
|
|
36
|
+
export declare const SCOPE_STORE_ENVELOPE_HEADER = "x-substrat-store-envelope";
|
|
37
|
+
/** The request header carrying the base64url signature. */
|
|
38
|
+
export declare const SCOPE_STORE_SIGNATURE_HEADER = "x-substrat-store-signature";
|
|
39
|
+
/**
|
|
40
|
+
* The operations only the platform may send to a scope store (#2207). A vertical's
|
|
41
|
+
* stub refuses every one of them. A kind's registration has to answer all of them,
|
|
42
|
+
* `substrat.erase` included, before a hosted deploy may store tenant data.
|
|
43
|
+
*/
|
|
44
|
+
export declare const RESERVED_STORE_OPERATIONS: readonly ['substrat.export', 'substrat.import', 'substrat.size', 'substrat.wipe', 'substrat.erase'];
|
|
45
|
+
export type ReservedStoreOperation = (typeof RESERVED_STORE_OPERATIONS)[number];
|
|
46
|
+
export type ScopeStoreAudience = 'caller' | 'platform';
|
|
47
|
+
export interface ScopeStoreEnvelope {
|
|
48
|
+
readonly v: 1;
|
|
49
|
+
readonly aud: ScopeStoreAudience;
|
|
50
|
+
readonly kid: string;
|
|
51
|
+
readonly script: string;
|
|
52
|
+
readonly name: string;
|
|
53
|
+
readonly op: string;
|
|
54
|
+
readonly digest: string;
|
|
55
|
+
readonly iat: number;
|
|
56
|
+
readonly nonce: string;
|
|
57
|
+
}
|
|
58
|
+
/** Whether this version admits `op` from `aud`. */
|
|
59
|
+
export declare function scopeStoreEnvelopeAdmits(v: number, aud: string, op: string): boolean;
|
|
60
|
+
export declare function bytesToBase64Url(bytes: Uint8Array): string;
|
|
61
|
+
export declare function base64UrlToBytes(value: string): Uint8Array | undefined;
|
|
62
|
+
/** Nine lines, no trailing newline. Throws on a field the parser would refuse. */
|
|
63
|
+
export declare function canonicalScopeStoreEnvelope(envelope: ScopeStoreEnvelope): string;
|
|
64
|
+
/** The envelope those bytes name, or undefined when they are not exactly what the encoder emits. */
|
|
65
|
+
export declare function parseScopeStoreEnvelope(canonical: string): ScopeStoreEnvelope | undefined;
|
|
66
|
+
/** SHA-256 of the exact request body, lowercase hex. */
|
|
67
|
+
export declare function scopeStoreBodyDigest(body: string): Promise<string>;
|
|
68
|
+
/** Whether `iat` is inside the freshness window of `nowSeconds`. */
|
|
69
|
+
export declare function scopeStoreEnvelopeFresh(iat: number, nowSeconds: number, windowSeconds?: number): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* The key id of a raw Ed25519 public key (base64url): base64url of SHA-256's first 8 bytes.
|
|
72
|
+
* Throws on a key that is not 32 bytes or encodes a small-order point, so a verifier given one
|
|
73
|
+
* never matches it.
|
|
74
|
+
*/
|
|
75
|
+
export declare function scopeStoreKeyId(publicKey: string): Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* A store's public keys for one audience, as configured: raw Ed25519 keys, base64url,
|
|
78
|
+
* separated by commas (whitespace around each is ignored). Throws on an empty list, a key
|
|
79
|
+
* that is not 32 bytes, a small-order point, a key not in canonical base64url (its unused trailing bits set, so
|
|
80
|
+
* two spellings would name one key), or the same key twice. Rotation is: add the new key,
|
|
81
|
+
* switch the signer, then drop the old key.
|
|
82
|
+
*/
|
|
83
|
+
export declare function parseScopeStorePublicKeys(text: string): readonly string[];
|
|
84
|
+
/**
|
|
85
|
+
* Both audiences' public keys, from their configured lists. Throws on anything
|
|
86
|
+
* {@link parseScopeStorePublicKeys} refuses, and on a key listed for both audiences: whoever
|
|
87
|
+
* holds the `caller` private key could then sign `platform` envelopes, `substrat.erase`
|
|
88
|
+
* included (L16). A store builds its keys only through this.
|
|
89
|
+
*/
|
|
90
|
+
export declare function scopeStorePublicKeysFrom(config: {
|
|
91
|
+
readonly caller: string;
|
|
92
|
+
readonly platform: string;
|
|
93
|
+
}): ScopeStorePublicKeys;
|
|
94
|
+
/**
|
|
95
|
+
* A fresh Ed25519 pair in the shapes this module takes: the PKCS8 private key a signer holds
|
|
96
|
+
* and the raw public key a store lists, both base64url, with the key id the envelope names.
|
|
97
|
+
*/
|
|
98
|
+
export declare function generateScopeStoreKeyPair(): Promise<{
|
|
99
|
+
readonly privateKey: string;
|
|
100
|
+
readonly publicKey: string;
|
|
101
|
+
readonly kid: string;
|
|
102
|
+
}>;
|
|
103
|
+
/** A signing key that is present but cannot be used. Its message never carries the key. */
|
|
104
|
+
export declare class ScopeStoreKeyError extends Error {
|
|
105
|
+
readonly name = "ScopeStoreKeyError";
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Whether `signature` is the Ed25519 signature of `canonical` under the raw public key.
|
|
109
|
+
* A malformed key or signature is false.
|
|
110
|
+
*/
|
|
111
|
+
export declare function verifyScopeStoreEnvelope(publicKey: string, canonical: string, signature: string): Promise<boolean>;
|
|
112
|
+
export interface IssuedScopeStoreEnvelope {
|
|
113
|
+
readonly envelope: ScopeStoreEnvelope;
|
|
114
|
+
readonly canonical: string;
|
|
115
|
+
/** base64url of the canonical UTF-8 bytes. {@link SCOPE_STORE_ENVELOPE_HEADER} carries it. */
|
|
116
|
+
readonly header: string;
|
|
117
|
+
/** {@link SCOPE_STORE_SIGNATURE_HEADER} carries it. */
|
|
118
|
+
readonly signature: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Build, digest and sign one envelope. `iat` and `nonce` default to now and 16 random bytes.
|
|
122
|
+
* Throws {@link ScopeStoreKeyError} when the key is unusable, and an Error when a field is.
|
|
123
|
+
*/
|
|
124
|
+
export declare function issueScopeStoreEnvelope(input: {
|
|
125
|
+
readonly privateKey: string;
|
|
126
|
+
readonly aud: ScopeStoreAudience;
|
|
127
|
+
readonly script: string;
|
|
128
|
+
readonly name: string;
|
|
129
|
+
readonly op: string;
|
|
130
|
+
readonly body: string;
|
|
131
|
+
readonly iat?: number;
|
|
132
|
+
readonly nonce?: string;
|
|
133
|
+
}): Promise<IssuedScopeStoreEnvelope>;
|
|
134
|
+
/** The public keys a store verifies with, per audience. */
|
|
135
|
+
export interface ScopeStorePublicKeys {
|
|
136
|
+
readonly caller: readonly string[];
|
|
137
|
+
readonly platform: readonly string[];
|
|
138
|
+
}
|
|
139
|
+
/** Why a call was refused. A store answers every one of them the same way, 401. */
|
|
140
|
+
export type ScopeStoreRefusal = 'missing' | 'malformed' | 'audience' | 'kid' | 'signature' | 'digest' | 'stale' | 'script' | 'body' | 'keys';
|
|
141
|
+
export type ScopeStoreCallVerdict = {
|
|
142
|
+
readonly ok: true;
|
|
143
|
+
readonly envelope: ScopeStoreEnvelope;
|
|
144
|
+
} | {
|
|
145
|
+
readonly ok: false;
|
|
146
|
+
readonly refusal: ScopeStoreRefusal;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Every envelope check a store makes on a call before the kind's class runs (RFC §10.3
|
|
150
|
+
* checks 1–4, L4, L5), in one place, so a store entry carries no copy. The object binding
|
|
151
|
+
* (check 5: the object's id is `idFromName` of the signed name) is the entry's, because it
|
|
152
|
+
* needs the object's id; so is reading the configured keys and script name.
|
|
153
|
+
*
|
|
154
|
+
* `script` is the store script's own name, compared with the signed line for equality.
|
|
155
|
+
* The body must be JSON naming the signed operation as `operation` and the signed object
|
|
156
|
+
* as `objectName`, so the signed name is the one the kind is asked about.
|
|
157
|
+
*/
|
|
158
|
+
export declare function verifyScopeStoreCall(input: {
|
|
159
|
+
readonly envelope: string | null | undefined;
|
|
160
|
+
readonly signature: string | null | undefined;
|
|
161
|
+
readonly body: string;
|
|
162
|
+
readonly keys: ScopeStorePublicKeys;
|
|
163
|
+
readonly script: string;
|
|
164
|
+
readonly nowSeconds: number;
|
|
165
|
+
readonly windowSeconds?: number;
|
|
166
|
+
}): Promise<ScopeStoreCallVerdict>;
|
|
167
|
+
//# sourceMappingURL=scope-store-envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-store-envelope.d.ts","sourceRoot":"","sources":["../src/scope-store-envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,mCAAmC,KAAK,CAAC;AACtD,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,8BAA8B,CAAC;AACvE,2DAA2D;AAC3D,eAAO,MAAM,4BAA4B,+BAA+B,CAAC;AAEzE;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,YACpC,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,gBAAgB,CACR,CAAC;AACX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IACd,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAcD,mDAAmD;AACnD,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAIpF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAI1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAWtE;AAwBD,kFAAkF;AAClF,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAoBhF;AAED,oGAAoG;AACpG,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAazF;AAED,wDAAwD;AACxD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGxE;AAED,oEAAoE;AACpE,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,aAAa,SAAsC,GAClD,OAAO,CAET;AA0BD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMxE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAgBzE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,oBAAoB,CAO7H;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC;IACzD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC,CAKD;AAwBD,2FAA2F;AAC3F,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,SAAkB,IAAI,wBAAwB;CAC/C;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE;IACnD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAwBpC;AAED,2DAA2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,mFAAmF;AACnF,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,WAAW,GACX,UAAU,GACV,KAAK,GACL,WAAW,GACX,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,MAAM,GACN,MAAM,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAC7B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAEhE;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE;IAChD,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA6CjC"}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signed envelope a scope-store call carries (#2287, RFC scope-stores §10.3).
|
|
3
|
+
*
|
|
4
|
+
* Ed25519 over a canonical encoding of every field the store acts on. The router signs
|
|
5
|
+
* audience `caller` and the control plane signs audience `platform`, each with its own
|
|
6
|
+
* private key. A store script holds only public keys, a list per audience, so a key can be
|
|
7
|
+
* rotated without a moment where no key verifies. The encoding is nine lines joined by
|
|
8
|
+
* `\n`, with no trailing newline, so a verifier in another language can rebuild it:
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* 1
|
|
12
|
+
* caller|platform
|
|
13
|
+
* <kid: base64url of the first 8 bytes of SHA-256 over the raw public key>
|
|
14
|
+
* <store script name>
|
|
15
|
+
* <object name>
|
|
16
|
+
* <operation>
|
|
17
|
+
* <sha256 hex of the exact request body>
|
|
18
|
+
* <iat, unix seconds>
|
|
19
|
+
* <nonce, base64url of 16 bytes>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* The signature is base64url over those exact UTF-8 bytes. An envelope is fresh for
|
|
23
|
+
* {@link SCOPE_STORE_ENVELOPE_WINDOW_SECONDS} on either side of the verifier's clock. A
|
|
24
|
+
* store does not remember nonces (RFC Q2): an envelope replayed inside the window, at the
|
|
25
|
+
* same script and object with the same body, is accepted again. The reserved operations are
|
|
26
|
+
* idempotent, and a kind operation's retry safety is the vertical's.
|
|
27
|
+
*
|
|
28
|
+
* The script line is an opaque string compared for equality: the signer builds it, the
|
|
29
|
+
* verifier is told its own. Nothing here parses it.
|
|
30
|
+
*
|
|
31
|
+
* This module imports nothing, so a store entry can load it as one file.
|
|
32
|
+
*/
|
|
33
|
+
export const SCOPE_STORE_ENVELOPE_VERSION = 1;
|
|
34
|
+
export const SCOPE_STORE_ENVELOPE_WINDOW_SECONDS = 60;
|
|
35
|
+
/** The request header carrying base64url of the canonical bytes. */
|
|
36
|
+
export const SCOPE_STORE_ENVELOPE_HEADER = 'x-substrat-store-envelope';
|
|
37
|
+
/** The request header carrying the base64url signature. */
|
|
38
|
+
export const SCOPE_STORE_SIGNATURE_HEADER = 'x-substrat-store-signature';
|
|
39
|
+
/**
|
|
40
|
+
* The operations only the platform may send to a scope store (#2207). A vertical's
|
|
41
|
+
* stub refuses every one of them. A kind's registration has to answer all of them,
|
|
42
|
+
* `substrat.erase` included, before a hosted deploy may store tenant data.
|
|
43
|
+
*/
|
|
44
|
+
export const RESERVED_STORE_OPERATIONS = [
|
|
45
|
+
'substrat.export',
|
|
46
|
+
'substrat.import',
|
|
47
|
+
'substrat.size',
|
|
48
|
+
'substrat.wipe',
|
|
49
|
+
'substrat.erase',
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* Which operations each (version, audience) admits. Closed: a pair not in this table is
|
|
53
|
+
* refused. `platform` sends exactly the reserved operations, and `caller` sends anything
|
|
54
|
+
* else, never a `substrat.*` name.
|
|
55
|
+
*/
|
|
56
|
+
const ADMITTED = {
|
|
57
|
+
'1': {
|
|
58
|
+
platform: (op) => RESERVED_STORE_OPERATIONS.includes(op),
|
|
59
|
+
caller: (op) => !op.startsWith('substrat.'),
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
/** Whether this version admits `op` from `aud`. */
|
|
63
|
+
export function scopeStoreEnvelopeAdmits(v, aud, op) {
|
|
64
|
+
const byAudience = Object.hasOwn(ADMITTED, String(v)) ? ADMITTED[String(v)] : undefined;
|
|
65
|
+
if (!byAudience || !Object.hasOwn(byAudience, aud))
|
|
66
|
+
return false;
|
|
67
|
+
return byAudience[aud](op);
|
|
68
|
+
}
|
|
69
|
+
export function bytesToBase64Url(bytes) {
|
|
70
|
+
let binary = '';
|
|
71
|
+
for (const byte of bytes)
|
|
72
|
+
binary += String.fromCharCode(byte);
|
|
73
|
+
return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '');
|
|
74
|
+
}
|
|
75
|
+
export function base64UrlToBytes(value) {
|
|
76
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value))
|
|
77
|
+
return undefined;
|
|
78
|
+
const padded = value.replaceAll('-', '+').replaceAll('_', '/') + '='.repeat((4 - (value.length % 4)) % 4);
|
|
79
|
+
try {
|
|
80
|
+
const binary = atob(padded);
|
|
81
|
+
const bytes = new Uint8Array(binary.length);
|
|
82
|
+
for (let i = 0; i < binary.length; i++)
|
|
83
|
+
bytes[i] = binary.charCodeAt(i);
|
|
84
|
+
return bytes;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function copyBytes(bytes) {
|
|
91
|
+
const copy = new ArrayBuffer(bytes.byteLength);
|
|
92
|
+
new Uint8Array(copy).set(bytes);
|
|
93
|
+
return copy;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Whether `text` is the canonical base64url of exactly `length` bytes: it decodes to that many
|
|
97
|
+
* bytes and re-encodes to the same text, so its unused trailing bits are zero and no second
|
|
98
|
+
* spelling names the same value.
|
|
99
|
+
*/
|
|
100
|
+
function isCanonicalBase64Url(text, length) {
|
|
101
|
+
const bytes = base64UrlToBytes(text);
|
|
102
|
+
return bytes?.length === length && bytesToBase64Url(bytes) === text;
|
|
103
|
+
}
|
|
104
|
+
const NONCE = /^[A-Za-z0-9_-]{22}$/;
|
|
105
|
+
const KID = /^[A-Za-z0-9_-]{11}$/;
|
|
106
|
+
const DIGEST = /^[0-9a-f]{64}$/;
|
|
107
|
+
// At most 15 digits, so every value it admits is a safe integer, as the encoder requires.
|
|
108
|
+
const IAT = /^(0|[1-9]\d{0,14})$/;
|
|
109
|
+
/** Nine lines, no trailing newline. Throws on a field the parser would refuse. */
|
|
110
|
+
export function canonicalScopeStoreEnvelope(envelope) {
|
|
111
|
+
if (envelope.v !== SCOPE_STORE_ENVELOPE_VERSION)
|
|
112
|
+
throw new Error(`unknown store envelope version ${envelope.v}`);
|
|
113
|
+
for (const field of [envelope.aud, envelope.kid, envelope.script, envelope.name, envelope.op, envelope.digest, envelope.nonce]) {
|
|
114
|
+
if (field.length === 0)
|
|
115
|
+
throw new Error('a store envelope field is empty');
|
|
116
|
+
if (field.includes('\n'))
|
|
117
|
+
throw new Error('a store envelope field contains a newline');
|
|
118
|
+
}
|
|
119
|
+
if (!Number.isSafeInteger(envelope.iat) || envelope.iat < 0)
|
|
120
|
+
throw new Error('a store envelope iat is not a non-negative integer');
|
|
121
|
+
const canonical = [
|
|
122
|
+
String(envelope.v),
|
|
123
|
+
envelope.aud,
|
|
124
|
+
envelope.kid,
|
|
125
|
+
envelope.script,
|
|
126
|
+
envelope.name,
|
|
127
|
+
envelope.op,
|
|
128
|
+
envelope.digest,
|
|
129
|
+
String(envelope.iat),
|
|
130
|
+
envelope.nonce,
|
|
131
|
+
].join('\n');
|
|
132
|
+
if (!parseScopeStoreEnvelope(canonical))
|
|
133
|
+
throw new Error('a store envelope field is malformed');
|
|
134
|
+
return canonical;
|
|
135
|
+
}
|
|
136
|
+
/** The envelope those bytes name, or undefined when they are not exactly what the encoder emits. */
|
|
137
|
+
export function parseScopeStoreEnvelope(canonical) {
|
|
138
|
+
const lines = canonical.split('\n');
|
|
139
|
+
if (lines.length !== 9)
|
|
140
|
+
return undefined;
|
|
141
|
+
const [version, aud, kid, script, name, op, digest, iatText, nonce] = lines;
|
|
142
|
+
if (version !== '1' || (aud !== 'caller' && aud !== 'platform'))
|
|
143
|
+
return undefined;
|
|
144
|
+
if (!script || !name || !op)
|
|
145
|
+
return undefined;
|
|
146
|
+
if (!KID.test(kid) || !DIGEST.test(digest) || !IAT.test(iatText) || !NONCE.test(nonce))
|
|
147
|
+
return undefined;
|
|
148
|
+
// The kid is 8 bytes and the nonce 16, each in canonical base64url. IAT's grammar already
|
|
149
|
+
// admits only the decimal text `String(n)` gives for a safe integer n: no sign, no leading zero.
|
|
150
|
+
if (!isCanonicalBase64Url(kid, 8) || !isCanonicalBase64Url(nonce, 16))
|
|
151
|
+
return undefined;
|
|
152
|
+
return { v: 1, aud, kid, script, name, op, digest, iat: Number(iatText), nonce };
|
|
153
|
+
}
|
|
154
|
+
/** SHA-256 of the exact request body, lowercase hex. */
|
|
155
|
+
export async function scopeStoreBodyDigest(body) {
|
|
156
|
+
const hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(body));
|
|
157
|
+
return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
158
|
+
}
|
|
159
|
+
/** Whether `iat` is inside the freshness window of `nowSeconds`. */
|
|
160
|
+
export function scopeStoreEnvelopeFresh(iat, nowSeconds, windowSeconds = SCOPE_STORE_ENVELOPE_WINDOW_SECONDS) {
|
|
161
|
+
return Math.abs(nowSeconds - iat) <= windowSeconds;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The encodings of Ed25519's eight small-order points, with the sign bit (the top bit of the
|
|
165
|
+
* last byte) cleared, including the non-canonical encodings p and p+1 of y: the list libsodium
|
|
166
|
+
* refuses. Under such a key a forged signature verifies for many messages (with the identity,
|
|
167
|
+
* R = identity and S = 0 verifies for any message under some verifiers), so no store accepts one.
|
|
168
|
+
*/
|
|
169
|
+
const SMALL_ORDER_KEYS = [
|
|
170
|
+
'0000000000000000000000000000000000000000000000000000000000000000', // y = 0, order 4
|
|
171
|
+
'0100000000000000000000000000000000000000000000000000000000000000', // the identity, order 1
|
|
172
|
+
'26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', // order 8
|
|
173
|
+
'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', // order 8
|
|
174
|
+
'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', // y = p - 1, order 2
|
|
175
|
+
'edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', // y = p, a non-canonical 0
|
|
176
|
+
'eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', // y = p + 1, a non-canonical identity
|
|
177
|
+
];
|
|
178
|
+
/** Whether 32 key bytes encode a small-order point, in either sign. */
|
|
179
|
+
function isSmallOrderKey(bytes) {
|
|
180
|
+
const unsigned = Uint8Array.from(bytes);
|
|
181
|
+
unsigned[31] = unsigned[31] & 0x7f;
|
|
182
|
+
const hex = [...unsigned].map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
183
|
+
return SMALL_ORDER_KEYS.includes(hex);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The key id of a raw Ed25519 public key (base64url): base64url of SHA-256's first 8 bytes.
|
|
187
|
+
* Throws on a key that is not 32 bytes or encodes a small-order point, so a verifier given one
|
|
188
|
+
* never matches it.
|
|
189
|
+
*/
|
|
190
|
+
export async function scopeStoreKeyId(publicKey) {
|
|
191
|
+
const bytes = base64UrlToBytes(publicKey);
|
|
192
|
+
if (!bytes || bytes.length !== 32)
|
|
193
|
+
throw new Error('a store public key is not 32 bytes of base64url');
|
|
194
|
+
if (isSmallOrderKey(bytes))
|
|
195
|
+
throw new Error('a store public key is a small-order point');
|
|
196
|
+
const hash = await crypto.subtle.digest('SHA-256', copyBytes(bytes));
|
|
197
|
+
return bytesToBase64Url(new Uint8Array(hash).slice(0, 8));
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* A store's public keys for one audience, as configured: raw Ed25519 keys, base64url,
|
|
201
|
+
* separated by commas (whitespace around each is ignored). Throws on an empty list, a key
|
|
202
|
+
* that is not 32 bytes, a small-order point, a key not in canonical base64url (its unused trailing bits set, so
|
|
203
|
+
* two spellings would name one key), or the same key twice. Rotation is: add the new key,
|
|
204
|
+
* switch the signer, then drop the old key.
|
|
205
|
+
*/
|
|
206
|
+
export function parseScopeStorePublicKeys(text) {
|
|
207
|
+
const keys = text.split(',').map((key) => key.trim());
|
|
208
|
+
if (keys.length === 0 || keys.some((key) => key.length === 0)) {
|
|
209
|
+
throw new Error('a store public key list is empty or has an empty entry');
|
|
210
|
+
}
|
|
211
|
+
const seen = new Set();
|
|
212
|
+
for (const key of keys) {
|
|
213
|
+
const bytes = base64UrlToBytes(key);
|
|
214
|
+
if (bytes?.length !== 32)
|
|
215
|
+
throw new Error('a store public key is not 32 bytes of base64url');
|
|
216
|
+
if (isSmallOrderKey(bytes))
|
|
217
|
+
throw new Error('a store public key is a small-order point');
|
|
218
|
+
// Canonical means the bytes re-encode to the same text, so equal text is equal bytes.
|
|
219
|
+
if (bytesToBase64Url(bytes) !== key)
|
|
220
|
+
throw new Error('a store public key is not canonical base64url');
|
|
221
|
+
if (seen.has(key))
|
|
222
|
+
throw new Error('a store public key is listed twice');
|
|
223
|
+
seen.add(key);
|
|
224
|
+
}
|
|
225
|
+
return keys;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Both audiences' public keys, from their configured lists. Throws on anything
|
|
229
|
+
* {@link parseScopeStorePublicKeys} refuses, and on a key listed for both audiences: whoever
|
|
230
|
+
* holds the `caller` private key could then sign `platform` envelopes, `substrat.erase`
|
|
231
|
+
* included (L16). A store builds its keys only through this.
|
|
232
|
+
*/
|
|
233
|
+
export function scopeStorePublicKeysFrom(config) {
|
|
234
|
+
const caller = parseScopeStorePublicKeys(config.caller);
|
|
235
|
+
const platform = parseScopeStorePublicKeys(config.platform);
|
|
236
|
+
if (caller.some((key) => platform.includes(key))) {
|
|
237
|
+
throw new Error('a store public key is listed for both audiences');
|
|
238
|
+
}
|
|
239
|
+
return { caller, platform };
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* A fresh Ed25519 pair in the shapes this module takes: the PKCS8 private key a signer holds
|
|
243
|
+
* and the raw public key a store lists, both base64url, with the key id the envelope names.
|
|
244
|
+
*/
|
|
245
|
+
export async function generateScopeStoreKeyPair() {
|
|
246
|
+
const pair = (await crypto.subtle.generateKey({ name: 'Ed25519' }, true, ['sign', 'verify']));
|
|
247
|
+
const privateKey = bytesToBase64Url(new Uint8Array((await crypto.subtle.exportKey('pkcs8', pair.privateKey))));
|
|
248
|
+
const publicKey = bytesToBase64Url(new Uint8Array((await crypto.subtle.exportKey('raw', pair.publicKey))));
|
|
249
|
+
return { privateKey, publicKey, kid: await scopeStoreKeyId(publicKey) };
|
|
250
|
+
}
|
|
251
|
+
/** Import a PKCS8 Ed25519 private key (base64url) and derive its key id from its public half. */
|
|
252
|
+
async function signingKey(pkcs8) {
|
|
253
|
+
const bytes = base64UrlToBytes(pkcs8);
|
|
254
|
+
if (!bytes)
|
|
255
|
+
throw new ScopeStoreKeyError('the store signing key is not base64url');
|
|
256
|
+
let jwk;
|
|
257
|
+
let key;
|
|
258
|
+
try {
|
|
259
|
+
// Extractable only so its public half (`x`) can be read for the key id; it never leaves here.
|
|
260
|
+
key = await crypto.subtle.importKey('pkcs8', copyBytes(bytes), { name: 'Ed25519' }, true, ['sign']);
|
|
261
|
+
jwk = (await crypto.subtle.exportKey('jwk', key));
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
throw new ScopeStoreKeyError('the store signing key is not an Ed25519 PKCS8 key');
|
|
265
|
+
}
|
|
266
|
+
if (typeof jwk.x !== 'string')
|
|
267
|
+
throw new ScopeStoreKeyError('the store signing key has no public half');
|
|
268
|
+
return { key, kid: await scopeStoreKeyId(jwk.x) };
|
|
269
|
+
}
|
|
270
|
+
/** A signing key that is present but cannot be used. Its message never carries the key. */
|
|
271
|
+
export class ScopeStoreKeyError extends Error {
|
|
272
|
+
name = 'ScopeStoreKeyError';
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Whether `signature` is the Ed25519 signature of `canonical` under the raw public key.
|
|
276
|
+
* A malformed key or signature is false.
|
|
277
|
+
*/
|
|
278
|
+
export async function verifyScopeStoreEnvelope(publicKey, canonical, signature) {
|
|
279
|
+
const keyBytes = base64UrlToBytes(publicKey);
|
|
280
|
+
const sigBytes = base64UrlToBytes(signature);
|
|
281
|
+
if (!keyBytes || !sigBytes || sigBytes.length !== 64)
|
|
282
|
+
return false;
|
|
283
|
+
try {
|
|
284
|
+
const key = await crypto.subtle.importKey('raw', copyBytes(keyBytes), { name: 'Ed25519' }, false, ['verify']);
|
|
285
|
+
return await crypto.subtle.verify('Ed25519', key, copyBytes(sigBytes), new TextEncoder().encode(canonical));
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Build, digest and sign one envelope. `iat` and `nonce` default to now and 16 random bytes.
|
|
293
|
+
* Throws {@link ScopeStoreKeyError} when the key is unusable, and an Error when a field is.
|
|
294
|
+
*/
|
|
295
|
+
export async function issueScopeStoreEnvelope(input) {
|
|
296
|
+
const signer = await signingKey(input.privateKey);
|
|
297
|
+
const envelope = {
|
|
298
|
+
v: 1,
|
|
299
|
+
aud: input.aud,
|
|
300
|
+
kid: signer.kid,
|
|
301
|
+
script: input.script,
|
|
302
|
+
name: input.name,
|
|
303
|
+
op: input.op,
|
|
304
|
+
digest: await scopeStoreBodyDigest(input.body),
|
|
305
|
+
iat: input.iat ?? Math.floor(Date.now() / 1000),
|
|
306
|
+
nonce: input.nonce ?? bytesToBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
307
|
+
};
|
|
308
|
+
if (!scopeStoreEnvelopeAdmits(envelope.v, envelope.aud, envelope.op)) {
|
|
309
|
+
throw new Error(`audience '${envelope.aud}' does not send '${envelope.op}'`);
|
|
310
|
+
}
|
|
311
|
+
const canonical = canonicalScopeStoreEnvelope(envelope);
|
|
312
|
+
const signature = await crypto.subtle.sign('Ed25519', signer.key, new TextEncoder().encode(canonical));
|
|
313
|
+
return {
|
|
314
|
+
envelope,
|
|
315
|
+
canonical,
|
|
316
|
+
header: bytesToBase64Url(new TextEncoder().encode(canonical)),
|
|
317
|
+
signature: bytesToBase64Url(new Uint8Array(signature)),
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Every envelope check a store makes on a call before the kind's class runs (RFC §10.3
|
|
322
|
+
* checks 1–4, L4, L5), in one place, so a store entry carries no copy. The object binding
|
|
323
|
+
* (check 5: the object's id is `idFromName` of the signed name) is the entry's, because it
|
|
324
|
+
* needs the object's id; so is reading the configured keys and script name.
|
|
325
|
+
*
|
|
326
|
+
* `script` is the store script's own name, compared with the signed line for equality.
|
|
327
|
+
* The body must be JSON naming the signed operation as `operation` and the signed object
|
|
328
|
+
* as `objectName`, so the signed name is the one the kind is asked about.
|
|
329
|
+
*/
|
|
330
|
+
export async function verifyScopeStoreCall(input) {
|
|
331
|
+
const refuse = (refusal) => ({ ok: false, refusal });
|
|
332
|
+
if (!input.envelope || !input.signature)
|
|
333
|
+
return refuse('missing');
|
|
334
|
+
const bytes = base64UrlToBytes(input.envelope);
|
|
335
|
+
if (!bytes)
|
|
336
|
+
return refuse('malformed');
|
|
337
|
+
let canonical;
|
|
338
|
+
try {
|
|
339
|
+
canonical = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
return refuse('malformed');
|
|
343
|
+
}
|
|
344
|
+
const envelope = parseScopeStoreEnvelope(canonical);
|
|
345
|
+
if (!envelope)
|
|
346
|
+
return refuse('malformed');
|
|
347
|
+
if (!scopeStoreEnvelopeAdmits(envelope.v, envelope.aud, envelope.op))
|
|
348
|
+
return refuse('audience');
|
|
349
|
+
// Key ids are over the decoded bytes, so two spellings of one key share an id. A key the
|
|
350
|
+
// other audience also lists refuses every call: its holder could sign for either (L16).
|
|
351
|
+
const kidsOf = async (keys) => {
|
|
352
|
+
const kids = new Map();
|
|
353
|
+
for (const key of keys) {
|
|
354
|
+
try {
|
|
355
|
+
kids.set(await scopeStoreKeyId(key), key);
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
// A malformed listed key verifies nothing.
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return kids;
|
|
362
|
+
};
|
|
363
|
+
const own = await kidsOf(input.keys[envelope.aud]);
|
|
364
|
+
const other = await kidsOf(input.keys[envelope.aud === 'caller' ? 'platform' : 'caller']);
|
|
365
|
+
if ([...own.keys()].some((kid) => other.has(kid)))
|
|
366
|
+
return refuse('keys');
|
|
367
|
+
const publicKey = own.get(envelope.kid);
|
|
368
|
+
if (!publicKey)
|
|
369
|
+
return refuse('kid');
|
|
370
|
+
if (!(await verifyScopeStoreEnvelope(publicKey, canonical, input.signature)))
|
|
371
|
+
return refuse('signature');
|
|
372
|
+
if (envelope.digest !== (await scopeStoreBodyDigest(input.body)))
|
|
373
|
+
return refuse('digest');
|
|
374
|
+
if (!scopeStoreEnvelopeFresh(envelope.iat, input.nowSeconds, input.windowSeconds))
|
|
375
|
+
return refuse('stale');
|
|
376
|
+
if (envelope.script !== input.script)
|
|
377
|
+
return refuse('script');
|
|
378
|
+
let parsed;
|
|
379
|
+
try {
|
|
380
|
+
parsed = JSON.parse(input.body);
|
|
381
|
+
}
|
|
382
|
+
catch {
|
|
383
|
+
return refuse('body');
|
|
384
|
+
}
|
|
385
|
+
const field = (key) => (typeof parsed === 'object' && parsed !== null ? Reflect.get(parsed, key) : undefined);
|
|
386
|
+
if (field('operation') !== envelope.op || field('objectName') !== envelope.name)
|
|
387
|
+
return refuse('body');
|
|
388
|
+
return { ok: true, envelope };
|
|
389
|
+
}
|
|
390
|
+
//# sourceMappingURL=scope-store-envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-store-envelope.js","sourceRoot":"","sources":["../src/scope-store-envelope.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* The hosted transport for a scope-store call (#2207).
|
|
4
|
+
*
|
|
5
|
+
* A vertical fetches `store.substrat.internal`. It names a binding, an operation
|
|
6
|
+
* and an input. It does not name a script, an object or a key: the egress worker
|
|
7
|
+
* hands the call to the router with the dispatch parameters the router set, and
|
|
8
|
+
* the router is what signs the envelope and addresses the store script.
|
|
9
|
+
* `*.substrat.internal` is in no DNS zone, so a call from inside a Durable Object
|
|
10
|
+
* — which an outbound worker does not see — fails instead of leaving the isolate.
|
|
11
|
+
*/
|
|
12
|
+
/** The one reserved host a scope-store call is addressed to. */
|
|
13
|
+
export declare const STORE_CALL_HOST = "store.substrat.internal";
|
|
14
|
+
/** The address a platform-transport `getScopeStore` fetches. The caller does not build it. */
|
|
15
|
+
export declare const STORE_CALL_URL = "https://store.substrat.internal/invoke";
|
|
16
|
+
/** An exact host match. A suffix would admit a name the platform does not own. */
|
|
17
|
+
export declare const isStoreCallHost: (hostname: string) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* What the vertical puts in the body. The scope it may name is the one the
|
|
20
|
+
* router dispatched it for; the router refuses any other. Strict, so a body
|
|
21
|
+
* that tries to carry a signature or a script name is not a request.
|
|
22
|
+
*/
|
|
23
|
+
export declare const storeCallRequest: z.ZodObject<{
|
|
24
|
+
scopeId: z.core.$ZodBranded<z.ZodString, "ScopeId", "out">;
|
|
25
|
+
binding: z.ZodString;
|
|
26
|
+
operation: z.ZodString;
|
|
27
|
+
input: z.ZodOptional<z.ZodUnknown>;
|
|
28
|
+
}, z.core.$strict>;
|
|
29
|
+
export type StoreCallRequest = z.infer<typeof storeCallRequest>;
|
|
30
|
+
/** Who the signature was made for. A reserved operation accepts only the platform's. */
|
|
31
|
+
export declare const storeCallAudience: z.ZodEnum<{
|
|
32
|
+
caller: "caller";
|
|
33
|
+
platform: "platform";
|
|
34
|
+
}>;
|
|
35
|
+
export type StoreCallAudience = z.infer<typeof storeCallAudience>;
|
|
36
|
+
/** A `substrat.*` operation is the platform's. A caller signature does not open it. */
|
|
37
|
+
export declare function storeAudienceAllows(operation: string, audience: StoreCallAudience): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The name an object keeps.
|
|
40
|
+
*
|
|
41
|
+
* The first accepted name is stored. A later call whose name differs is not
|
|
42
|
+
* this object's call, even when the signature over that other name is valid.
|
|
43
|
+
* That is the check that stops a signature for one tenant's object being
|
|
44
|
+
* presented to another's.
|
|
45
|
+
*/
|
|
46
|
+
export declare function rememberStoreObjectName(remembered: string | null, presented: string): string | undefined;
|
|
47
|
+
//# sourceMappingURL=scope-store-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-store-transport.d.ts","sourceRoot":"","sources":["../src/scope-store-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;GASG;AAEH,gEAAgE;AAChE,eAAO,MAAM,eAAe,4BAA4B,CAAC;AAEzD,8FAA8F;AAC9F,eAAO,MAAM,cAAc,2CAAsC,CAAC;AAElE,kFAAkF;AAClF,eAAO,MAAM,eAAe,aAAc,MAAM,KAAG,OACP,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;;kBAQlB,CAAC;AACZ,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,wFAAwF;AACxF,eAAO,MAAM,iBAAiB;;;EAAiC,CAAC;AAChE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAIlE,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAG3F;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIxG"}
|