@serve.zone/interfaces 32.35.0 → 32.36.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 +63 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/backup.d.ts +7 -1
- package/dist_ts/data/deploymentlegacyimport.d.ts +92 -0
- package/dist_ts/data/deploymentlegacyimport.js +237 -0
- package/dist_ts/data/deploymentoperation.d.ts +63 -38
- package/dist_ts/data/deploymentoperation.js +12 -2
- package/dist_ts/data/deploymentpreflight.d.ts +42 -10
- package/dist_ts/data/deploymentpreflight.js +47 -10
- package/dist_ts/data/immutableimage.d.ts +26 -2
- package/dist_ts/data/immutableimage.js +12 -2
- package/dist_ts/data/index.d.ts +5 -0
- package/dist_ts/data/index.js +6 -1
- package/dist_ts/data/runtimeassignmentexec.d.ts +110 -0
- package/dist_ts/data/runtimeassignmentexec.js +164 -0
- package/dist_ts/data/runtimeassignmentlogs.d.ts +121 -0
- package/dist_ts/data/runtimeassignmentlogs.js +139 -0
- package/dist_ts/data/runtimeassignmentstats.d.ts +60 -0
- package/dist_ts/data/runtimeassignmentstats.js +93 -0
- package/dist_ts/data/runtimelocalvolumearchive.d.ts +103 -0
- package/dist_ts/data/runtimelocalvolumearchive.js +111 -0
- package/dist_ts/data/user.d.ts +6 -1
- package/dist_ts/data/user.js +6 -1
- package/dist_ts/requests/runtimesession.d.ts +81 -0
- package/dist_ts/requests/service.d.ts +51 -0
- package/package.json +1 -1
- package/readme.md +105 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/backup.ts +7 -1
- package/ts/data/deploymentlegacyimport.ts +371 -0
- package/ts/data/deploymentoperation.ts +83 -39
- package/ts/data/deploymentpreflight.ts +86 -18
- package/ts/data/immutableimage.ts +42 -3
- package/ts/data/index.ts +5 -0
- package/ts/data/runtimeassignmentexec.ts +271 -0
- package/ts/data/runtimeassignmentlogs.ts +249 -0
- package/ts/data/runtimeassignmentstats.ts +149 -0
- package/ts/data/runtimelocalvolumearchive.ts +207 -0
- package/ts/data/user.ts +10 -0
- package/ts/requests/runtimesession.ts +102 -0
- package/ts/requests/service.ts +66 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type * as plugins from '../plugins.js';
|
|
2
|
+
import type { TSha256Digest } from './immutableimage.js';
|
|
3
|
+
import type { IRuntimeAuthorityReference } from './runtimeassignment.js';
|
|
4
|
+
import type { IRuntimeLocalStorageClaim } from './runtimelocalstorageclaim.js';
|
|
5
|
+
import {
|
|
6
|
+
getRuntimeLocalStorageClaimReference, snapshotRuntimeLocalStorageClaim, validateRuntimeLocalStorageClaim,
|
|
7
|
+
} from './runtimelocalstorageclaim.js';
|
|
8
|
+
import type { IRuntimeSessionBinding } from './runtimesession.js';
|
|
9
|
+
import { snapshotRuntimeSessionBinding } from './runtimesession.js';
|
|
10
|
+
import {
|
|
11
|
+
captureNetwork, networkDigest, networkEqual, networkRecord, networkReference, requireNetwork,
|
|
12
|
+
} from '../private/networkcontract.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The one archive format a volume travels in: a POSIX.1-2001 pax archive of the volume's tree.
|
|
16
|
+
*
|
|
17
|
+
* The first entry is the volume's root, `./`, and every other name is relative below it. An entry is
|
|
18
|
+
* a directory, a regular file, a symbolic link (stored, never followed), a hard link to an earlier
|
|
19
|
+
* entry of the same archive, or a FIFO. Ownership is numeric: `uid` and `gid`, never user or group
|
|
20
|
+
* names, so the tree means the same on every host. Mode bits, including setuid, setgid and sticky,
|
|
21
|
+
* and the modification time travel exactly. A socket carries no bytes and belongs to the process
|
|
22
|
+
* that created it, so it is omitted; a device node, extended attributes and ACLs are not part of
|
|
23
|
+
* the format, and a volume that holds a device node is refused. The archive ends with the format's
|
|
24
|
+
* two zero blocks, so its length is a whole number of 512-byte blocks.
|
|
25
|
+
*/
|
|
26
|
+
export type TRuntimeLocalVolumeArchiveFormat = 'pax';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A local controller reads one volume as an archive. The node refuses while a running container
|
|
30
|
+
* holds the volume: it reads a volume no container holds, or one whose holding container is
|
|
31
|
+
* stopped, which a node never restarts, and no container is granted the volume while it reads.
|
|
32
|
+
*/
|
|
33
|
+
export interface IReadRuntimeLocalVolumeArchiveRequest {
|
|
34
|
+
session: IRuntimeSessionBinding;
|
|
35
|
+
/** The reference of the node's current generation of a bound `directory` claim. */
|
|
36
|
+
claim: IRuntimeAuthorityReference;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The archive arrives on the stream the TypedRequest answers beside this body. `holder` states
|
|
41
|
+
* whether the volume was read unheld or under a stopped holder. The stream carries no integrity:
|
|
42
|
+
* the node learns the archive's length and digest only while it writes it.
|
|
43
|
+
*/
|
|
44
|
+
export interface IReadRuntimeLocalVolumeArchiveResponse {
|
|
45
|
+
claim: IRuntimeAuthorityReference;
|
|
46
|
+
format: TRuntimeLocalVolumeArchiveFormat;
|
|
47
|
+
holder: 'none' | 'stopped';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* A local controller writes one archive as the bytes of an `import` claim that waits in
|
|
52
|
+
* `import-required`: the online form of an operator's offline import. The node receives the stream
|
|
53
|
+
* beside this body, whose integrity must be exactly `byteLength` and `digest`, unpacks it into a
|
|
54
|
+
* private staging tree, and publishes that tree as the volume only after the whole archive
|
|
55
|
+
* verified. The tree keeps the ownership the archive carries, as every imported tree does.
|
|
56
|
+
*/
|
|
57
|
+
export interface IWriteRuntimeLocalVolumeArchiveRequest {
|
|
58
|
+
session: IRuntimeSessionBinding;
|
|
59
|
+
claim: IRuntimeAuthorityReference;
|
|
60
|
+
format: TRuntimeLocalVolumeArchiveFormat;
|
|
61
|
+
byteLength: number;
|
|
62
|
+
digest: TSha256Digest;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* `receiving` permits sending and confirms nothing more. The stream's acceptance receipt is what
|
|
67
|
+
* confirms that the node published the volume as `ready`; a rejected or aborted stream leaves the
|
|
68
|
+
* claim in `import-required` with nothing published.
|
|
69
|
+
*/
|
|
70
|
+
export interface IWriteRuntimeLocalVolumeArchiveResponse {
|
|
71
|
+
claim: IRuntimeAuthorityReference;
|
|
72
|
+
status: 'receiving';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Volume archives are a local controller's alone (`controller.kind: 'onebox'`), on the connection
|
|
77
|
+
* that holds its session, and a node moves one archive per volume at a time: a read or write of a
|
|
78
|
+
* volume that is already moving one is refused.
|
|
79
|
+
*/
|
|
80
|
+
export const runtimeLocalVolumeArchiveContract = Object.freeze({
|
|
81
|
+
error: 'Runtime local volume archive contract rejected.',
|
|
82
|
+
controllerKind: 'onebox',
|
|
83
|
+
format: 'pax',
|
|
84
|
+
entryKinds: ['directory', 'file', 'symlink', 'hardlink', 'fifo'],
|
|
85
|
+
omittedEntryKinds: ['socket'],
|
|
86
|
+
ownership: 'numeric-uid-gid',
|
|
87
|
+
blockBytes: 512,
|
|
88
|
+
/** The shortest archive: the root directory's header and the two closing zero blocks. */
|
|
89
|
+
minimumArchiveBytes: 1536,
|
|
90
|
+
concurrency: 'one-archive-per-volume',
|
|
91
|
+
} as const);
|
|
92
|
+
|
|
93
|
+
const fail = (): never => { throw new Error(runtimeLocalVolumeArchiveContract.error); };
|
|
94
|
+
const safe = <T>(operationArg: () => T): T => { try { return operationArg(); } catch { return fail(); } };
|
|
95
|
+
|
|
96
|
+
const archiveBytesOf = (valueArg: unknown): number => {
|
|
97
|
+
requireNetwork(typeof valueArg === 'number' && Number.isSafeInteger(valueArg)
|
|
98
|
+
&& valueArg >= runtimeLocalVolumeArchiveContract.minimumArchiveBytes
|
|
99
|
+
&& valueArg % runtimeLocalVolumeArchiveContract.blockBytes === 0);
|
|
100
|
+
return valueArg;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const snapshotReadRuntimeLocalVolumeArchiveRequest = (
|
|
104
|
+
valueArg: unknown,
|
|
105
|
+
): IReadRuntimeLocalVolumeArchiveRequest => safe(() => {
|
|
106
|
+
const value = networkRecord(captureNetwork(valueArg), ['session', 'claim']);
|
|
107
|
+
return { session: snapshotRuntimeSessionBinding(value.session), claim: networkReference(value.claim) };
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export const snapshotReadRuntimeLocalVolumeArchiveResponse = (
|
|
111
|
+
valueArg: unknown,
|
|
112
|
+
): IReadRuntimeLocalVolumeArchiveResponse => safe(() => {
|
|
113
|
+
const value = networkRecord(captureNetwork(valueArg), ['claim', 'format', 'holder']);
|
|
114
|
+
requireNetwork(value.format === 'pax' && (value.holder === 'none' || value.holder === 'stopped'));
|
|
115
|
+
return { claim: networkReference(value.claim), format: 'pax', holder: value.holder };
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
export const snapshotWriteRuntimeLocalVolumeArchiveRequest = (
|
|
119
|
+
valueArg: unknown,
|
|
120
|
+
): IWriteRuntimeLocalVolumeArchiveRequest => safe(() => {
|
|
121
|
+
const value = networkRecord(captureNetwork(valueArg), ['session', 'claim', 'format', 'byteLength', 'digest']);
|
|
122
|
+
requireNetwork(value.format === 'pax');
|
|
123
|
+
return {
|
|
124
|
+
session: snapshotRuntimeSessionBinding(value.session), claim: networkReference(value.claim), format: 'pax',
|
|
125
|
+
byteLength: archiveBytesOf(value.byteLength), digest: networkDigest(value.digest),
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
export const snapshotWriteRuntimeLocalVolumeArchiveResponse = (
|
|
130
|
+
valueArg: unknown,
|
|
131
|
+
): IWriteRuntimeLocalVolumeArchiveResponse => safe(() => {
|
|
132
|
+
const value = networkRecord(captureNetwork(valueArg), ['claim', 'status']);
|
|
133
|
+
requireNetwork(value.status === 'receiving');
|
|
134
|
+
return { claim: networkReference(value.claim), status: 'receiving' };
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
/** The exact integrity the write's stream must carry: the request's length and digest. */
|
|
138
|
+
export const getRuntimeLocalVolumeArchiveIntegrity = (
|
|
139
|
+
requestArg: unknown,
|
|
140
|
+
): plugins.typedrequestInterfaces.IVirtualStreamIntegrity => {
|
|
141
|
+
const request = snapshotWriteRuntimeLocalVolumeArchiveRequest(requestArg);
|
|
142
|
+
return { algorithm: 'sha256', byteLength: request.byteLength, digest: request.digest };
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* The claim a request names must be the node's current generation of a bound `directory` claim of
|
|
147
|
+
* the session's controller, cluster, node and runtime namespace, and the session must be a local
|
|
148
|
+
* controller's current one.
|
|
149
|
+
*/
|
|
150
|
+
const bindClaim = async (
|
|
151
|
+
requestArg: { session: IRuntimeSessionBinding; claim: IRuntimeAuthorityReference },
|
|
152
|
+
claimArg: unknown, trustedSessionArg: unknown,
|
|
153
|
+
): Promise<IRuntimeLocalStorageClaim> => {
|
|
154
|
+
const trustedSession = safe(() => snapshotRuntimeSessionBinding(trustedSessionArg));
|
|
155
|
+
const claim = safe(() => snapshotRuntimeLocalStorageClaim(claimArg));
|
|
156
|
+
if ((await validateRuntimeLocalStorageClaim(claim)).length) fail();
|
|
157
|
+
safe(() => requireNetwork(networkEqual(requestArg.session, trustedSession)
|
|
158
|
+
&& trustedSession.controller.kind === runtimeLocalVolumeArchiveContract.controllerKind
|
|
159
|
+
&& networkEqual(requestArg.claim, getRuntimeLocalStorageClaimReference(claim))
|
|
160
|
+
&& claim.lifecycle === 'bound' && claim.source.kind === 'directory'
|
|
161
|
+
&& networkEqual(claim.controller, trustedSession.controller)
|
|
162
|
+
&& claim.clusterId === trustedSession.clusterId
|
|
163
|
+
&& claim.nodeId === trustedSession.nodeId
|
|
164
|
+
&& claim.runtimeNamespace === trustedSession.runtimeNamespace));
|
|
165
|
+
return claim;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Node-side content binding, not authentication. `claimArg` is the node's current generation of the
|
|
170
|
+
* named claim and `trustedSessionArg` its CURRENT session, on whose own connection the request must
|
|
171
|
+
* have arrived. Whether the volume is `ready` and who holds it are the node's ledger checks.
|
|
172
|
+
*/
|
|
173
|
+
export const bindReadRuntimeLocalVolumeArchiveRequest = async (
|
|
174
|
+
valueArg: unknown, claimArg: unknown, trustedSessionArg: unknown,
|
|
175
|
+
): Promise<{ request: IReadRuntimeLocalVolumeArchiveRequest; claim: IRuntimeLocalStorageClaim }> => {
|
|
176
|
+
const request = snapshotReadRuntimeLocalVolumeArchiveRequest(valueArg);
|
|
177
|
+
return { request, claim: await bindClaim(request, claimArg, trustedSessionArg) };
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* As the read binding, and the claim must be an `import` claim. That it still waits in
|
|
182
|
+
* `import-required` is the node's ledger check.
|
|
183
|
+
*/
|
|
184
|
+
export const bindWriteRuntimeLocalVolumeArchiveRequest = async (
|
|
185
|
+
valueArg: unknown, claimArg: unknown, trustedSessionArg: unknown,
|
|
186
|
+
): Promise<{ request: IWriteRuntimeLocalVolumeArchiveRequest; claim: IRuntimeLocalStorageClaim }> => {
|
|
187
|
+
const request = snapshotWriteRuntimeLocalVolumeArchiveRequest(valueArg);
|
|
188
|
+
const claim = await bindClaim(request, claimArg, trustedSessionArg);
|
|
189
|
+
if (claim.initialization !== 'import') fail();
|
|
190
|
+
return { request, claim };
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export const bindReadRuntimeLocalVolumeArchiveResponse = (
|
|
194
|
+
valueArg: unknown, requestArg: unknown,
|
|
195
|
+
): IReadRuntimeLocalVolumeArchiveResponse => safe(() => {
|
|
196
|
+
const response = snapshotReadRuntimeLocalVolumeArchiveResponse(valueArg);
|
|
197
|
+
requireNetwork(networkEqual(response.claim, snapshotReadRuntimeLocalVolumeArchiveRequest(requestArg).claim));
|
|
198
|
+
return response;
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
export const bindWriteRuntimeLocalVolumeArchiveResponse = (
|
|
202
|
+
valueArg: unknown, requestArg: unknown,
|
|
203
|
+
): IWriteRuntimeLocalVolumeArchiveResponse => safe(() => {
|
|
204
|
+
const response = snapshotWriteRuntimeLocalVolumeArchiveResponse(valueArg);
|
|
205
|
+
requireNetwork(networkEqual(response.claim, snapshotWriteRuntimeLocalVolumeArchiveRequest(requestArg).claim));
|
|
206
|
+
return response;
|
|
207
|
+
});
|
package/ts/data/user.ts
CHANGED
|
@@ -13,6 +13,11 @@ export type TServiceDeploymentCapability =
|
|
|
13
13
|
| 'deployment:adopt-existing'
|
|
14
14
|
| 'deployment:status'
|
|
15
15
|
| 'deployment:create-greenfield'
|
|
16
|
+
/**
|
|
17
|
+
* Reserve a greenfield successor whose image Cloudly imports from an attested legacy service,
|
|
18
|
+
* and have Cloudly import it. Granted on an organization-service-slot grant only.
|
|
19
|
+
*/
|
|
20
|
+
| 'deployment:import-legacy'
|
|
16
21
|
| 'deployment:promote-route'
|
|
17
22
|
| 'deployment:rollback-image'
|
|
18
23
|
| 'deployment:rollback-route'
|
|
@@ -53,6 +58,7 @@ const serviceDeploymentCapabilities = new Set<TServiceDeploymentCapability>([
|
|
|
53
58
|
'deployment:adopt-existing',
|
|
54
59
|
'deployment:status',
|
|
55
60
|
'deployment:create-greenfield',
|
|
61
|
+
'deployment:import-legacy',
|
|
56
62
|
'deployment:promote-route',
|
|
57
63
|
'deployment:rollback-image',
|
|
58
64
|
'deployment:rollback-route',
|
|
@@ -106,6 +112,10 @@ export const validateServiceDeploymentGrant = (
|
|
|
106
112
|
&& capabilities.includes('deployment:adopt-existing')) {
|
|
107
113
|
errors.push('deployment:adopt-existing requires an existing-service grant');
|
|
108
114
|
}
|
|
115
|
+
if (capabilities && grant.scope !== 'organization-service-slot'
|
|
116
|
+
&& capabilities.includes('deployment:import-legacy')) {
|
|
117
|
+
errors.push('deployment:import-legacy requires an organization-service-slot grant');
|
|
118
|
+
}
|
|
109
119
|
return errors;
|
|
110
120
|
};
|
|
111
121
|
|
|
@@ -9,6 +9,10 @@ import type * as assignmentSecret from '../runtime.assignmentsecret.js';
|
|
|
9
9
|
import type * as fleet from '../data/fleetcutover.js';
|
|
10
10
|
import type { IRuntimeStorageClaim } from '../data/runtimestorageclaim.js';
|
|
11
11
|
import type * as localStorage from '../data/runtimelocalstorageclaim.js';
|
|
12
|
+
import type * as logs from '../data/runtimeassignmentlogs.js';
|
|
13
|
+
import type * as stats from '../data/runtimeassignmentstats.js';
|
|
14
|
+
import type * as exec from '../data/runtimeassignmentexec.js';
|
|
15
|
+
import type * as volumeArchive from '../data/runtimelocalvolumearchive.js';
|
|
12
16
|
|
|
13
17
|
/** Current-peer, exact-projection authorization; response contains secret keys. */
|
|
14
18
|
export interface IReq_Pallet_Controller_GetRuntimeManagedVpnCredential extends plugins.typedrequestInterfaces.implementsTR<
|
|
@@ -215,6 +219,104 @@ export interface IReq_Pallet_Controller_ReportRuntimeAssignmentTerminalReceipt e
|
|
|
215
219
|
response: terminal.IReportRuntimeAssignmentTerminalReceiptResponse;
|
|
216
220
|
}
|
|
217
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Pallet pushes one batch of one attempt's captured output over its current session and sends the
|
|
224
|
+
* next only after this one is acknowledged (`runtimeAssignmentLogContract`). The controller owns
|
|
225
|
+
* log persistence; the node's capture files are disposable transport artifacts.
|
|
226
|
+
*/
|
|
227
|
+
export interface IReq_Pallet_Controller_ReportRuntimeAssignmentLogs extends plugins.typedrequestInterfaces.implementsTR<
|
|
228
|
+
plugins.typedrequestInterfaces.ITypedRequest, IReq_Pallet_Controller_ReportRuntimeAssignmentLogs
|
|
229
|
+
> {
|
|
230
|
+
method: 'reportRuntimeAssignmentLogs';
|
|
231
|
+
request: logs.IReportRuntimeAssignmentLogsRequest;
|
|
232
|
+
response: logs.IReportRuntimeAssignmentLogsResponse;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Controller read of one resource sample of one attempt, over the node's current session. */
|
|
236
|
+
export interface IReq_Controller_Pallet_ReadRuntimeAssignmentStats extends plugins.typedrequestInterfaces.implementsTR<
|
|
237
|
+
plugins.typedrequestInterfaces.ITypedRequest, IReq_Controller_Pallet_ReadRuntimeAssignmentStats
|
|
238
|
+
> {
|
|
239
|
+
method: 'readRuntimeAssignmentStats';
|
|
240
|
+
request: stats.IReadRuntimeAssignmentStatsRequest;
|
|
241
|
+
response: stats.IReadRuntimeAssignmentStatsResponse;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* A local controller runs one command in one running attempt's container
|
|
246
|
+
* (`runtimeAssignmentExecContract`). The controller sends standard input on `stdin`, or states
|
|
247
|
+
* `null` for none. The node answers once the process runs: `stdout` carries a `tty` session's
|
|
248
|
+
* whole output, and `stderr` is `null` exactly for a `tty` session. The streams outlive this
|
|
249
|
+
* request and end when the process's output ends or the session ends.
|
|
250
|
+
*/
|
|
251
|
+
export interface IReq_Onebox_Pallet_OpenRuntimeAssignmentExec extends plugins.typedrequestInterfaces.implementsTR<
|
|
252
|
+
plugins.typedrequestInterfaces.ITypedRequest, IReq_Onebox_Pallet_OpenRuntimeAssignmentExec
|
|
253
|
+
> {
|
|
254
|
+
method: 'openRuntimeAssignmentExec';
|
|
255
|
+
request: {
|
|
256
|
+
exec: exec.IOpenRuntimeAssignmentExecRequest;
|
|
257
|
+
/** Requester sends standard input; the TypedHandler receives the opposite endpoint. */
|
|
258
|
+
stdin: plugins.typedrequestInterfaces.TVirtualStream<'send'> | null;
|
|
259
|
+
};
|
|
260
|
+
response: {
|
|
261
|
+
exec: exec.IOpenRuntimeAssignmentExecResponse;
|
|
262
|
+
/** Requester receives output; the TypedHandler returns sender endpoints. */
|
|
263
|
+
stdout: plugins.typedrequestInterfaces.TVirtualStream<'receive'>;
|
|
264
|
+
stderr: plugins.typedrequestInterfaces.TVirtualStream<'receive'> | null;
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** A local controller resizes the terminal of one `tty` exec session. */
|
|
269
|
+
export interface IReq_Onebox_Pallet_ResizeRuntimeAssignmentExec extends plugins.typedrequestInterfaces.implementsTR<
|
|
270
|
+
plugins.typedrequestInterfaces.ITypedRequest, IReq_Onebox_Pallet_ResizeRuntimeAssignmentExec
|
|
271
|
+
> {
|
|
272
|
+
method: 'resizeRuntimeAssignmentExec';
|
|
273
|
+
request: exec.IResizeRuntimeAssignmentExecRequest;
|
|
274
|
+
response: exec.IResizeRuntimeAssignmentExecResponse;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** A local controller ends one exec session, releases its slot and learns how it ended. */
|
|
278
|
+
export interface IReq_Onebox_Pallet_CloseRuntimeAssignmentExec extends plugins.typedrequestInterfaces.implementsTR<
|
|
279
|
+
plugins.typedrequestInterfaces.ITypedRequest, IReq_Onebox_Pallet_CloseRuntimeAssignmentExec
|
|
280
|
+
> {
|
|
281
|
+
method: 'closeRuntimeAssignmentExec';
|
|
282
|
+
request: exec.ICloseRuntimeAssignmentExecRequest;
|
|
283
|
+
response: exec.ICloseRuntimeAssignmentExecResponse;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* A local controller reads one node-local volume as a pax archive
|
|
288
|
+
* (`runtimeLocalVolumeArchiveContract`). The archive arrives on `archive`, which outlives this
|
|
289
|
+
* request; the node's completion of that stream is the end of the archive.
|
|
290
|
+
*/
|
|
291
|
+
export interface IReq_Onebox_Pallet_ReadRuntimeLocalVolumeArchive extends plugins.typedrequestInterfaces.implementsTR<
|
|
292
|
+
plugins.typedrequestInterfaces.ITypedRequest, IReq_Onebox_Pallet_ReadRuntimeLocalVolumeArchive
|
|
293
|
+
> {
|
|
294
|
+
method: 'readRuntimeLocalVolumeArchive';
|
|
295
|
+
request: volumeArchive.IReadRuntimeLocalVolumeArchiveRequest;
|
|
296
|
+
response: {
|
|
297
|
+
volume: volumeArchive.IReadRuntimeLocalVolumeArchiveResponse;
|
|
298
|
+
/** Requester receives archive bytes; the TypedHandler returns a sender endpoint. */
|
|
299
|
+
archive: plugins.typedrequestInterfaces.TVirtualStream<'receive'>;
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* A local controller writes one pax archive as the bytes of an `import` claim waiting in
|
|
305
|
+
* `import-required`. The stream's integrity is `getRuntimeLocalVolumeArchiveIntegrity(volume)`;
|
|
306
|
+
* its acceptance receipt confirms that the node published the volume as `ready`.
|
|
307
|
+
*/
|
|
308
|
+
export interface IReq_Onebox_Pallet_WriteRuntimeLocalVolumeArchive extends plugins.typedrequestInterfaces.implementsTR<
|
|
309
|
+
plugins.typedrequestInterfaces.ITypedRequest, IReq_Onebox_Pallet_WriteRuntimeLocalVolumeArchive
|
|
310
|
+
> {
|
|
311
|
+
method: 'writeRuntimeLocalVolumeArchive';
|
|
312
|
+
request: {
|
|
313
|
+
volume: volumeArchive.IWriteRuntimeLocalVolumeArchiveRequest;
|
|
314
|
+
/** Requester sends archive bytes; the TypedHandler receives the opposite endpoint. */
|
|
315
|
+
archive: plugins.typedrequestInterfaces.TVirtualStream<'send'>;
|
|
316
|
+
};
|
|
317
|
+
response: volumeArchive.IWriteRuntimeLocalVolumeArchiveResponse;
|
|
318
|
+
}
|
|
319
|
+
|
|
218
320
|
/** Current-peer, exact current assignment authorization; response is secret material. */
|
|
219
321
|
export interface IReq_Pallet_Controller_GetRuntimeRegistryCredential extends plugins.typedrequestInterfaces.implementsTR<
|
|
220
322
|
plugins.typedrequestInterfaces.ITypedRequest,
|
package/ts/requests/service.ts
CHANGED
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
IServiceDeploymentStatus,
|
|
18
18
|
} from '../data/deploymentoperation.js';
|
|
19
19
|
import type { TSha256Digest } from '../data/immutableimage.js';
|
|
20
|
+
import type { ILegacyServiceRuntimeAttestation } from '../data/deploymentlegacyimport.js';
|
|
20
21
|
import type { IProtocolOffer } from '../protocol.js';
|
|
21
22
|
import type {
|
|
22
23
|
IServiceRuntimeAssignmentView,
|
|
@@ -324,6 +325,71 @@ extends plugins.typedrequestInterfaces.implementsTR<
|
|
|
324
325
|
};
|
|
325
326
|
}
|
|
326
327
|
|
|
328
|
+
/**
|
|
329
|
+
* Captures durable evidence that a legacy `deployOnPush` service runs exactly the registry root its
|
|
330
|
+
* tag names: every required replica observed healthy on that one digest, with the root's platform
|
|
331
|
+
* manifests read from Cloudly's own registry. Administrators only, and only while the legacy
|
|
332
|
+
* runtime still runs — incomplete evidence is refused, never stored.
|
|
333
|
+
*
|
|
334
|
+
* `expectedRuntimeDigest`, when stated, is an assertion the observed digest must equal. Capturing
|
|
335
|
+
* again for an unchanged digest returns the attestation already stored.
|
|
336
|
+
*/
|
|
337
|
+
export interface IRequest_Any_Cloudly_CaptureLegacyServiceRuntimeAttestation
|
|
338
|
+
extends plugins.typedrequestInterfaces.implementsTR<
|
|
339
|
+
plugins.typedrequestInterfaces.ITypedRequest,
|
|
340
|
+
IRequest_Any_Cloudly_CaptureLegacyServiceRuntimeAttestation
|
|
341
|
+
> {
|
|
342
|
+
method: 'captureLegacyServiceRuntimeAttestation';
|
|
343
|
+
request: {
|
|
344
|
+
identity: IIdentityCredential;
|
|
345
|
+
legacyServiceId: string;
|
|
346
|
+
expectedRuntimeDigest?: TSha256Digest;
|
|
347
|
+
};
|
|
348
|
+
response: {
|
|
349
|
+
attestation: ILegacyServiceRuntimeAttestation;
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/** Every attestation Cloudly holds for one legacy service, oldest first. Administrators only. */
|
|
354
|
+
export interface IRequest_Any_Cloudly_GetLegacyServiceRuntimeAttestations
|
|
355
|
+
extends plugins.typedrequestInterfaces.implementsTR<
|
|
356
|
+
plugins.typedrequestInterfaces.ITypedRequest,
|
|
357
|
+
IRequest_Any_Cloudly_GetLegacyServiceRuntimeAttestations
|
|
358
|
+
> {
|
|
359
|
+
method: 'getLegacyServiceRuntimeAttestations';
|
|
360
|
+
request: {
|
|
361
|
+
identity: IIdentityCredential;
|
|
362
|
+
legacyServiceId: string;
|
|
363
|
+
};
|
|
364
|
+
response: {
|
|
365
|
+
attestations: ILegacyServiceRuntimeAttestation[];
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Imports the attested legacy image of a reserved legacy-import operation into the operation's own
|
|
371
|
+
* repository and release tag. Cloudly does it from its own registry — nothing is pushed — and
|
|
372
|
+
* records release evidence of source `cloudly-legacy-import`; the operation then continues exactly
|
|
373
|
+
* like one whose image was pushed. Replaying it after the import returns the recorded release.
|
|
374
|
+
*/
|
|
375
|
+
export interface IRequest_Any_Cloudly_ImportServiceDeploymentLegacyImage
|
|
376
|
+
extends plugins.typedrequestInterfaces.implementsTR<
|
|
377
|
+
plugins.typedrequestInterfaces.ITypedRequest,
|
|
378
|
+
IRequest_Any_Cloudly_ImportServiceDeploymentLegacyImage
|
|
379
|
+
> {
|
|
380
|
+
method: 'importServiceDeploymentLegacyImage';
|
|
381
|
+
request: {
|
|
382
|
+
identity: IIdentityCredential;
|
|
383
|
+
serviceId: string;
|
|
384
|
+
operationId: string;
|
|
385
|
+
expectedOperationRevision: number;
|
|
386
|
+
};
|
|
387
|
+
response: {
|
|
388
|
+
operation: IServiceDeploymentOperation;
|
|
389
|
+
release: IImageRelease;
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
327
393
|
export interface IRequest_Any_Cloudly_CreateService
|
|
328
394
|
extends plugins.typedrequestInterfaces.implementsTR<
|
|
329
395
|
plugins.typedrequestInterfaces.ITypedRequest,
|