@serve.zone/interfaces 9.0.0 → 10.1.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/changelog.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-07-13 - 10.1.0
4
+
5
+ ### Features
6
+
7
+ - define isolated restore orchestration contracts (backup)
8
+ - Add non-runnable scratch namespaces with backup-derived cluster and source authority.
9
+ - Add idempotency keys, revision compare-and-swap, exact cluster/node routing, verification, cursor pagination, durable backup holds, and retryable per-resource cleanup progress.
10
+
11
+ ### Maintenance
12
+
13
+ - Remove the legacy implicit-any build suppression and refresh the age-eligible TypeScript toolchain.
14
+
15
+ ## 2026-07-10 - 10.0.0
16
+
17
+ ### Breaking Changes
18
+
19
+ - accept JWT-only credentials for cluster config requests (config)
20
+ - Add IIdentityCredential as a JWT-only authentication contract.
21
+ - Make IIdentity extend IIdentityCredential so full identities remain compatible where credentials are accepted.
22
+ - Update getClusterConfig request identity to require only the JWT needed for server-side resolution.
23
+
3
24
  ## 2026-07-10 - 9.0.0
4
25
 
5
26
  ### Breaking Changes
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '9.0.0',
6
+ version: '10.1.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  };
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
@@ -53,6 +53,19 @@ export interface IBackupRestoreEvent {
53
53
  status: 'restored' | 'failed';
54
54
  errorText?: string;
55
55
  }
