@serve.zone/interfaces 7.13.0 → 7.15.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,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-06-10 - 7.15.0
4
+
5
+ ### Features
6
+
7
+ - add service migration interfaces and requests (migration)
8
+ - Add service migration data models and export them from the data index
9
+ - Add TypedRequest contracts for starting, listing, and pushing service migration updates
10
+ - Add service placement metadata for pinned, replicated, and held services
11
+
12
+ ## 2026-06-10 - 7.14.0
13
+
14
+ ### Features
15
+
16
+ - add corestore inventory request interfaces (corestore)
17
+ - Add typed request contracts for retrieving corestore inventory from Cloudly and Coreflow.
18
+ - Define corestore resource, service, and node inventory interfaces.
19
+ - Export corestore request interfaces from the requests index.
20
+
3
21
  ## 2026-06-10 - 7.13.0
4
22
 
5
23
  ### Features
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '7.13.0',
6
+ version: '7.15.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
@@ -2,6 +2,7 @@ export * from './cloudlyconfig.js';
2
2
  export * from './cluster.js';
3
3
  export * from './config.js';
4
4
  export * from './deployment.js';
5
+ export * from './migration.js';
5
6
  export * from './dns.js';
6
7
  export * from './docker.js';
7
8
  export * from './domain.js';
@@ -2,6 +2,7 @@ export * from './cloudlyconfig.js';
2
2
  export * from './cluster.js';
3
3
  export * from './config.js';
4
4
  export * from './deployment.js';
5
+ export * from './migration.js';
5
6
  export * from './dns.js';
6
7
  export * from './docker.js';
7
8
  export * from './domain.js';
@@ -25,4 +26,4 @@ export * from './taskexecution.js';
25
26
  export * from './traffic.js';
26
27
  export * from './user.js';
27
28
  export * from './version.js';
