@serve.zone/interfaces 11.0.0 ā 11.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +17 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/index.d.ts +2 -0
- package/dist_ts/data/index.js +3 -1
- package/dist_ts/data/isolatedrestore.d.ts +315 -0
- package/dist_ts/data/isolatedrestore.golden.d.ts +18 -0
- package/dist_ts/data/isolatedrestore.golden.js +131 -0
- package/dist_ts/data/isolatedrestore.js +1325 -0
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/index.ts +2 -0
- package/ts/data/isolatedrestore.golden.ts +157 -0
- package/ts/data/isolatedrestore.ts +2401 -0
package/changelog.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-07-13 - 11.1.1
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- reject provider-reserved database names at isolated-restore prepare ingress
|
|
8
|
+
- Reject MongoDB system database names for both source and target mappings before a new restore reservation can be committed.
|
|
9
|
+
- Preserve structural decoding of historical mappings so cleanup and status remain available across the contract upgrade.
|
|
10
|
+
|
|
11
|
+
## 2026-07-13 - 11.1.0
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- define the hardened isolated-restore control contract (backup)
|
|
16
|
+
- Bind short-lived, single-operation restore grants to a canonical, versioned authority and immutable restore plan.
|
|
17
|
+
- Enforce JWT-only public authority, bounded chunk uploads, strict archive/resource normalization, and cross-runtime digest rules.
|
|
18
|
+
- Add bearer-free durable chunk receipts, completed-object proofs, and golden vectors for independent implementations.
|
|
19
|
+
|
|
3
20
|
## 2026-07-13 - 11.0.0
|
|
4
21
|
|
|
5
22
|
### Breaking Changes
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/interfaces',
|
|
6
|
-
version: '11.
|
|
6
|
+
version: '11.1.1',
|
|
7
7
|
description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
|
package/dist_ts/data/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export * from './externalregistry.js';
|
|
|
11
11
|
export * from './gateway.js';
|
|
12
12
|
export * from './hostedapp.js';
|
|
13
13
|
export * from './image.js';
|
|
14
|
+
export * from './isolatedrestore.js';
|
|
15
|
+
export * from './isolatedrestore.golden.js';
|
|
14
16
|
export * from './mail.js';
|
|
15
17
|
export * from './registry.js';
|
|
16
18
|
export * from './secretbundle.js';
|
package/dist_ts/data/index.js
CHANGED
|
@@ -11,6 +11,8 @@ export * from './externalregistry.js';
|
|
|
11
11
|
export * from './gateway.js';
|
|
12
12
|
export * from './hostedapp.js';
|
|
13
13
|
export * from './image.js';
|
|
14
|
+
export * from './isolatedrestore.js';
|
|
15
|
+
export * from './isolatedrestore.golden.js';
|
|
14
16
|
export * from './mail.js';
|
|
15
17
|
export * from './registry.js';
|
|
16
18
|
export * from './secretbundle.js';
|
|
@@ -27,4 +29,4 @@ export * from './taskexecution.js';
|
|
|
27
29
|
export * from './traffic.js';
|
|
28
30
|
export * from './user.js';
|
|
29
31
|
export * from './version.js';
|
|
30
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsVUFBVSxDQUFDO0FBQ3pCLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsWUFBWSxDQUFDO0FBQzNCLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLG1CQUFtQixDQUFDO0FBQ2xDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxjQUFjLENBQUMifQ==
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import type { IBackupArchiveManifest, IBackupArchiveObject, TIsolatedRestoreResourceMapping } from './backup.js';
|
|
2
|
+
/** Operations carried by a short-lived, single-operation restore grant. */
|
|
3
|
+
export declare const isolatedRestoreGrantOperations: readonly ["prepare", "write-object", "execute", "cleanup", "status"];
|
|
4
|
+
export type TIsolatedRestoreGrantOperation = (typeof isolatedRestoreGrantOperations)[number];
|
|
5
|
+
/**
|
|
6
|
+
* Versioned limits shared by signers, relays, and Corestore.
|
|
7
|
+
*
|
|
8
|
+
* V1 uses an inline descriptor manifest inside a 1 MiB control request. Its
|
|
9
|
+
* 4,096 object slots reserve 256 entries for config, snapshots, keys, and
|
|
10
|
+
* index segments; the remaining 3,840 slots fit 1,920 default 8 MiB pack/index
|
|
11
|
+
* pairs. The 15 GiB total envelope is therefore reachable with the default
|
|
12
|
+
* ContainerArchive packing profile instead of advertising impossible capacity.
|
|
13
|
+
*/
|
|
14
|
+
export declare const isolatedRestoreContractLimits: Readonly<{
|
|
15
|
+
version: 1;
|
|
16
|
+
maximumControlJsonBytes: number;
|
|
17
|
+
maximumRestoreGrantBytes: number;
|
|
18
|
+
maximumConfiguredStringBytes: 2048;
|
|
19
|
+
maximumPathBytes: 4096;
|
|
20
|
+
maximumResourceMappings: 256;
|
|
21
|
+
maximumArchiveObjects: 4096;
|
|
22
|
+
reservedArchiveMetadataObjects: 256;
|
|
23
|
+
defaultContainerArchivePackTargetBytes: number;
|
|
24
|
+
maximumArchiveObjectBytes: number;
|
|
25
|
+
maximumArchiveTotalBytes: number;
|
|
26
|
+
maximumWriteChunkBytes: number;
|
|
27
|
+
maximumWriteChunkBase64Characters: 699052;
|
|
28
|
+
maximumObjectChunks: 4096;
|
|
29
|
+
}>;
|
|
30
|
+
/** ContainerArchive v1 paths that may be replicated into restore staging. */
|
|
31
|
+
export declare const isolatedRestoreRepositoryPathProfile: Readonly<{
|
|
32
|
+
version: 1;
|
|
33
|
+
rootObject: "config.json";
|
|
34
|
+
topLevelDirectories: readonly ["packs", "snapshots", "index", "keys"];
|
|
35
|
+
temporaryFilesAllowed: false;
|
|
36
|
+
ancestorConflictsAllowed: false;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Exact normalized payload of a signed isolated restore grant.
|
|
40
|
+
* Persist this projection for audit/recovery, never the compact bearer JWT.
|
|
41
|
+
*/
|
|
42
|
+
export interface IIsolatedRestoreGrantClaims {
|
|
43
|
+
grantVersion: 1;
|
|
44
|
+
iss: string;
|
|
45
|
+
aud: string;
|
|
46
|
+
sub: string;
|
|
47
|
+
jti: string;
|
|
48
|
+
authorizationId: string;
|
|
49
|
+
tenantId: string;
|
|
50
|
+
clusterId: string;
|
|
51
|
+
targetNodeName: string;
|
|
52
|
+
restoreId: string;
|
|
53
|
+
sourceBackupId: string;
|
|
54
|
+
sourceServiceId: string;
|
|
55
|
+
scratchNamespaceId: string;
|
|
56
|
+
stagingArchiveId: string;
|
|
57
|
+
operation: TIsolatedRestoreGrantOperation;
|
|
58
|
+
resourceMappingsSha256: string;
|
|
59
|
+
archiveManifestSha256: string;
|
|
60
|
+
iat: number;
|
|
61
|
+
nbf: number;
|
|
62
|
+
exp: number;
|
|
63
|
+
}
|
|
64
|
+
declare const isolatedRestoreVerifiedGrantBrand: unique symbol;
|
|
65
|
+
/**
|
|
66
|
+
* Runtime-branded result of invoking a cryptographic verifier for a compact
|
|
67
|
+
* restore grant. The bearer itself remains in module-private storage so this
|
|
68
|
+
* value cannot disclose it through serialization or reflection. It cannot be
|
|
69
|
+
* reconstructed from claims alone and is accepted only by the same module
|
|
70
|
+
* instance that performed verification.
|
|
71
|
+
*/
|
|
72
|
+
export interface IVerifiedIsolatedRestoreGrant {
|
|
73
|
+
readonly claims: Readonly<IIsolatedRestoreGrantClaims>;
|
|
74
|
+
readonly [isolatedRestoreVerifiedGrantBrand]: true;
|
|
75
|
+
}
|
|
76
|
+
export type TIsolatedRestoreGrantVerifier = (compactArg: string) => unknown | Promise<unknown>;
|
|
77
|
+
/** The signed restoreGrant is the only authority accepted in control bodies. */
|
|
78
|
+
export interface IIsolatedRestoreControlForbiddenAuthority {
|
|
79
|
+
authorizationId?: never;
|
|
80
|
+
tenantId?: never;
|
|
81
|
+
clusterId?: never;
|
|
82
|
+
targetNodeName?: never;
|
|
83
|
+
restoreId?: never;
|
|
84
|
+
sourceBackupId?: never;
|
|
85
|
+
sourceServiceId?: never;
|
|
86
|
+
targetServiceId?: never;
|
|
87
|
+
scratchNamespaceId?: never;
|
|
88
|
+
stagingArchiveId?: never;
|
|
89
|
+
operation?: never;
|
|
90
|
+
resourceMappingsSha256?: never;
|
|
91
|
+
archiveManifestSha256?: never;
|
|
92
|
+
}
|
|
93
|
+
export interface IIsolatedRestoreControlPrepareRequest extends IIsolatedRestoreControlForbiddenAuthority {
|
|
94
|
+
restoreGrant: string;
|
|
95
|
+
expectedRevision: number;
|
|
96
|
+
resourceMappings: TIsolatedRestoreResourceMapping[];
|
|
97
|
+
archiveManifest: IBackupArchiveManifest;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* One bounded chunk of an immutable manifest object. `size` and `sha256`
|
|
101
|
+
* describe the complete object; `chunkSha256` authenticates this request's
|
|
102
|
+
* decoded bytes. Offset + decoded length === size means only that the chunk
|
|
103
|
+
* reaches the object boundary; it does not prove object completion.
|
|
104
|
+
*/
|
|
105
|
+
export interface IIsolatedRestoreControlWriteRequest extends IIsolatedRestoreControlForbiddenAuthority {
|
|
106
|
+
restoreGrant: string;
|
|
107
|
+
expectedRevision: number;
|
|
108
|
+
path: string;
|
|
109
|
+
size: number;
|
|
110
|
+
sha256: string;
|
|
111
|
+
offset: number;
|
|
112
|
+
chunkSha256: string;
|
|
113
|
+
contentsBase64: string;
|
|
114
|
+
}
|
|
115
|
+
export interface IIsolatedRestoreControlExecuteRequest extends IIsolatedRestoreControlForbiddenAuthority {
|
|
116
|
+
restoreGrant: string;
|
|
117
|
+
expectedRevision: number;
|
|
118
|
+
}
|
|
119
|
+
export interface IIsolatedRestoreControlCleanupRequest extends IIsolatedRestoreControlForbiddenAuthority {
|
|
120
|
+
restoreGrant: string;
|
|
121
|
+
expectedRevision: number;
|
|
122
|
+
}
|
|
123
|
+
export interface IIsolatedRestoreControlStatusRequest extends IIsolatedRestoreControlForbiddenAuthority {
|
|
124
|
+
restoreGrant: string;
|
|
125
|
+
}
|
|
126
|
+
export type TIsolatedRestoreControlRequest = IIsolatedRestoreControlPrepareRequest | IIsolatedRestoreControlWriteRequest | IIsolatedRestoreControlExecuteRequest | IIsolatedRestoreControlCleanupRequest | IIsolatedRestoreControlStatusRequest;
|
|
127
|
+
/**
|
|
128
|
+
* Stable authority shared by every grant for one restore plan. Request-local
|
|
129
|
+
* operation, jti, and validity times are intentionally excluded so separately
|
|
130
|
+
* authorized write requests can contribute to the same object.
|
|
131
|
+
*/
|
|
132
|
+
export interface IIsolatedRestoreAuthorityProjection {
|
|
133
|
+
version: 1;
|
|
134
|
+
iss: string;
|
|
135
|
+
aud: string;
|
|
136
|
+
sub: string;
|
|
137
|
+
authorizationId: string;
|
|
138
|
+
tenantId: string;
|
|
139
|
+
clusterId: string;
|
|
140
|
+
targetNodeName: string;
|
|
141
|
+
restoreId: string;
|
|
142
|
+
sourceBackupId: string;
|
|
143
|
+
sourceServiceId: string;
|
|
144
|
+
scratchNamespaceId: string;
|
|
145
|
+
stagingArchiveId: string;
|
|
146
|
+
resourceMappingsSha256: string;
|
|
147
|
+
archiveManifestSha256: string;
|
|
148
|
+
}
|
|
149
|
+
export type TIsolatedRestoreBoundPrepareRequest = Omit<IIsolatedRestoreControlPrepareRequest, 'restoreGrant'>;
|
|
150
|
+
export type TIsolatedRestoreBoundWriteRequestData = Omit<IIsolatedRestoreControlWriteRequest, 'restoreGrant'>;
|
|
151
|
+
export type TIsolatedRestoreBoundExecuteRequest = Omit<IIsolatedRestoreControlExecuteRequest, 'restoreGrant'>;
|
|
152
|
+
export type TIsolatedRestoreBoundCleanupRequest = Omit<IIsolatedRestoreControlCleanupRequest, 'restoreGrant'>;
|
|
153
|
+
export type TIsolatedRestoreBoundStatusRequest = Omit<IIsolatedRestoreControlStatusRequest, 'restoreGrant'>;
|
|
154
|
+
export interface IIsolatedRestoreBoundPlan {
|
|
155
|
+
authority: Readonly<IIsolatedRestoreAuthorityProjection>;
|
|
156
|
+
authoritySha256: string;
|
|
157
|
+
claims: Readonly<IIsolatedRestoreGrantClaims>;
|
|
158
|
+
resourceMappings: readonly TIsolatedRestoreResourceMapping[];
|
|
159
|
+
archiveManifest: Readonly<IBackupArchiveManifest>;
|
|
160
|
+
}
|
|
161
|
+
export interface IIsolatedRestoreBoundPrepareRequest {
|
|
162
|
+
authority: Readonly<IIsolatedRestoreAuthorityProjection>;
|
|
163
|
+
authoritySha256: string;
|
|
164
|
+
claims: Readonly<IIsolatedRestoreGrantClaims>;
|
|
165
|
+
request: Readonly<TIsolatedRestoreBoundPrepareRequest>;
|
|
166
|
+
}
|
|
167
|
+
export interface IIsolatedRestoreVerifiedChunkDescriptor {
|
|
168
|
+
contentsBase64: string;
|
|
169
|
+
decodedSize: number;
|
|
170
|
+
sha256: string;
|
|
171
|
+
}
|
|
172
|
+
export interface IIsolatedRestoreBoundWriteRequest {
|
|
173
|
+
authority: Readonly<IIsolatedRestoreAuthorityProjection>;
|
|
174
|
+
authoritySha256: string;
|
|
175
|
+
claims: Readonly<IIsolatedRestoreGrantClaims>;
|
|
176
|
+
request: Readonly<TIsolatedRestoreBoundWriteRequestData>;
|
|
177
|
+
descriptor: Readonly<IBackupArchiveObject>;
|
|
178
|
+
chunk: Readonly<IIsolatedRestoreVerifiedChunkDescriptor>;
|
|
179
|
+
/**
|
|
180
|
+
* The chunk reaches the declared size boundary. This is not object
|
|
181
|
+
* completion: only bindIsolatedRestoreCompletedObject proves contiguous
|
|
182
|
+
* coverage from offset 0 and the complete manifest-object SHA-256.
|
|
183
|
+
*/
|
|
184
|
+
endsAtObjectSize: boolean;
|
|
185
|
+
}
|
|
186
|
+
export interface IIsolatedRestoreBoundControlRequest<TRequest extends object> {
|
|
187
|
+
authority: Readonly<IIsolatedRestoreAuthorityProjection>;
|
|
188
|
+
authoritySha256: string;
|
|
189
|
+
claims: Readonly<IIsolatedRestoreGrantClaims>;
|
|
190
|
+
request: Readonly<TRequest>;
|
|
191
|
+
plan: IIsolatedRestoreBoundPlan;
|
|
192
|
+
}
|
|
193
|
+
declare const isolatedRestoreCompletedObjectBrand: unique symbol;
|
|
194
|
+
export interface IIsolatedRestoreCompletedObjectBinding {
|
|
195
|
+
readonly authority: Readonly<IIsolatedRestoreAuthorityProjection>;
|
|
196
|
+
readonly authoritySha256: string;
|
|
197
|
+
readonly descriptor: Readonly<IBackupArchiveObject>;
|
|
198
|
+
readonly chunkCount: number;
|
|
199
|
+
readonly contiguousBytes: number;
|
|
200
|
+
readonly sha256: string;
|
|
201
|
+
readonly [isolatedRestoreCompletedObjectBrand]: true;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Bearer-free receipt suitable for trusted Corestore persistence. Its hashes
|
|
205
|
+
* detect corruption and bind authority, descriptor, range, and chunk digest;
|
|
206
|
+
* they do not replace grant authentication or authenticate an untrusted store.
|
|
207
|
+
*/
|
|
208
|
+
export interface IIsolatedRestoreDurableChunkReceipt {
|
|
209
|
+
version: 1;
|
|
210
|
+
authority: Readonly<IIsolatedRestoreAuthorityProjection>;
|
|
211
|
+
authoritySha256: string;
|
|
212
|
+
descriptor: Readonly<IBackupArchiveObject>;
|
|
213
|
+
offset: number;
|
|
214
|
+
decodedSize: number;
|
|
215
|
+
chunkSha256: string;
|
|
216
|
+
receiptSha256: string;
|
|
217
|
+
}
|
|
218
|
+
/** Durable, bearer-free proof regenerated from receipts and one file snapshot. */
|
|
219
|
+
export interface IIsolatedRestoreDurableCompletedObjectProof {
|
|
220
|
+
version: 1;
|
|
221
|
+
authority: Readonly<IIsolatedRestoreAuthorityProjection>;
|
|
222
|
+
authoritySha256: string;
|
|
223
|
+
descriptor: Readonly<IBackupArchiveObject>;
|
|
224
|
+
chunkCount: number;
|
|
225
|
+
contiguousBytes: number;
|
|
226
|
+
sha256: string;
|
|
227
|
+
receiptSetSha256: string;
|
|
228
|
+
proofSha256: string;
|
|
229
|
+
}
|
|
230
|
+
export declare class IsolatedRestoreContractError extends Error {
|
|
231
|
+
constructor(reasonArg: string);
|
|
232
|
+
}
|
|
233
|
+
/** Cross-runtime rules for restore authority digests. */
|
|
234
|
+
export declare const isolatedRestoreCanonicalJsonRules: Readonly<{
|
|
235
|
+
version: 1;
|
|
236
|
+
encoding: "utf-8";
|
|
237
|
+
objectKeyOrdering: "utf-16-code-unit-ascending";
|
|
238
|
+
arrayOrdering: "preserved-dense";
|
|
239
|
+
unicodeNormalization: "preserved";
|
|
240
|
+
numberEncoding: "safe-integer-json-no-negative-zero";
|
|
241
|
+
digest: "sha256-lowercase-hex";
|
|
242
|
+
}>;
|
|
243
|
+
/**
|
|
244
|
+
* Enforces the raw HTTP ingress limit before buffering or JSON parsing.
|
|
245
|
+
* Apply it to Content-Length and to the running byte count after every chunk.
|
|
246
|
+
*/
|
|
247
|
+
export declare const assertIsolatedRestoreControlIngressByteLength: (byteLengthArg: unknown) => number;
|
|
248
|
+
export declare const normalizeIsolatedRestoreResourceMappings: (valueArg: unknown) => TIsolatedRestoreResourceMapping[];
|
|
249
|
+
/**
|
|
250
|
+
* Rejects names that the exact restore providers cannot provision, replace,
|
|
251
|
+
* or delete. Keep this separate from structural normalization so historical
|
|
252
|
+
* coordinator state remains readable for cleanup after a contract upgrade.
|
|
253
|
+
*/
|
|
254
|
+
export declare const assertIsolatedRestoreProviderRestorableResourceMappings: (mappingsArg: readonly TIsolatedRestoreResourceMapping[]) => void;
|
|
255
|
+
export declare const normalizeIsolatedRestoreArchiveManifest: (valueArg: unknown) => IBackupArchiveManifest;
|
|
256
|
+
export declare const normalizeIsolatedRestoreGrantClaims: (valueArg: unknown) => Readonly<IIsolatedRestoreGrantClaims>;
|
|
257
|
+
export declare const normalizeIsolatedRestoreControlPrepareRequest: (valueArg: unknown) => IIsolatedRestoreControlPrepareRequest;
|
|
258
|
+
export declare const normalizeIsolatedRestoreControlWriteRequest: (valueArg: unknown) => IIsolatedRestoreControlWriteRequest;
|
|
259
|
+
export declare const normalizeIsolatedRestoreControlExecuteRequest: (valueArg: unknown) => IIsolatedRestoreControlExecuteRequest;
|
|
260
|
+
export declare const normalizeIsolatedRestoreControlCleanupRequest: (valueArg: unknown) => IIsolatedRestoreControlCleanupRequest;
|
|
261
|
+
export declare const normalizeIsolatedRestoreControlStatusRequest: (valueArg: unknown) => IIsolatedRestoreControlStatusRequest;
|
|
262
|
+
export declare const canonicalizeIsolatedRestoreResourceMappings: (valueArg: readonly TIsolatedRestoreResourceMapping[]) => string;
|
|
263
|
+
export declare const canonicalizeIsolatedRestoreArchiveManifest: (valueArg: IBackupArchiveManifest) => string;
|
|
264
|
+
export declare const canonicalizeIsolatedRestoreGrantClaims: (valueArg: IIsolatedRestoreGrantClaims) => string;
|
|
265
|
+
export declare const normalizeIsolatedRestoreAuthorityProjection: (valueArg: unknown) => Readonly<IIsolatedRestoreAuthorityProjection>;
|
|
266
|
+
export declare const createIsolatedRestoreAuthorityProjection: (claimsArg: IIsolatedRestoreGrantClaims) => Readonly<IIsolatedRestoreAuthorityProjection>;
|
|
267
|
+
export declare const canonicalizeIsolatedRestoreAuthorityProjection: (valueArg: IIsolatedRestoreAuthorityProjection) => string;
|
|
268
|
+
export declare const createIsolatedRestoreBytesSha256: (contentsArg: Uint8Array) => Promise<string>;
|
|
269
|
+
export declare const createIsolatedRestoreResourceMappingsSha256: (valueArg: unknown) => Promise<string>;
|
|
270
|
+
export declare const createIsolatedRestoreArchiveManifestSha256: (valueArg: unknown) => Promise<string>;
|
|
271
|
+
export declare const createIsolatedRestoreGrantClaimsSha256: (valueArg: unknown) => Promise<string>;
|
|
272
|
+
export declare const createIsolatedRestoreAuthoritySha256: (valueArg: unknown) => Promise<string>;
|
|
273
|
+
/**
|
|
274
|
+
* Invokes the caller's cryptographic verifier for exactly `compact`, retains
|
|
275
|
+
* that bearer in module-private storage, and brands the immutable claims
|
|
276
|
+
* projection. Binding helpers reject claims supplied without this operation
|
|
277
|
+
* and reject any control body carrying another compact JWT.
|
|
278
|
+
*/
|
|
279
|
+
export declare const verifyIsolatedRestoreGrant: (compactArg: unknown, verifierArg: TIsolatedRestoreGrantVerifier) => Promise<IVerifiedIsolatedRestoreGrant>;
|
|
280
|
+
export declare const assertIsolatedRestoreGrantOperation: (grantArg: IVerifiedIsolatedRestoreGrant, expectedOperationArg: TIsolatedRestoreGrantOperation) => Readonly<IIsolatedRestoreGrantClaims>;
|
|
281
|
+
export declare const bindIsolatedRestoreGrantToPlan: (grantArg: IVerifiedIsolatedRestoreGrant, expectedOperationArg: TIsolatedRestoreGrantOperation, resourceMappingsArg: unknown, archiveManifestArg: unknown) => Promise<IIsolatedRestoreBoundPlan>;
|
|
282
|
+
export declare const bindIsolatedRestorePrepareRequestToGrant: (grantArg: IVerifiedIsolatedRestoreGrant, requestArg: unknown) => Promise<IIsolatedRestoreBoundPrepareRequest>;
|
|
283
|
+
export declare const bindIsolatedRestoreExecuteRequestToGrant: (grantArg: IVerifiedIsolatedRestoreGrant, requestArg: unknown, resourceMappingsArg: unknown, archiveManifestArg: unknown) => Promise<IIsolatedRestoreBoundControlRequest<TIsolatedRestoreBoundExecuteRequest>>;
|
|
284
|
+
export declare const bindIsolatedRestoreCleanupRequestToGrant: (grantArg: IVerifiedIsolatedRestoreGrant, requestArg: unknown, resourceMappingsArg: unknown, archiveManifestArg: unknown) => Promise<IIsolatedRestoreBoundControlRequest<TIsolatedRestoreBoundCleanupRequest>>;
|
|
285
|
+
export declare const bindIsolatedRestoreStatusRequestToGrant: (grantArg: IVerifiedIsolatedRestoreGrant, requestArg: unknown, resourceMappingsArg: unknown, archiveManifestArg: unknown) => Promise<IIsolatedRestoreBoundControlRequest<TIsolatedRestoreBoundStatusRequest>>;
|
|
286
|
+
export declare const bindIsolatedRestoreWriteRequestToGrant: (grantArg: IVerifiedIsolatedRestoreGrant, requestArg: unknown, resourceMappingsArg: unknown, archiveManifestArg: unknown) => Promise<IIsolatedRestoreBoundWriteRequest>;
|
|
287
|
+
/** Returns a fresh caller-owned copy; verified bindings never expose mutable bytes. */
|
|
288
|
+
export declare const decodeIsolatedRestoreBoundWriteChunk: (bindingArg: IIsolatedRestoreBoundWriteRequest) => Uint8Array;
|
|
289
|
+
export declare const normalizeIsolatedRestoreDurableChunkReceipt: (valueArg: unknown) => Readonly<IIsolatedRestoreDurableChunkReceipt>;
|
|
290
|
+
/**
|
|
291
|
+
* Rehydrates a trusted-store receipt and verifies both consistency digests.
|
|
292
|
+
* This does not replace verification of the grant that originally produced it.
|
|
293
|
+
*/
|
|
294
|
+
export declare const verifyIsolatedRestoreDurableChunkReceipt: (valueArg: unknown) => Promise<Readonly<IIsolatedRestoreDurableChunkReceipt>>;
|
|
295
|
+
/**
|
|
296
|
+
* Creates a bearer-free receipt only from a runtime-verified write binding.
|
|
297
|
+
* Persist the result in authenticated/trusted Corestore state for recovery.
|
|
298
|
+
*/
|
|
299
|
+
export declare const createIsolatedRestoreDurableChunkReceipt: (bindingArg: IIsolatedRestoreBoundWriteRequest) => Promise<Readonly<IIsolatedRestoreDurableChunkReceipt>>;
|
|
300
|
+
/**
|
|
301
|
+
* Rehydrates ordered trusted-store receipts and verifies them against one
|
|
302
|
+
* defensive snapshot of the complete staged file. Per-range and full-file
|
|
303
|
+
* SHA-256 checks bind the resulting proof to authority, object, and receipt set.
|
|
304
|
+
*/
|
|
305
|
+
export declare const verifyIsolatedRestoreDurableCompletedObject: (receiptsArg: readonly unknown[], contentsArg: Uint8Array) => Promise<Readonly<IIsolatedRestoreDurableCompletedObjectProof>>;
|
|
306
|
+
/**
|
|
307
|
+
* Process-local completion convenience for runtime-branded chunks. It does not
|
|
308
|
+
* survive restart. Enterprise/Corestore workflows must persist durable chunk
|
|
309
|
+
* receipts and call verifyIsolatedRestoreDurableCompletedObject after recovery.
|
|
310
|
+
* Chunks must share one authority and descriptor, cover [0, size) contiguously,
|
|
311
|
+
* and hash to the complete manifest descriptor.
|
|
312
|
+
*/
|
|
313
|
+
export declare const bindIsolatedRestoreCompletedObject: (bindingsArg: readonly IIsolatedRestoreBoundWriteRequest[]) => Promise<IIsolatedRestoreCompletedObjectBinding>;
|
|
314
|
+
export declare const assertIsolatedRestoreCompletedObject: (completedArg: IIsolatedRestoreCompletedObjectBinding) => IIsolatedRestoreCompletedObjectBinding;
|
|
315
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IBackupArchiveManifest, TIsolatedRestoreResourceMapping } from './backup.js';
|
|
2
|
+
import type { IIsolatedRestoreGrantClaims } from './isolatedrestore.js';
|
|
3
|
+
export interface IIsolatedRestoreCanonicalDigestGoldenVector<TInput> {
|
|
4
|
+
input: TInput;
|
|
5
|
+
canonicalJson: string;
|
|
6
|
+
sha256: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Portable fixed values for signer, relay, and verifier suites. The inputs
|
|
10
|
+
* deliberately cover an astral scalar, composed and decomposed accents, a
|
|
11
|
+
* quote, and a backslash. Consumers compare both JSON and SHA-256 verbatim.
|
|
12
|
+
*/
|
|
13
|
+
export declare const isolatedRestoreCanonicalDigestGoldenVectors: {
|
|
14
|
+
version: 1;
|
|
15
|
+
resourceMappings: IIsolatedRestoreCanonicalDigestGoldenVector<TIsolatedRestoreResourceMapping[]>;
|
|
16
|
+
archiveManifest: IIsolatedRestoreCanonicalDigestGoldenVector<IBackupArchiveManifest>;
|
|
17
|
+
grantClaims: IIsolatedRestoreCanonicalDigestGoldenVector<IIsolatedRestoreGrantClaims>;
|
|
18
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const deepFreezeVector = (valueArg) => {
|
|
2
|
+
if (!valueArg || typeof valueArg !== 'object' || Object.isFrozen(valueArg)) {
|
|
3
|
+
return valueArg;
|
|
4
|
+
}
|
|
5
|
+
for (const key of Reflect.ownKeys(valueArg)) {
|
|
6
|
+
const descriptor = Object.getOwnPropertyDescriptor(valueArg, key);
|
|
7
|
+
if (descriptor && Object.hasOwn(descriptor, 'value')) {
|
|
8
|
+
deepFreezeVector(descriptor.value);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return Object.freeze(valueArg);
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Portable fixed values for signer, relay, and verifier suites. The inputs
|
|
15
|
+
* deliberately cover an astral scalar, composed and decomposed accents, a
|
|
16
|
+
* quote, and a backslash. Consumers compare both JSON and SHA-256 verbatim.
|
|
17
|
+
*/
|
|
18
|
+
export const isolatedRestoreCanonicalDigestGoldenVectors = deepFreezeVector({
|
|
19
|
+
version: 1,
|
|
20
|
+
resourceMappings: {
|
|
21
|
+
input: [
|
|
22
|
+
{
|
|
23
|
+
id: 'mapping-volume',
|
|
24
|
+
type: 'volume',
|
|
25
|
+
source: {
|
|
26
|
+
snapshotId: 'snapshot-volume',
|
|
27
|
+
volumeName: 'source-volume',
|
|
28
|
+
mountPath: '/srv/š/Ć©/"quoted"',
|
|
29
|
+
},
|
|
30
|
+
target: {
|
|
31
|
+
volumeName: 'scratch-volume',
|
|
32
|
+
mountPath: '/srv/š/eĢ/"quoted"',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'mapping-database',
|
|
37
|
+
type: 'database',
|
|
38
|
+
source: {
|
|
39
|
+
snapshotId: 'snapshot-database',
|
|
40
|
+
resourceName: 'source-database-resource',
|
|
41
|
+
databaseName: 'source_database',
|
|
42
|
+
},
|
|
43
|
+
target: {
|
|
44
|
+
resourceName: 'scratch-database-resource',
|
|
45
|
+
databaseName: 'scratch_database',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'mapping-objectstorage',
|
|
50
|
+
type: 'objectstorage',
|
|
51
|
+
source: {
|
|
52
|
+
snapshotId: 'snapshot-objectstorage',
|
|
53
|
+
resourceName: 'source-objectstorage-resource',
|
|
54
|
+
bucketName: 'source-bucket',
|
|
55
|
+
},
|
|
56
|
+
target: {
|
|
57
|
+
resourceName: 'scratch-objectstorage-resource',
|
|
58
|
+
bucketName: 'scratch-bucket',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
canonicalJson: '[{"id":"mapping-volume","source":{"mountPath":"/srv/š/Ć©/\\"quoted\\"","snapshotId":"snapshot-volume","volumeName":"source-volume"},"target":{"mountPath":"/srv/š/eĢ/\\"quoted\\"","volumeName":"scratch-volume"},"type":"volume"},' +
|
|
63
|
+
'{"id":"mapping-database","source":{"databaseName":"source_database","resourceName":"source-database-resource","snapshotId":"snapshot-database"},"target":{"databaseName":"scratch_database","resourceName":"scratch-database-resource"},"type":"database"},' +
|
|
64
|
+
'{"id":"mapping-objectstorage","source":{"bucketName":"source-bucket","resourceName":"source-objectstorage-resource","snapshotId":"snapshot-objectstorage"},"target":{"bucketName":"scratch-bucket","resourceName":"scratch-objectstorage-resource"},"type":"objectstorage"}]',
|
|
65
|
+
sha256: '3c084580fc258dcb5dc25b80d7331eb1d9072a124f640df3ce26eba4917afe70',
|
|
66
|
+
},
|
|
67
|
+
archiveManifest: {
|
|
68
|
+
input: {
|
|
69
|
+
version: 1,
|
|
70
|
+
backupId: 'backup-0001',
|
|
71
|
+
createdAt: 1700000000123,
|
|
72
|
+
objects: [
|
|
73
|
+
{
|
|
74
|
+
path: 'config.json',
|
|
75
|
+
size: 2,
|
|
76
|
+
sha256: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
path: 'snapshots/snapshot-volume.json',
|
|
80
|
+
size: 3,
|
|
81
|
+
sha256: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
path: 'snapshots/snapshot-database.json',
|
|
85
|
+
size: 5,
|
|
86
|
+
sha256: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
path: 'snapshots/snapshot-objectstorage.json',
|
|
90
|
+
size: 7,
|
|
91
|
+
sha256: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
totalSize: 17,
|
|
95
|
+
},
|
|
96
|
+
canonicalJson: '{"backupId":"backup-0001","createdAt":1700000000123,"objects":[{"path":"config.json","sha256":"0000000000000000000000000000000000000000000000000000000000000000","size":2},' +
|
|
97
|
+
'{"path":"snapshots/snapshot-volume.json","sha256":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","size":3},' +
|
|
98
|
+
'{"path":"snapshots/snapshot-database.json","sha256":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","size":5},' +
|
|
99
|
+
'{"path":"snapshots/snapshot-objectstorage.json","sha256":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","size":7}],"totalSize":17,"version":1}',
|
|
100
|
+
sha256: 'cd688de1a4b7e0f0b185c660a2c0c199ea4009832c5614a49e8a4dec411f3bd4',
|
|
101
|
+
},
|
|
102
|
+
grantClaims: {
|
|
103
|
+
input: {
|
|
104
|
+
grantVersion: 1,
|
|
105
|
+
iss: 'urn:foss:restore:š:Ć©:eĢ:"quoted":\\backslash',
|
|
106
|
+
aud: 'corestore.restore',
|
|
107
|
+
sub: 'cloudly-control',
|
|
108
|
+
jti: 'grant-0001',
|
|
109
|
+
authorizationId: 'authorization-0001',
|
|
110
|
+
tenantId: 'tenant-0001',
|
|
111
|
+
clusterId: 'cluster-eu-1',
|
|
112
|
+
targetNodeName: 'node-1',
|
|
113
|
+
restoreId: 'restore-0001',
|
|
114
|
+
sourceBackupId: 'backup-0001',
|
|
115
|
+
sourceServiceId: 'service-source',
|
|
116
|
+
scratchNamespaceId: 'scratch-0001',
|
|
117
|
+
stagingArchiveId: 'archive-0001',
|
|
118
|
+
operation: 'prepare',
|
|
119
|
+
resourceMappingsSha256: '3c084580fc258dcb5dc25b80d7331eb1d9072a124f640df3ce26eba4917afe70',
|
|
120
|
+
archiveManifestSha256: 'cd688de1a4b7e0f0b185c660a2c0c199ea4009832c5614a49e8a4dec411f3bd4',
|
|
121
|
+
iat: 2_000_000_000,
|
|
122
|
+
nbf: 2_000_000_000,
|
|
123
|
+
exp: 2_000_000_120,
|
|
124
|
+
},
|
|
125
|
+
canonicalJson: '{"archiveManifestSha256":"cd688de1a4b7e0f0b185c660a2c0c199ea4009832c5614a49e8a4dec411f3bd4","aud":"corestore.restore","authorizationId":"authorization-0001","clusterId":"cluster-eu-1","exp":2000000120,"grantVersion":1,"iat":2000000000,' +
|
|
126
|
+
'"iss":"urn:foss:restore:š:Ć©:eĢ:\\"quoted\\":\\\\backslash","jti":"grant-0001","nbf":2000000000,"operation":"prepare","resourceMappingsSha256":"3c084580fc258dcb5dc25b80d7331eb1d9072a124f640df3ce26eba4917afe70",' +
|
|
127
|
+
'"restoreId":"restore-0001","scratchNamespaceId":"scratch-0001","sourceBackupId":"backup-0001","sourceServiceId":"service-source","stagingArchiveId":"archive-0001","sub":"cloudly-control","targetNodeName":"node-1","tenantId":"tenant-0001"}',
|
|
128
|
+
sha256: '6fcc94b4c6498b9fa45ec41de197999bbb38b9f8437a9c41f9c9478bdf3af8bf',
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXNvbGF0ZWRyZXN0b3JlLmdvbGRlbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2RhdGEvaXNvbGF0ZWRyZXN0b3JlLmdvbGRlbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFZQSxNQUFNLGdCQUFnQixHQUFHLENBQUksUUFBVyxFQUFLLEVBQUU7SUFDN0MsSUFBSSxDQUFDLFFBQVEsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQzNFLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFDRCxLQUFLLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBa0IsQ0FBQyxFQUFFLENBQUM7UUFDdEQsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLHdCQUF3QixDQUFDLFFBQWtCLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDNUUsSUFBSSxVQUFVLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNyRCxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDckMsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDakMsQ0FBQyxDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLDJDQUEyQyxHQVdwRCxnQkFBZ0IsQ0FBQztJQUNuQixPQUFPLEVBQUUsQ0FBQztJQUNWLGdCQUFnQixFQUFFO1FBQ2hCLEtBQUssRUFBRTtZQUNMO2dCQUNFLEVBQUUsRUFBRSxnQkFBZ0I7Z0JBQ3BCLElBQUksRUFBRSxRQUFRO2dCQUNkLE1BQU0sRUFBRTtvQkFDTixVQUFVLEVBQUUsaUJBQWlCO29CQUM3QixVQUFVLEVBQUUsZUFBZTtvQkFDM0IsU0FBUyxFQUFFLG9CQUFvQjtpQkFDaEM7Z0JBQ0QsTUFB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
|