56
+ /**
57
+ * Durable retention hold owned by one isolated restore. An entry is active
58
+ * while `releasedAt` is absent. Active holds never expire implicitly:
59
+ * retention may neither claim nor delete the backup until every active hold
60
+ * has been released after successful scratch-resource and staging cleanup.
61
+ */
62
+ export interface IBackupRestoreHold {
63
+ restoreId: string;
64
+ idempotencyKey: string;
65
+ acquiredAt: number;
66
+ releasedAt?: number;
67
+ releaseReason?: string;
68
+ }
56
69
  export interface IBackupRecord {
57
70
  id: string;
58
71
  serviceId: string;
@@ -76,6 +89,12 @@ export interface IBackupRecord {
76
89
  requestedBy?: string;
77
90
  errorText?: string;
78
91
  restoreHistory?: IBackupRestoreEvent[];
92
+ /**
93
+ * Authoritative isolated-restore holds. Cloudly atomically appends the
94
+ * active entry with restore creation. Failed archive cleanup must retain
95
+ * this backup record so hold recovery remains possible.
96
+ */
97
+ restoreHolds?: IBackupRestoreHold[];
79
98
  tags?: Record<string, string>;
80
99
  }
81
100
  /** Retention policy understood by containerarchive prune. */
@@ -92,3 +111,213 @@ export interface IArchivePruneResult {
92
111
  freedBytes: number;
93
112
  dryRun: boolean;
94
113
  }
114
+ /**
115
+ * JWT-free actor projection persisted with isolated-restore audit data.
116
+ * Authentication credentials must never be copied into restore records.
117
+ */
118
+ export interface IIsolatedRestoreActor {
119
+ userId: string;
120
+ type: 'human' | 'machine' | 'system';
121
+ role?: 'admin' | 'user' | 'api' | 'cluster';
122
+ }
123
+ export type TIsolatedRestoreStatus = 'pending' | 'preparing' | 'staging' | 'restoring' | 'verifying' | 'ready' | 'failed' | 'cleanup-pending' | 'cleaning' | 'cleaned' | 'cleanup-failed';
124
+ export type TIsolatedRestoreErrorPhase = 'validation' | 'source-backup-hold' | 'preparation' | 'staging' | 'restoring' | 'verifying' | 'cleanup';
125
+ /** Append-only structured failure entry for one isolated restore. */
126
+ export interface IIsolatedRestoreError {
127
+ sequence: number;
128
+ phase: TIsolatedRestoreErrorPhase;
129
+ code: string;
130
+ message: string;
131
+ retryable: boolean;
132
+ occurredAt: number;
133
+ }
134
+ export type TIsolatedRestoreAuditAction = 'created' | 'status-transitioned' | 'source-backup-hold-acquired' | 'cleanup-requested' | 'expired' | 'source-backup-hold-release-requested' | 'source-backup-hold-released';
135
+ /** Append-only lifecycle event. `sequence` is strictly increasing per restore. */
136
+ export interface IIsolatedRestoreAuditEvent {
137
+ sequence: number;
138
+ action: TIsolatedRestoreAuditAction;
139
+ actor: IIsolatedRestoreActor;
140
+ occurredAt: number;
141
+ fromStatus?: TIsolatedRestoreStatus;
142
+ toStatus?: TIsolatedRestoreStatus;
143
+ reason?: string;
144
+ }
145
+ export interface IIsolatedRestoreVolumeMapping {
146
+ /** Stable server-generated id used by verification and cleanup progress. */
147
+ id: string;
148
+ type: 'volume';
149
+ source: {
150
+ snapshotId: string;
151
+ volumeName: string;
152
+ mountPath: string;
153
+ };
154
+ target: {
155
+ volumeName: string;
156
+ mountPath: string;
157
+ };
158
+ }
159
+ export interface IIsolatedRestoreDatabaseMapping {
160
+ /** Stable server-generated id used by verification and cleanup progress. */
161
+ id: string;
162
+ type: 'database';
163
+ source: {
164
+ snapshotId: string;
165
+ resourceName: string;
166
+ databaseName: string;
167
+ };
168
+ target: {
169
+ resourceName: string;
170
+ databaseName: string;
171
+ };
172
+ }
173
+ export interface IIsolatedRestoreObjectStorageMapping {
174
+ /** Stable server-generated id used by verification and cleanup progress. */
175
+ id: string;
176
+ type: 'objectstorage';
177
+ source: {
178
+ snapshotId: string;
179
+ resourceName: string;
180
+ bucketName: string;
181
+ };
182
+ target: {
183
+ resourceName: string;
184
+ bucketName: string;
185
+ };
186
+ }
187
+ export type TIsolatedRestoreResourceMapping = IIsolatedRestoreVolumeMapping | IIsolatedRestoreDatabaseMapping | IIsolatedRestoreObjectStorageMapping;
188
+ export type TIsolatedRestoreVerificationStatus = 'pending' | 'running' | 'passed' | 'failed';
189
+ export interface IIsolatedRestoreVerificationCheck {
190
+ /** Stable machine-readable check code. */
191
+ code: string;
192
+ status: 'passed' | 'failed';
193
+ message?: string;
194
+ }
195
+ export interface IIsolatedRestoreResourceVerification {
196
+ resourceMappingId: string;
197
+ resourceType: TBackupResourceType;
198
+ status: TIsolatedRestoreVerificationStatus;
199
+ checks: IIsolatedRestoreVerificationCheck[];
200
+ checkedAt?: number;
201
+ }
202
+ /** Complete verification state returned by the target data plane. */
203
+ export interface IIsolatedRestoreVerification {
204
+ status: TIsolatedRestoreVerificationStatus;
205
+ results: IIsolatedRestoreResourceVerification[];
206
+ startedAt?: number;
207
+ completedAt?: number;
208
+ }
209
+ export type TIsolatedRestoreCleanupTrigger = 'manual' | 'expired' | 'restore-failed' | 'policy';
210
+ export type TIsolatedRestoreCleanupProgressStatus = 'pending' | 'running' | 'succeeded' | 'failed';
211
+ export interface IIsolatedRestoreResourceCleanupProgress {
212
+ resourceMappingId: string;
213
+ resourceType: TBackupResourceType;
214
+ status: TIsolatedRestoreCleanupProgressStatus;
215
+ attempts: number;
216
+ updatedAt?: number;
217
+ errorCode?: string;
218
+ errorMessage?: string;
219
+ }
220
+ export interface IIsolatedRestoreStagingCleanupProgress {
221
+ stagingArchiveId: string;
222
+ status: TIsolatedRestoreCleanupProgressStatus;
223
+ attempts: number;
224
+ updatedAt?: number;
225
+ errorCode?: string;
226
+ errorMessage?: string;
227
+ }
228
+ /** Data-plane cleanup progress shared by public and internal status views. */
229
+ export interface IIsolatedRestoreCleanupProgress {
230
+ resources: IIsolatedRestoreResourceCleanupProgress[];
231
+ stagingArchive: IIsolatedRestoreStagingCleanupProgress;
232
+ }
233
+ /**
234
+ * Cleanup metadata. The source-backup hold remains active until every
235
+ * resource entry and the staging entry report `succeeded`. `cleanup-failed`
236
+ * is retryable and must not release the hold.
237
+ */
238
+ export interface IIsolatedRestoreCleanup extends IIsolatedRestoreCleanupProgress {
239
+ trigger: TIsolatedRestoreCleanupTrigger;
240
+ reason: string;
241
+ requestedBy: IIsolatedRestoreActor;
242
+ requestedAt: number;
243
+ startedAt?: number;
244
+ completedAt?: number;
245
+ }
246
+ export type TIsolatedRestoreSourceBackupHoldStatus = 'acquired' | 'release-pending' | 'released';
247
+ /**
248
+ * Restore-side projection of the authoritative IBackupRecord hold. The hold
249
+ * is non-expiring and may enter `released` only after exact cleanup success.
250
+ */
251
+ export interface IIsolatedRestoreSourceBackupHold {
252
+ status: TIsolatedRestoreSourceBackupHoldStatus;
253
+ acquiredAt: number;
254
+ releaseRequestedAt?: number;
255
+ releasedAt?: number;
256
+ releaseReason?: string;
257
+ }
258
+ export type TIsolatedRestoreNodeStatus = 'preparing' | 'prepared' | 'staging' | 'restoring' | 'verifying' | 'ready' | 'failed' | 'cleaning' | 'cleaned' | 'cleanup-failed';
259
+ /**
260
+ * Data-plane state for one exact cluster/node/restore routing key. `revision`
261
+ * advances after every mutation and is the compare-and-swap value used by
262
+ * prepare, execute, and cleanup requests.
263
+ */
264
+ export interface IIsolatedRestoreNodeState {
265
+ restoreId: string;
266
+ clusterId: string;
267
+ targetNodeName: string;
268
+ sourceBackupId: string;
269
+ sourceServiceId: string;
270
+ scratchNamespaceId: string;
271
+ stagingArchiveId: string;
272
+ revision: number;
273
+ status: TIsolatedRestoreNodeStatus;
274
+ completedResourceMappingIds: string[];
275
+ verification: IIsolatedRestoreVerification;
276
+ cleanup?: IIsolatedRestoreCleanupProgress;
277
+ preparedAt?: number;
278
+ readyAt?: number;
279
+ updatedAt: number;
280
+ lastErrorCode?: string;
281
+ lastErrorMessage?: string;
282
+ }
283
+ /**
284
+ * Durable control-plane record for a restore into a generated data-plane
285
+ * scratch namespace. The namespace is not an IService and carries no image,
286
+ * runtime, route, port, environment, or secret authority.
287
+ *
288
+ * `clusterId` and `sourceServiceId` are copied from the authoritative source
289
+ * backup, never accepted from the caller. `revision` advances monotonically
290
+ * for optimistic lifecycle updates. A restore execution failure (`failed`)
291
+ * must proceed through cleanup before its source-backup hold can be released.
292
+ */
293
+ export interface IIsolatedRestoreRecord {
294
+ /** Server-generated restore id. */
295
+ id: string;
296
+ /** Caller key used to return the same restore after retried creation. */
297
+ idempotencyKey: string;
298
+ revision: number;
299
+ sourceBackupId: string;
300
+ sourceServiceId: string;
301
+ sourceServiceName?: string;
302
+ clusterId: string;
303
+ /** Server-generated, non-runnable data-plane namespace. */
304
+ scratchNamespaceId: string;
305
+ /** Server-generated archive namespace, distinct from sourceBackupId. */
306
+ stagingArchiveId: string;
307
+ targetNodeName: string;
308
+ purpose: string;
309
+ requestedBy: IIsolatedRestoreActor;
310
+ status: TIsolatedRestoreStatus;
311
+ resourceMappings: TIsolatedRestoreResourceMapping[];
312
+ verification: IIsolatedRestoreVerification;
313
+ sourceBackupHold: IIsolatedRestoreSourceBackupHold;
314
+ createdAt: number;
315
+ updatedAt: number;
316
+ expiresAt: number;
317
+ readyAt?: number;
318
+ cleanup?: IIsolatedRestoreCleanup;
319
+ /** Append-only; entries are never replaced when a later phase fails. */
320
+ errors: IIsolatedRestoreError[];
321
+ /** Append-only lifecycle audit trail. */
322
+ auditEvents: IIsolatedRestoreAuditEvent[];
323
+ }
@@ -3,18 +3,19 @@ export interface IToken {
3
3
  expiresAt: number;
4
4
  assignedRoles: string[];
5
5
  }
6
+ export interface IIdentityCredential {
7
+ jwt: string;
8
+ }
6
9
  /**
7
10
  * an identity is assumed by authentication as a user
8
11
  * an identity is ephemeral and has to be renewed regularly
9
12
  */
10
- export interface IIdentity {
13
+ export interface IIdentity extends IIdentityCredential {
11
14
  name: string;
12
15
  userId: string;
13
16
  type: 'machine' | 'human';
14
17
  role: 'admin' | 'user' | 'api' | 'cluster';
15
18
  expiresAt: number;
16
- /** the jwt token should contain above data for verification */
17
- jwt: string;
18
19
  }
19
20
  export interface IUser {
20
21
  id: string;
@@ -1,5 +1,5 @@
1
1
  import * as plugins from '../plugins.js';
2
- import type { IArchivePruneResult, IArchiveRetentionPolicy, IBackupArchiveManifest, IBackupArchiveObject, IBackupRecord, IBackupReplicationResult, TBackupSnapshot } from '../data/backup.js';
2
+ import type { IArchivePruneResult, IArchiveRetentionPolicy, IBackupArchiveManifest, IBackupArchiveObject, IBackupRecord, IBackupReplicationResult, IIsolatedRestoreNodeState, IIsolatedRestoreRecord, TBackupSnapshot, TIsolatedRestoreResourceMapping } from '../data/backup.js';
3
3
  import type { IService } from '../data/service.js';
4
4
  import type { IIdentity } from '../data/user.js';
5
5
  export interface IReq_Any_Cloudly_CreateServiceBackup extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_CreateServiceBackup> {
@@ -146,3 +146,150 @@ export interface IReq_Cloudly_Coreflow_PruneNodeArchive extends plugins.typedreq
146
146
  result?: IArchivePruneResult;
147
147
  };
148
148
  }
149
+ /**
150
+ * Creates a restore in a new non-runnable data-plane scratch namespace.
151
+ * Cloudly derives clusterId and sourceServiceId from the authoritative backup,
152
+ * atomically acquires its retention hold, and owns every generated target id.
153
+ */
154
+ export interface IReq_Any_Cloudly_CreateIsolatedRestore extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_CreateIsolatedRestore> {
155
+ method: 'createIsolatedRestore';
156
+ request: {
157
+ identity: IIdentity;
158
+ sourceBackupId: string;
159
+ targetNodeName: string;
160
+ purpose: string;
161
+ /** Caller-generated key; retries return the original restore. */
162
+ idempotencyKey: string;
163
+ /** Requested lifetime; Cloudly applies its configured maximum. */
164
+ ttlMs?: number;
165
+ /** Derived from the authoritative backup. */
166
+ clusterId?: never;
167
+ /** Derived from the authoritative backup. */
168
+ sourceServiceId?: never;
169
+ /** Generated by Cloudly. Explicitly forbidden as caller input. */
170
+ id?: never;
171
+ /** Alias-like caller input is forbidden as well. */
172
+ restoreId?: never;
173
+ /** Legacy runnable-service targeting is forbidden. */
174
+ targetServiceId?: never;
175
+ /** Generated by Cloudly. Explicitly forbidden as caller input. */
176
+ scratchNamespaceId?: never;
177
+ /** Generated by Cloudly. Explicitly forbidden as caller input. */
178
+ stagingArchiveId?: never;
179
+ /** Generated after validating every snapshot in the source backup. */
180
+ resourceMappings?: never;
181
+ };
182
+ response: {
183
+ restore: IIsolatedRestoreRecord;
184
+ };
185
+ }
186
+ export interface IReq_Any_Cloudly_GetIsolatedRestores extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetIsolatedRestores> {
187
+ method: 'getIsolatedRestores';
188
+ request: {
189
+ identity: IIdentity;
190
+ sourceBackupId?: string;
191
+ sourceServiceId?: string;
192
+ clusterId?: string;
193
+ targetNodeName?: string;
194
+ scratchNamespaceId?: string;
195
+ status?: IIsolatedRestoreRecord['status'];
196
+ includeCleaned?: boolean;
197
+ /** Opaque cursor returned by the previous page. */
198
+ cursor?: string;
199
+ /** Server-capped page size. */
200
+ limit?: number;
201
+ };
202
+ response: {
203
+ restores: IIsolatedRestoreRecord[];
204
+ /** Omitted when this is the final page. */
205
+ nextCursor?: string;
206
+ };
207
+ }
208
+ export interface IReq_Any_Cloudly_GetIsolatedRestoreById extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetIsolatedRestoreById> {
209
+ method: 'getIsolatedRestoreById';
210
+ request: {
211
+ identity: IIdentity;
212
+ restoreId: string;
213
+ };
214
+ response: {
215
+ restore: IIsolatedRestoreRecord;
216
+ };
217
+ }
218
+ /**
219
+ * Prepares and stages one isolated restore on an exact cluster node. A missing
220
+ * node state has revision 0; successful mutation returns the next revision.
221
+ */
222
+ export interface IReq_Cloudly_Coreflow_PrepareIsolatedRestore extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Cloudly_Coreflow_PrepareIsolatedRestore> {
223
+ method: 'coreflowPrepareIsolatedRestore';
224
+ request: {
225
+ clusterId: string;
226
+ targetNodeName: string;
227
+ restoreId: string;
228
+ expectedRevision: number;
229
+ sourceBackupId: string;
230
+ sourceServiceId: string;
231
+ scratchNamespaceId: string;
232
+ stagingArchiveId: string;
233
+ resourceMappings: TIsolatedRestoreResourceMapping[];
234
+ archiveManifest: IBackupArchiveManifest;
235
+ };
236
+ response: {
237
+ state: IIsolatedRestoreNodeState;
238
+ };
239
+ }
240
+ /** Read-only status for one exact cluster/node/restore routing key. */
241
+ export interface IReq_Cloudly_Coreflow_GetIsolatedRestoreStatus extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Cloudly_Coreflow_GetIsolatedRestoreStatus> {
242
+ method: 'coreflowGetIsolatedRestoreStatus';
243
+ request: {
244
+ clusterId: string;
245
+ targetNodeName: string;
246
+ restoreId: string;
247
+ };
248
+ response: {
249
+ found: boolean;
250
+ state?: IIsolatedRestoreNodeState;
251
+ };
252
+ }
253
+ export interface IReq_Cloudly_Coreflow_ExecuteIsolatedRestore extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Cloudly_Coreflow_ExecuteIsolatedRestore> {
254
+ method: 'coreflowExecuteIsolatedRestore';
255
+ request: {
256
+ clusterId: string;
257
+ targetNodeName: string;
258
+ restoreId: string;
259
+ expectedRevision: number;
260
+ };
261
+ response: {
262
+ state: IIsolatedRestoreNodeState;
263
+ };
264
+ }
265
+ /**
266
+ * Idempotent cleanup mutation. A cleanup-failed state remains retryable and
267
+ * does not authorize release of the source-backup hold.
268
+ */
269
+ export interface IReq_Cloudly_Coreflow_CleanupIsolatedRestore extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Cloudly_Coreflow_CleanupIsolatedRestore> {
270
+ method: 'coreflowCleanupIsolatedRestore';
271
+ request: {
272
+ clusterId: string;
273
+ targetNodeName: string;
274
+ restoreId: string;
275
+ expectedRevision: number;
276
+ };
277
+ response: {
278
+ state: IIsolatedRestoreNodeState;
279
+ };
280
+ }
281
+ /**
282
+ * Requests idempotent asynchronous cleanup. The restore record is retained as
283
+ * audit evidence and transitions through the canonical cleanup statuses.
284
+ */
285
+ export interface IReq_Any_Cloudly_CleanupIsolatedRestore extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_CleanupIsolatedRestore> {
286
+ method: 'cleanupIsolatedRestore';
287
+ request: {
288
+ identity: IIdentity;
289
+ restoreId: string;
290
+ reason: string;
291
+ };
292
+ response: {
293
+ restore: IIsolatedRestoreRecord;
294
+ };
295
+ }
@@ -17,7 +17,7 @@ export interface IRequest_Any_Cloudly_GetServerConfig extends plugins.typedreque
17
17
  export interface IRequest_Any_Cloudly_GetClusterConfig extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IRequest_Any_Cloudly_GetClusterConfig> {
18
18
  method: 'getClusterConfig';
19
19
  request: {
20
- identity: userInterfaces.IIdentity;
20
+ identity: userInterfaces.IIdentityCredential;
21
21
  };
22
22
  response: {
23
23
  configData: clusterInterfaces.ICluster;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "9.0.0",
3
+ "version": "10.1.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.",
6
6
  "exports": {
@@ -19,7 +19,7 @@
19
19
  "@git.zone/tsdoc": "^2.1.1",
20
20
  "@git.zone/tsrun": "^2.0.5",
21
21
  "@git.zone/tstest": "^3.6.6",
22
- "@types/node": "^26.0.1"
22
+ "@types/node": "^26.1.0"
23
23
  },
24
24
  "files": [
25
25
  "ts/**/*",
@@ -52,7 +52,7 @@
52
52
  ],
53
53
  "scripts": {
54
54
  "test": "tstest test/ --verbose --logfile --timeout 60",
55
- "build": "tsbuild tsfolders --allowimplicitany",
55
+ "build": "tsbuild tsfolders",
56
56
  "buildDocs": "tsdoc"
57
57
  }
58
58
  }
package/readme.md CHANGED
@@ -99,7 +99,7 @@ Common data contracts include:
99
99
  - `ISecretBundle` and `ISecretGroup` for secret ownership and shared secret groups.
100
100
  - Mail gateway contracts for domain authorities, address bindings, WorkApp bindings, managed SMTP/API credentials, spool items, delivery journals, and inbound/outbound message payloads.
101
101
  - Service-level mail configuration through `IService.data.mail`, including per-address inbound `smtpForward` settings and outbound credential metadata. Cloudly settings include dcrouter gateway, SMTP submission, and inbound forward-target keys for reconciling those bindings.
102
- - `IUser`, `IIdentity`, and token-related contracts for authentication context.
102
+ - `IUser`, JWT-only `IIdentityCredential`, full `IIdentity`, and token-related contracts for authentication context. `IIdentity` extends `IIdentityCredential` with server-issued user metadata.
103
103
  - `ICloudlyConfig`, `ICloudlySettings`, status, server, bare-metal, BaseOS, backup, and task execution interfaces for control-plane state.
104
104
 
105
105
  Shared service port helpers are exported from `data` so Cloudly, App Store resolution, Coreflow, Coretraffic, Onebox, and dcrouter agree on the same normalization rules:
@@ -138,6 +138,8 @@ interface IExampleRequest {
138
138
  }
139
139
  ```
140
140
 
141
+ `requests.config.IRequest_Any_Cloudly_GetClusterConfig` accepts `data.IIdentityCredential`, which contains only the JWT needed for server-side identity resolution. Username/password login and machine-token exchange responses continue to return the full `data.IIdentity`.
142
+
141
143
  Gateway request contracts include `getGatewayClientRoutes` (`requests.gateway.IReq_GetGatewayClientRoutes`) for listing owned `IGatewayClientRoute[]` route views, and `syncGatewayClientRoute` for idempotently syncing or deleting hostname-owned and routeRef-owned routes. Mail request contracts include `syncMailAddressBinding`, `deleteMailAddressBinding`, `rotateMailCredential`, and `getMailDeliveryStatus`. `IReq_GetMailDeliveryStatus` looks up a delivery spool item by `spoolItemId`, returns `data.IMailDeliveryStatus`, and accepts `IMailSubmissionRequestAuth` so service-mail credentials can query their own accepted, queued, deferred, delivered, or failed status. `TMailAddressBindingSync.outboundEnabled` explicitly controls whether a gateway should maintain a managed outbound SMTP credential for an address binding. Binding credential metadata is public; `rotateMailCredential` returns the new secret only in its one-time `IMailCredentialOneTimeSecret` response.
142
144
 
143
145
  Request groups are exported by product area:
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '9.0.0',
6
+ version: '10.1.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
package/ts/data/backup.ts CHANGED
@@ -77,6 +77,20 @@ export interface IBackupRestoreEvent {
77
77
  errorText?: string;
78
78
  }
79
79
 
80
+ /**
81
+ * Durable retention hold owned by one isolated restore. An entry is active
82
+ * while `releasedAt` is absent. Active holds never expire implicitly:
83
+ * retention may neither claim nor delete the backup until every active hold
84
+ * has been released after successful scratch-resource and staging cleanup.
85
+ */
86
+ export interface IBackupRestoreHold {
87
+ restoreId: string;
88
+ idempotencyKey: string;
89
+ acquiredAt: number;
90
+ releasedAt?: number;
91
+ releaseReason?: string;
92
+ }
93
+
80
94
  export interface IBackupRecord {
81
95
  id: string;
82
96
  serviceId: string;
@@ -100,6 +114,12 @@ export interface IBackupRecord {
100
114
  requestedBy?: string;
101
115
  errorText?: string;
102
116
  restoreHistory?: IBackupRestoreEvent[];
117
+ /**
118
+ * Authoritative isolated-restore holds. Cloudly atomically appends the
119
+ * active entry with restore creation. Failed archive cleanup must retain
120
+ * this backup record so hold recovery remains possible.
121
+ */
122
+ restoreHolds?: IBackupRestoreHold[];
103
123
  tags?: Record<string, string>;
104
124
  }
105
125
 
@@ -118,3 +138,291 @@ export interface IArchivePruneResult {
118
138
  freedBytes: number;
119
139
  dryRun: boolean;
120
140
  }
141
+
142
+ /**
143
+ * JWT-free actor projection persisted with isolated-restore audit data.
144
+ * Authentication credentials must never be copied into restore records.
145
+ */
146
+ export interface IIsolatedRestoreActor {
147
+ userId: string;
148
+ type: 'human' | 'machine' | 'system';
149
+ role?: 'admin' | 'user' | 'api' | 'cluster';
150
+ }
151
+
152
+ export type TIsolatedRestoreStatus =
153
+ | 'pending'
154
+ | 'preparing'
155
+ | 'staging'
156
+ | 'restoring'
157
+ | 'verifying'
158
+ | 'ready'
159
+ | 'failed'
160
+ | 'cleanup-pending'
161
+ | 'cleaning'
162
+ | 'cleaned'
163
+ | 'cleanup-failed';
164
+
165
+ export type TIsolatedRestoreErrorPhase =
166
+ | 'validation'
167
+ | 'source-backup-hold'
168
+ | 'preparation'
169
+ | 'staging'
170
+ | 'restoring'
171
+ | 'verifying'
172
+ | 'cleanup';
173
+
174
+ /** Append-only structured failure entry for one isolated restore. */
175
+ export interface IIsolatedRestoreError {
176
+ sequence: number;
177
+ phase: TIsolatedRestoreErrorPhase;
178
+ code: string;
179
+ message: string;
180
+ retryable: boolean;
181
+ occurredAt: number;
182
+ }
183
+
184
+ export type TIsolatedRestoreAuditAction =
185
+ | 'created'
186
+ | 'status-transitioned'
187
+ | 'source-backup-hold-acquired'
188
+ | 'cleanup-requested'
189
+ | 'expired'
190
+ | 'source-backup-hold-release-requested'
191
+ | 'source-backup-hold-released';
192
+
193
+ /** Append-only lifecycle event. `sequence` is strictly increasing per restore. */
194
+ export interface IIsolatedRestoreAuditEvent {
195
+ sequence: number;
196
+ action: TIsolatedRestoreAuditAction;
197
+ actor: IIsolatedRestoreActor;
198
+ occurredAt: number;
199
+ fromStatus?: TIsolatedRestoreStatus;
200
+ toStatus?: TIsolatedRestoreStatus;
201
+ reason?: string;
202
+ }
203
+
204
+ export interface IIsolatedRestoreVolumeMapping {
205
+ /** Stable server-generated id used by verification and cleanup progress. */
206
+ id: string;
207
+ type: 'volume';
208
+ source: {
209
+ snapshotId: string;
210
+ volumeName: string;
211
+ mountPath: string;
212
+ };
213
+ target: {
214
+ volumeName: string;
215
+ mountPath: string;
216
+ };
217
+ }
218
+
219
+ export interface IIsolatedRestoreDatabaseMapping {
220
+ /** Stable server-generated id used by verification and cleanup progress. */
221
+ id: string;
222
+ type: 'database';
223
+ source: {
224
+ snapshotId: string;
225
+ resourceName: string;
226
+ databaseName: string;
227
+ };
228
+ target: {
229
+ resourceName: string;
230
+ databaseName: string;
231
+ };
232
+ }
233
+
234
+ export interface IIsolatedRestoreObjectStorageMapping {
235
+ /** Stable server-generated id used by verification and cleanup progress. */
236
+ id: string;
237
+ type: 'objectstorage';
238
+ source: {
239
+ snapshotId: string;
240
+ resourceName: string;
241
+ bucketName: string;
242
+ };
243
+ target: {
244
+ resourceName: string;
245
+ bucketName: string;
246
+ };
247
+ }
248
+
249
+ export type TIsolatedRestoreResourceMapping =
250
+ | IIsolatedRestoreVolumeMapping
251
+ | IIsolatedRestoreDatabaseMapping
252
+ | IIsolatedRestoreObjectStorageMapping;
253
+
254
+ export type TIsolatedRestoreVerificationStatus =
255
+ | 'pending'
256
+ | 'running'
257
+ | 'passed'
258
+ | 'failed';
259
+
260
+ export interface IIsolatedRestoreVerificationCheck {
261
+ /** Stable machine-readable check code. */
262
+ code: string;
263
+ status: 'passed' | 'failed';
264
+ message?: string;
265
+ }
266
+
267
+ export interface IIsolatedRestoreResourceVerification {
268
+ resourceMappingId: string;
269
+ resourceType: TBackupResourceType;
270
+ status: TIsolatedRestoreVerificationStatus;
271
+ checks: IIsolatedRestoreVerificationCheck[];
272
+ checkedAt?: number;
273
+ }
274
+
275
+ /** Complete verification state returned by the target data plane. */
276
+ export interface IIsolatedRestoreVerification {
277
+ status: TIsolatedRestoreVerificationStatus;
278
+ results: IIsolatedRestoreResourceVerification[];
279
+ startedAt?: number;
280
+ completedAt?: number;
281
+ }
282
+
283
+ export type TIsolatedRestoreCleanupTrigger =
284
+ | 'manual'
285
+ | 'expired'
286
+ | 'restore-failed'
287
+ | 'policy';
288
+
289
+ export type TIsolatedRestoreCleanupProgressStatus =
290
+ | 'pending'
291
+ | 'running'
292
+ | 'succeeded'
293
+ | 'failed';
294
+
295
+ export interface IIsolatedRestoreResourceCleanupProgress {
296
+ resourceMappingId: string;
297
+ resourceType: TBackupResourceType;
298
+ status: TIsolatedRestoreCleanupProgressStatus;
299
+ attempts: number;
300
+ updatedAt?: number;
301
+ errorCode?: string;
302
+ errorMessage?: string;
303
+ }
304
+
305
+ export interface IIsolatedRestoreStagingCleanupProgress {
306
+ stagingArchiveId: string;
307
+ status: TIsolatedRestoreCleanupProgressStatus;
308
+ attempts: number;
309
+ updatedAt?: number;
310
+ errorCode?: string;
311
+ errorMessage?: string;
312
+ }
313
+
314
+ /** Data-plane cleanup progress shared by public and internal status views. */
315
+ export interface IIsolatedRestoreCleanupProgress {
316
+ resources: IIsolatedRestoreResourceCleanupProgress[];
317
+ stagingArchive: IIsolatedRestoreStagingCleanupProgress;
318
+ }
319
+
320
+ /**
321
+ * Cleanup metadata. The source-backup hold remains active until every
322
+ * resource entry and the staging entry report `succeeded`. `cleanup-failed`
323
+ * is retryable and must not release the hold.
324
+ */
325
+ export interface IIsolatedRestoreCleanup extends IIsolatedRestoreCleanupProgress {
326
+ trigger: TIsolatedRestoreCleanupTrigger;
327
+ reason: string;
328
+ requestedBy: IIsolatedRestoreActor;
329
+ requestedAt: number;
330
+ startedAt?: number;
331
+ completedAt?: number;
332
+ }
333
+
334
+ export type TIsolatedRestoreSourceBackupHoldStatus =
335
+ | 'acquired'
336
+ | 'release-pending'
337
+ | 'released';
338
+
339
+ /**
340
+ * Restore-side projection of the authoritative IBackupRecord hold. The hold
341
+ * is non-expiring and may enter `released` only after exact cleanup success.
342
+ */
343
+ export interface IIsolatedRestoreSourceBackupHold {
344
+ status: TIsolatedRestoreSourceBackupHoldStatus;
345
+ acquiredAt: number;
346
+ releaseRequestedAt?: number;
347
+ releasedAt?: number;
348
+ releaseReason?: string;
349
+ }
350
+
351
+ export type TIsolatedRestoreNodeStatus =
352
+ | 'preparing'
353
+ | 'prepared'
354
+ | 'staging'
355
+ | 'restoring'
356
+ | 'verifying'
357
+ | 'ready'
358
+ | 'failed'
359
+ | 'cleaning'
360
+ | 'cleaned'
361
+ | 'cleanup-failed';
362
+
363
+ /**
364
+ * Data-plane state for one exact cluster/node/restore routing key. `revision`
365
+ * advances after every mutation and is the compare-and-swap value used by
366
+ * prepare, execute, and cleanup requests.
367
+ */
368
+ export interface IIsolatedRestoreNodeState {
369
+ restoreId: string;
370
+ clusterId: string;
371
+ targetNodeName: string;
372
+ sourceBackupId: string;
373
+ sourceServiceId: string;
374
+ scratchNamespaceId: string;
375
+ stagingArchiveId: string;
376
+ revision: number;
377
+ status: TIsolatedRestoreNodeStatus;
378
+ completedResourceMappingIds: string[];
379
+ verification: IIsolatedRestoreVerification;
380
+ cleanup?: IIsolatedRestoreCleanupProgress;
381
+ preparedAt?: number;
382
+ readyAt?: number;
383
+ updatedAt: number;
384
+ lastErrorCode?: string;
385
+ lastErrorMessage?: string;
386
+ }
387
+
388
+ /**
389
+ * Durable control-plane record for a restore into a generated data-plane
390
+ * scratch namespace. The namespace is not an IService and carries no image,
391
+ * runtime, route, port, environment, or secret authority.
392
+ *
393
+ * `clusterId` and `sourceServiceId` are copied from the authoritative source
394
+ * backup, never accepted from the caller. `revision` advances monotonically
395
+ * for optimistic lifecycle updates. A restore execution failure (`failed`)
396
+ * must proceed through cleanup before its source-backup hold can be released.
397
+ */
398
+ export interface IIsolatedRestoreRecord {
399
+ /** Server-generated restore id. */
400
+ id: string;
401
+ /** Caller key used to return the same restore after retried creation. */
402
+ idempotencyKey: string;
403
+ revision: number;
404
+ sourceBackupId: string;
405
+ sourceServiceId: string;
406
+ sourceServiceName?: string;
407
+ clusterId: string;
408
+ /** Server-generated, non-runnable data-plane namespace. */
409
+ scratchNamespaceId: string;
410
+ /** Server-generated archive namespace, distinct from sourceBackupId. */
411
+ stagingArchiveId: string;
412
+ targetNodeName: string;
413
+ purpose: string;
414
+ requestedBy: IIsolatedRestoreActor;
415
+ status: TIsolatedRestoreStatus;
416
+ resourceMappings: TIsolatedRestoreResourceMapping[];
417
+ verification: IIsolatedRestoreVerification;
418
+ sourceBackupHold: IIsolatedRestoreSourceBackupHold;
419
+ createdAt: number;
420
+ updatedAt: number;
421
+ expiresAt: number;
422
+ readyAt?: number;
423
+ cleanup?: IIsolatedRestoreCleanup;
424
+ /** Append-only; entries are never replaced when a later phase fails. */
425
+ errors: IIsolatedRestoreError[];
426
+ /** Append-only lifecycle audit trail. */
427
+ auditEvents: IIsolatedRestoreAuditEvent[];
428
+ }
package/ts/data/user.ts CHANGED
@@ -4,18 +4,20 @@ export interface IToken {
4
4
  assignedRoles: string[];
5
5
  }
6
6
 
7
+ export interface IIdentityCredential {
8
+ jwt: string;
9
+ }
10
+
7
11
  /**
8
12
  * an identity is assumed by authentication as a user
9
13
  * an identity is ephemeral and has to be renewed regularly
10
14
  */
11
- export interface IIdentity {
15
+ export interface IIdentity extends IIdentityCredential {
12
16
  name: string;
13
17
  userId: string;
14
18
  type: 'machine' | 'human';
15
19
  role: 'admin' | 'user' | 'api' | 'cluster';
16
20
  expiresAt: number;
17
- /** the jwt token should contain above data for verification */
18
- jwt: string;
19
21
  }
20
22
 
21
23
  export interface IUser {
@@ -27,4 +29,4 @@ export interface IUser {
27
29
  password?: string;
28
30
  tokens?: IToken[];
29
31
  }
30
- }
32
+ }
@@ -6,7 +6,10 @@ import type {
6
6
  IBackupArchiveObject,
7
7
  IBackupRecord,
8
8
  IBackupReplicationResult,
9
+ IIsolatedRestoreNodeState,
10
+ IIsolatedRestoreRecord,
9
11
  TBackupSnapshot,
12
+ TIsolatedRestoreResourceMapping,
10
13
  } from '../data/backup.js';
11
14
  import type { IService } from '../data/service.js';
12
15
  import type { IIdentity } from '../data/user.js';
@@ -214,3 +217,190 @@ extends plugins.typedrequestInterfaces.implementsTR<
214
217
  result?: IArchivePruneResult;
215
218
  };
216
219
  }
220
+
221
+ /**
222
+ * Creates a restore in a new non-runnable data-plane scratch namespace.
223
+ * Cloudly derives clusterId and sourceServiceId from the authoritative backup,
224
+ * atomically acquires its retention hold, and owns every generated target id.
225
+ */
226
+ export interface IReq_Any_Cloudly_CreateIsolatedRestore
227
+ extends plugins.typedrequestInterfaces.implementsTR<
228
+ plugins.typedrequestInterfaces.ITypedRequest,
229
+ IReq_Any_Cloudly_CreateIsolatedRestore
230
+ > {
231
+ method: 'createIsolatedRestore';
232
+ request: {
233
+ identity: IIdentity;
234
+ sourceBackupId: string;
235
+ targetNodeName: string;
236
+ purpose: string;
237
+ /** Caller-generated key; retries return the original restore. */
238
+ idempotencyKey: string;
239
+ /** Requested lifetime; Cloudly applies its configured maximum. */
240
+ ttlMs?: number;
241
+ /** Derived from the authoritative backup. */
242
+ clusterId?: never;
243
+ /** Derived from the authoritative backup. */
244
+ sourceServiceId?: never;
245
+ /** Generated by Cloudly. Explicitly forbidden as caller input. */
246
+ id?: never;
247
+ /** Alias-like caller input is forbidden as well. */
248
+ restoreId?: never;
249
+ /** Legacy runnable-service targeting is forbidden. */
250
+ targetServiceId?: never;
251
+ /** Generated by Cloudly. Explicitly forbidden as caller input. */
252
+ scratchNamespaceId?: never;
253
+ /** Generated by Cloudly. Explicitly forbidden as caller input. */
254
+ stagingArchiveId?: never;
255
+ /** Generated after validating every snapshot in the source backup. */
256
+ resourceMappings?: never;
257
+ };
258
+ response: {
259
+ restore: IIsolatedRestoreRecord;
260
+ };
261
+ }
262
+
263
+ export interface IReq_Any_Cloudly_GetIsolatedRestores
264
+ extends plugins.typedrequestInterfaces.implementsTR<
265
+ plugins.typedrequestInterfaces.ITypedRequest,
266
+ IReq_Any_Cloudly_GetIsolatedRestores
267
+ > {
268
+ method: 'getIsolatedRestores';
269
+ request: {
270
+ identity: IIdentity;
271
+ sourceBackupId?: string;
272
+ sourceServiceId?: string;
273
+ clusterId?: string;
274
+ targetNodeName?: string;
275
+ scratchNamespaceId?: string;
276
+ status?: IIsolatedRestoreRecord['status'];
277
+ includeCleaned?: boolean;
278
+ /** Opaque cursor returned by the previous page. */
279
+ cursor?: string;
280
+ /** Server-capped page size. */
281
+ limit?: number;
282
+ };
283
+ response: {
284
+ restores: IIsolatedRestoreRecord[];
285
+ /** Omitted when this is the final page. */
286
+ nextCursor?: string;
287
+ };
288
+ }
289
+
290
+ export interface IReq_Any_Cloudly_GetIsolatedRestoreById
291
+ extends plugins.typedrequestInterfaces.implementsTR<
292
+ plugins.typedrequestInterfaces.ITypedRequest,
293
+ IReq_Any_Cloudly_GetIsolatedRestoreById
294
+ > {
295
+ method: 'getIsolatedRestoreById';
296
+ request: {
297
+ identity: IIdentity;
298
+ restoreId: string;
299
+ };
300
+ response: {
301
+ restore: IIsolatedRestoreRecord;
302
+ };
303
+ }
304
+
305
+ /**
306
+ * Prepares and stages one isolated restore on an exact cluster node. A missing
307
+ * node state has revision 0; successful mutation returns the next revision.
308
+ */
309
+ export interface IReq_Cloudly_Coreflow_PrepareIsolatedRestore
310
+ extends plugins.typedrequestInterfaces.implementsTR<
311
+ plugins.typedrequestInterfaces.ITypedRequest,
312
+ IReq_Cloudly_Coreflow_PrepareIsolatedRestore
313
+ > {
314
+ method: 'coreflowPrepareIsolatedRestore';
315
+ request: {
316
+ clusterId: string;
317
+ targetNodeName: string;
318
+ restoreId: string;
319
+ expectedRevision: number;
320
+ sourceBackupId: string;
321
+ sourceServiceId: string;
322
+ scratchNamespaceId: string;
323
+ stagingArchiveId: string;
324
+ resourceMappings: TIsolatedRestoreResourceMapping[];
325
+ archiveManifest: IBackupArchiveManifest;
326
+ };
327
+ response: {
328
+ state: IIsolatedRestoreNodeState;
329
+ };
330
+ }
331
+
332
+ /** Read-only status for one exact cluster/node/restore routing key. */
333
+ export interface IReq_Cloudly_Coreflow_GetIsolatedRestoreStatus
334
+ extends plugins.typedrequestInterfaces.implementsTR<
335
+ plugins.typedrequestInterfaces.ITypedRequest,
336
+ IReq_Cloudly_Coreflow_GetIsolatedRestoreStatus
337
+ > {
338
+ method: 'coreflowGetIsolatedRestoreStatus';
339
+ request: {
340
+ clusterId: string;
341
+ targetNodeName: string;
342
+ restoreId: string;
343
+ };
344
+ response: {
345
+ found: boolean;
346
+ state?: IIsolatedRestoreNodeState;
347
+ };
348
+ }
349
+
350
+ export interface IReq_Cloudly_Coreflow_ExecuteIsolatedRestore
351
+ extends plugins.typedrequestInterfaces.implementsTR<
352
+ plugins.typedrequestInterfaces.ITypedRequest,
353
+ IReq_Cloudly_Coreflow_ExecuteIsolatedRestore
354
+ > {
355
+ method: 'coreflowExecuteIsolatedRestore';
356
+ request: {
357
+ clusterId: string;
358
+ targetNodeName: string;
359
+ restoreId: string;
360
+ expectedRevision: number;
361
+ };
362
+ response: {
363
+ state: IIsolatedRestoreNodeState;
364
+ };
365
+ }
366
+
367
+ /**
368
+ * Idempotent cleanup mutation. A cleanup-failed state remains retryable and
369
+ * does not authorize release of the source-backup hold.
370
+ */
371
+ export interface IReq_Cloudly_Coreflow_CleanupIsolatedRestore
372
+ extends plugins.typedrequestInterfaces.implementsTR<
373
+ plugins.typedrequestInterfaces.ITypedRequest,
374
+ IReq_Cloudly_Coreflow_CleanupIsolatedRestore
375
+ > {
376
+ method: 'coreflowCleanupIsolatedRestore';
377
+ request: {
378
+ clusterId: string;
379
+ targetNodeName: string;
380
+ restoreId: string;
381
+ expectedRevision: number;
382
+ };
383
+ response: {
384
+ state: IIsolatedRestoreNodeState;
385
+ };
386
+ }
387
+
388
+ /**
389
+ * Requests idempotent asynchronous cleanup. The restore record is retained as
390
+ * audit evidence and transitions through the canonical cleanup statuses.
391
+ */
392
+ export interface IReq_Any_Cloudly_CleanupIsolatedRestore
393
+ extends plugins.typedrequestInterfaces.implementsTR<
394
+ plugins.typedrequestInterfaces.ITypedRequest,
395
+ IReq_Any_Cloudly_CleanupIsolatedRestore
396
+ > {
397
+ method: 'cleanupIsolatedRestore';
398
+ request: {
399
+ identity: IIdentity;
400
+ restoreId: string;
401
+ reason: string;
402
+ };
403
+ response: {
404
+ restore: IIsolatedRestoreRecord;
405
+ };
406
+ }
@@ -27,7 +27,7 @@ extends plugins.typedrequestInterfaces.implementsTR<
27
27
  > {
28
28
  method: 'getClusterConfig';
29
29
  request: {
30
- identity: userInterfaces.IIdentity;
30
+ identity: userInterfaces.IIdentityCredential;
31
31
  };
32
32
  response: {
33
33
  configData: clusterInterfaces.ICluster;