28
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLFVBQVUsQ0FBQztBQUN6QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsV0FBVyxDQUFDO0FBQzFCLGNBQWMsY0FBYyxDQUFDIn0=
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsVUFBVSxDQUFDO0FBQ3pCLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsWUFBWSxDQUFDO0FBQzNCLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLFdBQVcsQ0FBQztBQUMxQixjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLG1CQUFtQixDQUFDO0FBQ2xDLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxjQUFjLENBQUMifQ==
@@ -0,0 +1,31 @@
1
+ export type TServiceMigrationStatus = 'running' | 'completed' | 'failed';
2
+ export type TServiceMigrationStepStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
3
+ export type TServiceMigrationStepKey = 'validate' | 'stop-source' | 'snapshot' | 'restore' | 'deploy-target' | 'verify';
4
+ export interface IServiceMigrationStep {
5
+ key: TServiceMigrationStepKey;
6
+ label: string;
7
+ status: TServiceMigrationStepStatus;
8
+ startedAt?: number;
9
+ finishedAt?: number;
10
+ message?: string;
11
+ }
12
+ /**
13
+ * A node-to-node service migration orchestrated by Cloudly:
14
+ * gracefully stop everywhere -> snapshot data on the source ->
15
+ * restore on the target -> deploy pinned to the target -> verify.
16
+ * On failure before deploy, placement rolls back to the source.
17
+ */
18
+ export interface IServiceMigration {
19
+ id: string;
20
+ serviceId: string;
21
+ serviceName: string;
22
+ sourceNodeName: string;
23
+ targetNodeName: string;
24
+ /** Backup archive id used for the data move (migration-<id>). */
25
+ backupId?: string;
26
+ status: TServiceMigrationStatus;
27
+ steps: IServiceMigrationStep[];
28
+ startedAt: number;
29
+ finishedAt?: number;
30
+ error?: string;
31
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9taWdyYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
@@ -17,6 +17,23 @@ export interface IServiceVolume {
17
17
  /** Driver-specific options forwarded to Docker's VolumeDriver.Create request. */
18
18
  options?: Record<string, string>;
19
19
  }
20
+ /**
21
+ * Where a service is allowed to run.
22
+ * - absent or mode 'replicated': the service runs on every node (legacy
23
+ * full-replication behavior).
24
+ * - mode 'pinned' + nodeName: the service runs only on that swarm node;
25
+ * other nodes stop it but preserve local data (volumes, corestore
26
+ * resources) so a migration can move it safely.
27
+ * - hold: the service is stopped on all nodes with data preserved; used by
28
+ * the migration orchestrator between the stop and deploy phases.
29
+ */
30
+ export interface IServicePlacement {
31
+ mode: 'pinned' | 'replicated';
32
+ /** Swarm node hostname for pinned mode. */
33
+ nodeName?: string;
34
+ /** When true, no node runs the service (data preserved everywhere). */
35
+ hold?: boolean;
36
+ }
20
37
  export type TServiceReconciliationStatus = 'running' | 'ready' | 'degraded' | 'failed';
21
38
  export interface IServiceReconciliationStageStatus {
22
39
  stage: string;
@@ -47,6 +64,7 @@ export interface IService {
47
64
  * and archived before a replacement deployment starts.
48
65
  */
49
66
  rollingCapable?: boolean;
67
+ placement?: IServicePlacement;
50
68
  appTemplateId?: string;
51
69
  appTemplateVersion?: string;
52
70
  appStoreUpgradePolicy?: 'manual' | 'notify' | 'auto';
@@ -0,0 +1,45 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { IIdentity } from '../data/user.js';
3
+ /**
4
+ * A provisioned corestore resource (SmartDb database or SmartStorage bucket)
5
+ * as reported by a node's corestore control API.
6
+ */
7
+ export interface ICorestoreResourceInfo {
8
+ capability: 'database' | 'objectstorage';
9
+ provider: string;
10
+ resourceName: string;
11
+ createdAt: number;
12
+ }
13
+ export interface ICorestoreServiceResources {
14
+ serviceId: string;
15
+ serviceName?: string;
16
+ resources: ICorestoreResourceInfo[];
17
+ updatedAt: number;
18
+ }
19
+ /**
20
+ * Corestore inventory of one node (each coreflow node runs its own corestore;
21
+ * the data is node-local, which is what makes node placement matter).
22
+ */
23
+ export interface ICorestoreNodeInventory {
24
+ /** Swarm node hostnames of the reporting coreflow. */
25
+ nodeNames: string[];
26
+ reachable: boolean;
27
+ error?: string;
28
+ services: ICorestoreServiceResources[];
29
+ }
30
+ export interface IReq_Any_Cloudly_GetCorestoreInventory extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetCorestoreInventory> {
31
+ method: 'getCorestoreInventory';
32
+ request: {
33
+ identity: IIdentity;
34
+ };
35
+ response: {
36
+ inventories: ICorestoreNodeInventory[];
37
+ };
38
+ }
39
+ export interface IReq_Cloudly_Coreflow_GetCorestoreInventory extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Cloudly_Coreflow_GetCorestoreInventory> {
40
+ method: 'coreflowGetCorestoreInventory';
41
+ request: Record<string, never>;
42
+ response: {
43
+ inventory: ICorestoreNodeInventory;
44
+ };
45
+ }
@@ -0,0 +1,2 @@
1
+ import * as plugins from '../plugins.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZXN0b3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcmVxdWVzdHMvY29yZXN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDIn0=
@@ -6,6 +6,7 @@ import * as backupRequests from './backup.js';
6
6
  import * as certificateRequests from './certificate.js';
7
7
  import * as clusterRequests from './cluster.js';
8
8
  import * as configRequests from './config.js';
9
+ import * as corestoreRequests from './corestore.js';
9
10
  import * as deploymentRequests from './deployment.js';
10
11
  import * as dnsRequests from './dns.js';
11
12
  import * as domainRequests from './domain.js';
@@ -17,6 +18,7 @@ import * as imageRequests from './image.js';
17
18
  import * as informRequests from './inform.js';
18
19
  import * as logRequests from './log.js';
19
20
  import * as mailRequests from './mail.js';
21
+ import * as migrationRequests from './migration.js';
20
22
  import * as networkRequests from './network.js';
21
23
  import * as nodeRequests from './node.js';
22
24
  import * as platformRequests from './platform.js';
@@ -29,7 +31,7 @@ import * as settingsRequests from './settings.js';
29
31
  import * as statusRequests from './status.js';
30
32
  import * as taskRequests from './task.js';
31
33
  import * as versionRequests from './version.js';
32
- export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, configRequests as config, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, gatewayRequests as gateway, hostedAppRequests as hostedapp, identityRequests as identity, imageRequests as image, informRequests as inform, logRequests as log, mailRequests as mail, networkRequests as network, nodeRequests as node, platformRequests as platform, routingRequests as routing, secretBundleRequests as secretbundle, secretGroupRequests as secretgroup, serverRequests as server, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, };
34
+ export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, configRequests as config, corestoreRequests as corestore, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, gatewayRequests as gateway, hostedAppRequests as hostedapp, identityRequests as identity, imageRequests as image, informRequests as inform, logRequests as log, mailRequests as mail, migrationRequests as migration, networkRequests as network, nodeRequests as node, platformRequests as platform, routingRequests as routing, secretBundleRequests as secretbundle, secretGroupRequests as secretgroup, serverRequests as server, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, };
33
35
  export * from './inform.js';
34
36
  export * from './hostedapp.js';
35
37
  export * from './mail.js';
@@ -7,6 +7,7 @@ import * as backupRequests from './backup.js';
7
7
  import * as certificateRequests from './certificate.js';
8
8
  import * as clusterRequests from './cluster.js';
9
9
  import * as configRequests from './config.js';
10
+ import * as corestoreRequests from './corestore.js';
10
11
  import * as deploymentRequests from './deployment.js';
11
12
  import * as dnsRequests from './dns.js';
12
13
  import * as domainRequests from './domain.js';
@@ -18,6 +19,7 @@ import * as imageRequests from './image.js';
18
19
  import * as informRequests from './inform.js';
19
20
  import * as logRequests from './log.js';
20
21
  import * as mailRequests from './mail.js';
22
+ import * as migrationRequests from './migration.js';
21
23
  import * as networkRequests from './network.js';
22
24
  import * as nodeRequests from './node.js';
23
25
  import * as platformRequests from './platform.js';
@@ -30,8 +32,8 @@ import * as settingsRequests from './settings.js';
30
32
  import * as statusRequests from './status.js';
31
33
  import * as taskRequests from './task.js';
32
34
  import * as versionRequests from './version.js';
33
- export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, configRequests as config, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, gatewayRequests as gateway, hostedAppRequests as hostedapp, identityRequests as identity, imageRequests as image, informRequests as inform, logRequests as log, mailRequests as mail, networkRequests as network, nodeRequests as node, platformRequests as platform, routingRequests as routing, secretBundleRequests as secretbundle, secretGroupRequests as secretgroup, serverRequests as server, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, };
35
+ export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, configRequests as config, corestoreRequests as corestore, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, gatewayRequests as gateway, hostedAppRequests as hostedapp, identityRequests as identity, imageRequests as image, informRequests as inform, logRequests as log, mailRequests as mail, migrationRequests as migration, networkRequests as network, nodeRequests as node, platformRequests as platform, routingRequests as routing, secretBundleRequests as secretbundle, secretGroupRequests as secretgroup, serverRequests as server, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, };
34
36
  export * from './inform.js';
35
37
  export * from './hostedapp.js';
36
38
  export * from './mail.js';
37
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yZXF1ZXN0cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEtBQUssYUFBYSxNQUFNLFlBQVksQ0FBQztBQUM1QyxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssbUJBQW1CLE1BQU0sa0JBQWtCLENBQUM7QUFDeEQsT0FBTyxLQUFLLGVBQWUsTUFBTSxjQUFjLENBQUM7QUFDaEQsT0FBTyxLQUFLLGNBQWMsTUFBTSxhQUFhLENBQUM7QUFDOUMsT0FBTyxLQUFLLGtCQUFrQixNQUFNLGlCQUFpQixDQUFDO0FBQ3RELE9BQU8sS0FBSyxXQUFXLE1BQU0sVUFBVSxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxjQUFjLE1BQU0sYUFBYSxDQUFDO0FBQzlDLE9BQU8sS0FBSyx3QkFBd0IsTUFBTSx1QkFBdUIsQ0FBQztBQUNsRSxPQUFPLEtBQUssZUFBZSxNQUFNLGNBQWMsQ0FBQztBQUNoRCxPQUFPLEtBQUssaUJBQWlCLE1BQU0sZ0JBQWdCLENBQUM7QUFDcEQsT0FBTyxLQUFLLGdCQUFnQixNQUFNLGVBQWUsQ0FBQztBQUNsRCxPQUFPLEtBQUssYUFBYSxNQUFNLFlBQVksQ0FBQztBQUM1QyxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssV0FBVyxNQUFNLFVBQVUsQ0FBQztBQUN4QyxPQUFPLEtBQUssWUFBWSxNQUFNLFdBQVcsQ0FBQztBQUMxQyxPQUFPLEtBQUssZUFBZSxNQUFNLGNBQWMsQ0FBQztBQUNoRCxPQUFPLEtBQUssWUFBWSxNQUFNLFdBQVcsQ0FBQztBQUMxQyxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxlQUFlLE1BQU0sY0FBYyxDQUFDO0FBQ2hELE9BQU8sS0FBSyxvQkFBb0IsTUFBTSxtQkFBbUIsQ0FBQztBQUMxRCxPQUFPLEtBQUssbUJBQW1CLE1BQU0sa0JBQWtCLENBQUM7QUFDeEQsT0FBTyxLQUFLLGNBQWMsTUFBTSxhQUFhLENBQUM7QUFDOUMsT0FBTyxLQUFLLGVBQWUsTUFBTSxjQUFjLENBQUM7QUFDaEQsT0FBTyxLQUFLLGdCQUFnQixNQUFNLGVBQWUsQ0FBQztBQUNsRCxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssWUFBWSxNQUFNLFdBQVcsQ0FBQztBQUMxQyxPQUFPLEtBQUssZUFBZSxNQUFNLGNBQWMsQ0FBQztBQUVoRCxPQUFPLEVBQ0wsYUFBYSxJQUFJLEtBQUssRUFDdEIsZ0JBQWdCLElBQUksUUFBUSxFQUM1QixpQkFBaUIsSUFBSSxTQUFTLEVBQzlCLGNBQWMsSUFBSSxNQUFNLEVBQ3hCLGNBQWMsSUFBSSxNQUFNLEVBQ3hCLG1CQUFtQixJQUFJLFdBQVcsRUFDbEMsZUFBZSxJQUFJLE9BQU8sRUFDMUIsY0FBYyxJQUFJLE1BQU0sRUFDeEIsa0JBQWtCLElBQUksVUFBVSxFQUNoQyxXQUFXLElBQUksR0FBRyxFQUNsQixjQUFjLElBQUksTUFBTSxFQUN4Qix3QkFBd0IsSUFBSSxnQkFBZ0IsRUFDNUMsZUFBZSxJQUFJLE9BQU8sRUFDMUIsaUJBQWlCLElBQUksU0FBUyxFQUM5QixnQkFBZ0IsSUFBSSxRQUFRLEVBQzVCLGFBQWEsSUFBSSxLQUFLLEVBQ3RCLGNBQWMsSUFBSSxNQUFNLEVBQ3hCLFdBQVcsSUFBSSxHQUFHLEVBQ2xCLFlBQVksSUFBSSxJQUFJLEVBQ3BCLGVBQWUsSUFBSSxPQUFPLEVBQzFCLFlBQVksSUFBSSxJQUFJLEVBQ3BCLGdCQUFnQixJQUFJLFFBQVEsRUFDNUIsZUFBZSxJQUFJLE9BQU8sRUFDMUIsb0JBQW9CLElBQUksWUFBWSxFQUNwQyxtQkFBbUIsSUFBSSxXQUFXLEVBQ2xDLGNBQWMsSUFBSSxNQUFNLEVBQ3hCLGVBQWUsSUFBSSxPQUFPLEVBQzFCLGdCQUFnQixJQUFJLFFBQVEsRUFDNUIsY0FBYyxJQUFJLE1BQU0sRUFDeEIsWUFBWSxJQUFJLElBQUksRUFDcEIsZUFBZSxJQUFJLE9BQU8sR0FDM0IsQ0FBQztBQUVGLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxXQUFXLENBQUMifQ==
39
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yZXF1ZXN0cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEtBQUssYUFBYSxNQUFNLFlBQVksQ0FBQztBQUM1QyxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssbUJBQW1CLE1BQU0sa0JBQWtCLENBQUM7QUFDeEQsT0FBTyxLQUFLLGVBQWUsTUFBTSxjQUFjLENBQUM7QUFDaEQsT0FBTyxLQUFLLGNBQWMsTUFBTSxhQUFhLENBQUM7QUFDOUMsT0FBTyxLQUFLLGlCQUFpQixNQUFNLGdCQUFnQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxrQkFBa0IsTUFBTSxpQkFBaUIsQ0FBQztBQUN0RCxPQUFPLEtBQUssV0FBVyxNQUFNLFVBQVUsQ0FBQztBQUN4QyxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssd0JBQXdCLE1BQU0sdUJBQXVCLENBQUM7QUFDbEUsT0FBTyxLQUFLLGVBQWUsTUFBTSxjQUFjLENBQUM7QUFDaEQsT0FBTyxLQUFLLGlCQUFpQixNQUFNLGdCQUFnQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxnQkFBZ0IsTUFBTSxlQUFlLENBQUM7QUFDbEQsT0FBTyxLQUFLLGFBQWEsTUFBTSxZQUFZLENBQUM7QUFDNUMsT0FBTyxLQUFLLGNBQWMsTUFBTSxhQUFhLENBQUM7QUFDOUMsT0FBTyxLQUFLLFdBQVcsTUFBTSxVQUFVLENBQUM7QUFDeEMsT0FBTyxLQUFLLFlBQVksTUFBTSxXQUFXLENBQUM7QUFDMUMsT0FBTyxLQUFLLGlCQUFpQixNQUFNLGdCQUFnQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxlQUFlLE1BQU0sY0FBYyxDQUFDO0FBQ2hELE9BQU8sS0FBSyxZQUFZLE1BQU0sV0FBVyxDQUFDO0FBQzFDLE9BQU8sS0FBSyxnQkFBZ0IsTUFBTSxlQUFlLENBQUM7QUFDbEQsT0FBTyxLQUFLLGVBQWUsTUFBTSxjQUFjLENBQUM7QUFDaEQsT0FBTyxLQUFLLG9CQUFvQixNQUFNLG1CQUFtQixDQUFDO0FBQzFELE9BQU8sS0FBSyxtQkFBbUIsTUFBTSxrQkFBa0IsQ0FBQztBQUN4RCxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssZUFBZSxNQUFNLGNBQWMsQ0FBQztBQUNoRCxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxjQUFjLE1BQU0sYUFBYSxDQUFDO0FBQzlDLE9BQU8sS0FBSyxZQUFZLE1BQU0sV0FBVyxDQUFDO0FBQzFDLE9BQU8sS0FBSyxlQUFlLE1BQU0sY0FBYyxDQUFDO0FBRWhELE9BQU8sRUFDTCxhQUFhLElBQUksS0FBSyxFQUN0QixnQkFBZ0IsSUFBSSxRQUFRLEVBQzVCLGlCQUFpQixJQUFJLFNBQVMsRUFDOUIsY0FBYyxJQUFJLE1BQU0sRUFDeEIsY0FBYyxJQUFJLE1BQU0sRUFDeEIsbUJBQW1CLElBQUksV0FBVyxFQUNsQyxlQUFlLElBQUksT0FBTyxFQUMxQixjQUFjLElBQUksTUFBTSxFQUN4QixpQkFBaUIsSUFBSSxTQUFTLEVBQzlCLGtCQUFrQixJQUFJLFVBQVUsRUFDaEMsV0FBVyxJQUFJLEdBQUcsRUFDbEIsY0FBYyxJQUFJLE1BQU0sRUFDeEIsd0JBQXdCLElBQUksZ0JBQWdCLEVBQzVDLGVBQWUsSUFBSSxPQUFPLEVBQzFCLGlCQUFpQixJQUFJLFNBQVMsRUFDOUIsZ0JBQWdCLElBQUksUUFBUSxFQUM1QixhQUFhLElBQUksS0FBSyxFQUN0QixjQUFjLElBQUksTUFBTSxFQUN4QixXQUFXLElBQUksR0FBRyxFQUNsQixZQUFZLElBQUksSUFBSSxFQUNwQixpQkFBaUIsSUFBSSxTQUFTLEVBQzlCLGVBQWUsSUFBSSxPQUFPLEVBQzFCLFlBQVksSUFBSSxJQUFJLEVBQ3BCLGdCQUFnQixJQUFJLFFBQVEsRUFDNUIsZUFBZSxJQUFJLE9BQU8sRUFDMUIsb0JBQW9CLElBQUksWUFBWSxFQUNwQyxtQkFBbUIsSUFBSSxXQUFXLEVBQ2xDLGNBQWMsSUFBSSxNQUFNLEVBQ3hCLGVBQWUsSUFBSSxPQUFPLEVBQzFCLGdCQUFnQixJQUFJLFFBQVEsRUFDNUIsY0FBYyxJQUFJLE1BQU0sRUFDeEIsWUFBWSxJQUFJLElBQUksRUFDcEIsZUFBZSxJQUFJLE9BQU8sR0FDM0IsQ0FBQztBQUVGLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxXQUFXLENBQUMifQ==
@@ -0,0 +1,35 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { IServiceMigration } from '../data/migration.js';
3
+ import type { IIdentity } from '../data/user.js';
4
+ export interface IReq_Any_Cloudly_MigrateServiceToNode extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_MigrateServiceToNode> {
5
+ method: 'migrateServiceToNode';
6
+ request: {
7
+ identity: IIdentity;
8
+ serviceId: string;
9
+ /** Swarm node hostname holding the authoritative data copy. */
10
+ sourceNodeName: string;
11
+ /** Swarm node hostname the service moves to. */
12
+ targetNodeName: string;
13
+ };
14
+ response: {
15
+ migration: IServiceMigration;
16
+ };
17
+ }
18
+ export interface IReq_Any_Cloudly_GetServiceMigrations extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetServiceMigrations> {
19
+ method: 'getServiceMigrations';
20
+ request: {
21
+ identity: IIdentity;
22
+ /** Limit to one service; absent returns all migrations. */
23
+ serviceId?: string;
24
+ };
25
+ response: {
26
+ migrations: IServiceMigration[];
27
+ };
28
+ }
29
+ export interface IReq_Cloudly_Any_PushServiceMigrationUpdate extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Cloudly_Any_PushServiceMigrationUpdate> {
30
+ method: 'pushServiceMigrationUpdate';
31
+ request: {
32
+ migration: IServiceMigration;
33
+ };
34
+ response: Record<string, never>;
35
+ }
@@ -0,0 +1,2 @@
1
+ import * as plugins from '../plugins.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcmVxdWVzdHMvbWlncmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDIn0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "7.13.0",
3
+ "version": "7.15.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.",
6
6
  "exports": {
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '7.13.0',
6
+ version: '7.15.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
package/ts/data/index.ts CHANGED
@@ -2,6 +2,7 @@ export * from './cloudlyconfig.js';
2
2
  export * from './cluster.js';
3
3
  export * from './config.js';
4
4
  export * from './deployment.js';
5
+ export * from './migration.js';
5
6
  export * from './dns.js';
6
7
  export * from './docker.js';
7
8
  export * from './domain.js';
@@ -0,0 +1,41 @@
1
+ export type TServiceMigrationStatus = 'running' | 'completed' | 'failed';
2
+
3
+ export type TServiceMigrationStepStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
4
+
5
+ export type TServiceMigrationStepKey =
6
+ | 'validate'
7
+ | 'stop-source'
8
+ | 'snapshot'
9
+ | 'restore'
10
+ | 'deploy-target'
11
+ | 'verify';
12
+
13
+ export interface IServiceMigrationStep {
14
+ key: TServiceMigrationStepKey;
15
+ label: string;
16
+ status: TServiceMigrationStepStatus;
17
+ startedAt?: number;
18
+ finishedAt?: number;
19
+ message?: string;
20
+ }
21
+
22
+ /**
23
+ * A node-to-node service migration orchestrated by Cloudly:
24
+ * gracefully stop everywhere -> snapshot data on the source ->
25
+ * restore on the target -> deploy pinned to the target -> verify.
26
+ * On failure before deploy, placement rolls back to the source.
27
+ */
28
+ export interface IServiceMigration {
29
+ id: string;
30
+ serviceId: string;
31
+ serviceName: string;
32
+ sourceNodeName: string;
33
+ targetNodeName: string;
34
+ /** Backup archive id used for the data move (migration-<id>). */
35
+ backupId?: string;
36
+ status: TServiceMigrationStatus;
37
+ steps: IServiceMigrationStep[];
38
+ startedAt: number;
39
+ finishedAt?: number;
40
+ error?: string;
41
+ }
@@ -19,6 +19,24 @@ export interface IServiceVolume {
19
19
  options?: Record<string, string>;
20
20
  }
21
21
 
22
+ /**
23
+ * Where a service is allowed to run.
24
+ * - absent or mode 'replicated': the service runs on every node (legacy
25
+ * full-replication behavior).
26
+ * - mode 'pinned' + nodeName: the service runs only on that swarm node;
27
+ * other nodes stop it but preserve local data (volumes, corestore
28
+ * resources) so a migration can move it safely.
29
+ * - hold: the service is stopped on all nodes with data preserved; used by
30
+ * the migration orchestrator between the stop and deploy phases.
31
+ */
32
+ export interface IServicePlacement {
33
+ mode: 'pinned' | 'replicated';
34
+ /** Swarm node hostname for pinned mode. */
35
+ nodeName?: string;
36
+ /** When true, no node runs the service (data preserved everywhere). */
37
+ hold?: boolean;
38
+ }
39
+
22
40
  export type TServiceReconciliationStatus = 'running' | 'ready' | 'degraded' | 'failed';
23
41
 
24
42
  export interface IServiceReconciliationStageStatus {
@@ -53,6 +71,7 @@ export interface IService {
53
71
  * and archived before a replacement deployment starts.
54
72
  */
55
73
  rollingCapable?: boolean;
74
+ placement?: IServicePlacement;
56
75
  appTemplateId?: string;
57
76
  appTemplateVersion?: string;
58
77
  appStoreUpgradePolicy?: 'manual' | 'notify' | 'auto';
@@ -0,0 +1,58 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { IIdentity } from '../data/user.js';
3
+
4
+ /**
5
+ * A provisioned corestore resource (SmartDb database or SmartStorage bucket)
6
+ * as reported by a node's corestore control API.
7
+ */
8
+ export interface ICorestoreResourceInfo {
9
+ capability: 'database' | 'objectstorage';
10
+ provider: string;
11
+ resourceName: string;
12
+ createdAt: number;
13
+ }
14
+
15
+ export interface ICorestoreServiceResources {
16
+ serviceId: string;
17
+ serviceName?: string;
18
+ resources: ICorestoreResourceInfo[];
19
+ updatedAt: number;
20
+ }
21
+
22
+ /**
23
+ * Corestore inventory of one node (each coreflow node runs its own corestore;
24
+ * the data is node-local, which is what makes node placement matter).
25
+ */
26
+ export interface ICorestoreNodeInventory {
27
+ /** Swarm node hostnames of the reporting coreflow. */
28
+ nodeNames: string[];
29
+ reachable: boolean;
30
+ error?: string;
31
+ services: ICorestoreServiceResources[];
32
+ }
33
+
34
+ export interface IReq_Any_Cloudly_GetCorestoreInventory
35
+ extends plugins.typedrequestInterfaces.implementsTR<
36
+ plugins.typedrequestInterfaces.ITypedRequest,
37
+ IReq_Any_Cloudly_GetCorestoreInventory
38
+ > {
39
+ method: 'getCorestoreInventory';
40
+ request: {
41
+ identity: IIdentity;
42
+ };
43
+ response: {
44
+ inventories: ICorestoreNodeInventory[];
45
+ };
46
+ }
47
+
48
+ export interface IReq_Cloudly_Coreflow_GetCorestoreInventory
49
+ extends plugins.typedrequestInterfaces.implementsTR<
50
+ plugins.typedrequestInterfaces.ITypedRequest,
51
+ IReq_Cloudly_Coreflow_GetCorestoreInventory
52
+ > {
53
+ method: 'coreflowGetCorestoreInventory';
54
+ request: Record<string, never>;
55
+ response: {
56
+ inventory: ICorestoreNodeInventory;
57
+ };
58
+ }
@@ -8,6 +8,7 @@ import * as backupRequests from './backup.js';
8
8
  import * as certificateRequests from './certificate.js';
9
9
  import * as clusterRequests from './cluster.js';
10
10
  import * as configRequests from './config.js';
11
+ import * as corestoreRequests from './corestore.js';
11
12
  import * as deploymentRequests from './deployment.js';
12
13
  import * as dnsRequests from './dns.js';
13
14
  import * as domainRequests from './domain.js';
@@ -19,6 +20,7 @@ import * as imageRequests from './image.js';
19
20
  import * as informRequests from './inform.js';
20
21
  import * as logRequests from './log.js';
21
22
  import * as mailRequests from './mail.js';
23
+ import * as migrationRequests from './migration.js';
22
24
  import * as networkRequests from './network.js';
23
25
  import * as nodeRequests from './node.js';
24
26
  import * as platformRequests from './platform.js';
@@ -41,6 +43,7 @@ export {
41
43
  certificateRequests as certificate,
42
44
  clusterRequests as cluster,
43
45
  configRequests as config,
46
+ corestoreRequests as corestore,
44
47
  deploymentRequests as deployment,
45
48
  dnsRequests as dns,
46
49
  domainRequests as domain,
@@ -52,6 +55,7 @@ export {
52
55
  informRequests as inform,
53
56
  logRequests as log,
54
57
  mailRequests as mail,
58
+ migrationRequests as migration,
55
59
  networkRequests as network,
56
60
  nodeRequests as node,
57
61
  platformRequests as platform,
@@ -0,0 +1,50 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { IServiceMigration } from '../data/migration.js';
3
+ import type { IIdentity } from '../data/user.js';
4
+
5
+ export interface IReq_Any_Cloudly_MigrateServiceToNode
6
+ extends plugins.typedrequestInterfaces.implementsTR<
7
+ plugins.typedrequestInterfaces.ITypedRequest,
8
+ IReq_Any_Cloudly_MigrateServiceToNode
9
+ > {
10
+ method: 'migrateServiceToNode';
11
+ request: {
12
+ identity: IIdentity;
13
+ serviceId: string;
14
+ /** Swarm node hostname holding the authoritative data copy. */
15
+ sourceNodeName: string;
16
+ /** Swarm node hostname the service moves to. */
17
+ targetNodeName: string;
18
+ };
19
+ response: {
20
+ migration: IServiceMigration;
21
+ };
22
+ }
23
+
24
+ export interface IReq_Any_Cloudly_GetServiceMigrations
25
+ extends plugins.typedrequestInterfaces.implementsTR<
26
+ plugins.typedrequestInterfaces.ITypedRequest,
27
+ IReq_Any_Cloudly_GetServiceMigrations
28
+ > {
29
+ method: 'getServiceMigrations';
30
+ request: {
31
+ identity: IIdentity;
32
+ /** Limit to one service; absent returns all migrations. */
33
+ serviceId?: string;
34
+ };
35
+ response: {
36
+ migrations: IServiceMigration[];
37
+ };
38
+ }
39
+
40
+ export interface IReq_Cloudly_Any_PushServiceMigrationUpdate
41
+ extends plugins.typedrequestInterfaces.implementsTR<
42
+ plugins.typedrequestInterfaces.ITypedRequest,
43
+ IReq_Cloudly_Any_PushServiceMigrationUpdate
44
+ > {
45
+ method: 'pushServiceMigrationUpdate';
46
+ request: {
47
+ migration: IServiceMigration;
48
+ };
49
+ response: Record<string, never>;
50
+ }