@serve.zone/interfaces 32.12.0 → 32.14.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.
@@ -17,6 +17,7 @@ export * from './docker.js';
17
17
  export * from './domain.js';
18
18
  export * from './event.js';
19
19
  export * from './externalregistry.js';
20
+ export * from './fleetcutover.js';
20
21
  export * from './gateway.js';
21
22
  export * from './hostedapp.js';
22
23
  export * from './image.js';
@@ -17,6 +17,7 @@ export * from './docker.js';
17
17
  export * from './domain.js';
18
18
  export * from './event.js';
19
19
  export * from './externalregistry.js';
20
+ export * from './fleetcutover.js';
20
21
  export * from './gateway.js';
21
22
  export * from './hostedapp.js';
22
23
  export * from './image.js';
@@ -61,4 +62,4 @@ export * from './traffic.js';
61
62
  export * from './user.js';
62
63
  export * from './version.js';
63
64
  export * from './webpush.js';
64
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFVBQVUsQ0FBQztBQUN6QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLHdCQUF3QixDQUFDO0FBRXZDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsV0FBVyxDQUFDO0FBQzFCLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsY0FBYyxDQUFDIn0=
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFVBQVUsQ0FBQztBQUN6QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLFdBQVcsQ0FBQztBQUMxQixjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsd0JBQXdCLENBQUM7QUFFdkMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxjQUFjLENBQUMifQ==
@@ -0,0 +1,141 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { IIdentityCredential } from '../data/user.js';
3
+ import type { IClusterRuntime } from '../data/clusterruntime.js';
4
+ import type { IServiceRuntimeSpec } from '../data/serviceruntime.js';
5
+ import type { IFleetCutoverAcceptedEvidenceReference, IFleetCutoverCorestoreAdoptionReceipt, IFleetCutoverIngressDesignation, IFleetCutoverIngressPreparationRequest, IFleetCutoverIngressAuthority, IFleetCutoverScope, IFleetCutoverScopeClassificationRequest, IFleetCutoverVolumeHandoffIntent, TFleetCutoverPhaseAdvance, TFleetCutoverRuntimeSpecRelease, TFleetCutoverVolumeFence } from '../data/fleetcutover.js';
6
+ export interface IReq_Any_Cloudly_GetFleetCutoverScope extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetFleetCutoverScope> {
7
+ method: 'getFleetCutoverScope';
8
+ request: {
9
+ identity: IIdentityCredential;
10
+ clusterId: string;
11
+ };
12
+ response: {
13
+ scope: IFleetCutoverScope | null;
14
+ };
15
+ }
16
+ /**
17
+ * The administrator classifies the exact current census candidate. Cloudly compares every entry
18
+ * with its current service, platform-service, credential, and storage authority before it may
19
+ * persist a complete scope; the request itself is no proof of those facts.
20
+ */
21
+ export interface IReq_Admin_Cloudly_ClassifyFleetCutoverScope extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Admin_Cloudly_ClassifyFleetCutoverScope> {
22
+ method: 'classifyFleetCutoverScope';
23
+ request: {
24
+ identity: IIdentityCredential;
25
+ classification: IFleetCutoverScopeClassificationRequest;
26
+ };
27
+ response: {
28
+ scope: IFleetCutoverScope;
29
+ };
30
+ }
31
+ /**
32
+ * Forward-only legal phase CAS. All receipt references are dereferenced by Cloudly in the same
33
+ * transaction; caller-supplied records or booleans never satisfy a cutover condition.
34
+ */
35
+ export interface IReq_Admin_Cloudly_AdvanceFleetCutoverPhase extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Admin_Cloudly_AdvanceFleetCutoverPhase> {
36
+ method: 'advanceFleetCutoverPhase';
37
+ request: {
38
+ identity: IIdentityCredential;
39
+ advance: TFleetCutoverPhaseAdvance;
40
+ };
41
+ response: {
42
+ runtime: IClusterRuntime;
43
+ replayed: boolean;
44
+ };
45
+ }
46
+ /**
47
+ * Cloudly designates one existing live service as the new ingress before assignment. It accepts
48
+ * only current owner state and creates the managed launcher bearer and designation atomically.
49
+ */
50
+ export interface IReq_Admin_Cloudly_PrepareFleetCutoverIngress extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Admin_Cloudly_PrepareFleetCutoverIngress> {
51
+ method: 'prepareFleetCutoverIngress';
52
+ request: {
53
+ identity: IIdentityCredential;
54
+ preparation: IFleetCutoverIngressPreparationRequest;
55
+ };
56
+ response: {
57
+ designation: IFleetCutoverIngressDesignation;
58
+ /** The resulting exact-cluster spec, still held after preparation. */
59
+ spec: IServiceRuntimeSpec;
60
+ replayed: boolean;
61
+ };
62
+ }
63
+ /**
64
+ * The only cutover-specific hold release. Ingress releases first under an accepted empty public
65
+ * port policy; applications require the accepted ingress/port/route authority assembled later.
66
+ */
67
+ export interface IReq_Admin_Cloudly_ReleaseFleetCutoverRuntimeSpec extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Admin_Cloudly_ReleaseFleetCutoverRuntimeSpec> {
68
+ method: 'releaseFleetCutoverRuntimeSpec';
69
+ request: {
70
+ identity: IIdentityCredential;
71
+ release: TFleetCutoverRuntimeSpecRelease;
72
+ };
73
+ response: {
74
+ spec: IServiceRuntimeSpec;
75
+ replayed: boolean;
76
+ };
77
+ }
78
+ export interface IReq_Any_Cloudly_GetFleetCutoverIngressAuthority extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetFleetCutoverIngressAuthority> {
79
+ method: 'getFleetCutoverIngressAuthority';
80
+ request: {
81
+ identity: IIdentityCredential;
82
+ clusterId: string;
83
+ };
84
+ response: {
85
+ authority: IFleetCutoverIngressAuthority | null;
86
+ };
87
+ }
88
+ /** Root-local only. Holding an intent creates negative storage authority and no runtime session. */
89
+ export interface IReq_PalletLocal_Pallet_HoldFleetCutoverVolumeFence extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_PalletLocal_Pallet_HoldFleetCutoverVolumeFence> {
90
+ method: 'holdFleetCutoverVolumeFence';
91
+ request: {
92
+ fenceId: string;
93
+ handoffIntent: IFleetCutoverVolumeHandoffIntent;
94
+ };
95
+ response: {
96
+ fence: Extract<TFleetCutoverVolumeFence, {
97
+ state: 'held';
98
+ }>;
99
+ };
100
+ }
101
+ export interface IReq_PalletLocal_Pallet_GetFleetCutoverVolumeFence extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_PalletLocal_Pallet_GetFleetCutoverVolumeFence> {
102
+ method: 'getFleetCutoverVolumeFence';
103
+ request: {
104
+ fenceId: string;
105
+ };
106
+ response: {
107
+ fence: TFleetCutoverVolumeFence | null;
108
+ };
109
+ }
110
+ /**
111
+ * Pallet consumes the local fence only around a current accepted Corestore adoption result. The
112
+ * receipt carries the real ready storage-claim reference; the earlier handoff intent does not.
113
+ */
114
+ export interface IReq_PalletLocal_Pallet_ConsumeFleetCutoverVolumeFence extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_PalletLocal_Pallet_ConsumeFleetCutoverVolumeFence> {
115
+ method: 'consumeFleetCutoverVolumeFence';
116
+ request: {
117
+ fence: IFleetCutoverAcceptedEvidenceReference;
118
+ adoption: IFleetCutoverCorestoreAdoptionReceipt;
119
+ };
120
+ response: {
121
+ fence: Extract<TFleetCutoverVolumeFence, {
122
+ state: 'consumed';
123
+ }>;
124
+ };
125
+ }
126
+ /**
127
+ * Corestore owns the one-shot initial lineage/RWO CAS. The local caller supplies the held fence
128
+ * and server-owned handoff intent; Corestore returns the claim only after its provider is ready.
129
+ */
130
+ export interface IReq_Pallet_Corestore_AdoptFleetCutoverVolume extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Pallet_Corestore_AdoptFleetCutoverVolume> {
131
+ method: 'adoptFleetCutoverVolume';
132
+ request: {
133
+ handoffIntent: IFleetCutoverVolumeHandoffIntent;
134
+ palletFence: Extract<TFleetCutoverVolumeFence, {
135
+ state: 'held';
136
+ }>;
137
+ };
138
+ response: {
139
+ adoption: IFleetCutoverCorestoreAdoptionReceipt;
140
+ };
141
+ }
@@ -0,0 +1,2 @@
1
+ import * as plugins from '../plugins.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxlZXRjdXRvdmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcmVxdWVzdHMvZmxlZXRjdXRvdmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDIn0=
@@ -14,6 +14,7 @@ import * as deploymentRequests from './deployment.js';
14
14
  import * as dnsRequests from './dns.js';
15
15
  import * as domainRequests from './domain.js';
16
16
  import * as externalRegistryRequests from './externalregistry.js';
17
+ import * as fleetCutoverRequests from './fleetcutover.js';
17
18
  import * as gatewayRequests from './gateway.js';
18
19
  import * as hostedAppRequests from './hostedapp.js';
19
20
  import * as identityRequests from './identity.js';
@@ -35,7 +36,7 @@ import * as statusRequests from './status.js';
35
36
  import * as taskRequests from './task.js';
36
37
  import * as versionRequests from './version.js';
37
38
  import * as webPushRequests from './webpush.js';
38
- export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, clusterIngressRequests as clusteringress, configRequests as config, coreMailRequests as coremail, coreMailAdminRequests as coremailAdmin, 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, palletRequests as pallet, platformRequests as platform, routingRequests as routing, runtimeSessionRequests as runtimesession, secretRequests as secret, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, webPushRequests as webpush, };
39
+ export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, clusterIngressRequests as clusteringress, configRequests as config, coreMailRequests as coremail, coreMailAdminRequests as coremailAdmin, corestoreRequests as corestore, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, fleetCutoverRequests as fleetcutover, 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, palletRequests as pallet, platformRequests as platform, routingRequests as routing, runtimeSessionRequests as runtimesession, secretRequests as secret, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, webPushRequests as webpush, };
39
40
  export * from './inform.js';
40
41
  export * from './hostedapp.js';
41
42
  export * from './mail.js';
@@ -15,6 +15,7 @@ import * as deploymentRequests from './deployment.js';
15
15
  import * as dnsRequests from './dns.js';
16
16
  import * as domainRequests from './domain.js';
17
17
  import * as externalRegistryRequests from './externalregistry.js';
18
+ import * as fleetCutoverRequests from './fleetcutover.js';
18
19
  import * as gatewayRequests from './gateway.js';
19
20
  import * as hostedAppRequests from './hostedapp.js';
20
21
  import * as identityRequests from './identity.js';
@@ -36,9 +37,9 @@ import * as statusRequests from './status.js';
36
37
  import * as taskRequests from './task.js';
37
38
  import * as versionRequests from './version.js';
38
39
  import * as webPushRequests from './webpush.js';
39
- export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, clusterIngressRequests as clusteringress, configRequests as config, coreMailRequests as coremail, coreMailAdminRequests as coremailAdmin, 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, palletRequests as pallet, platformRequests as platform, routingRequests as routing, runtimeSessionRequests as runtimesession, secretRequests as secret, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, webPushRequests as webpush, };
40
+ export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, clusterIngressRequests as clusteringress, configRequests as config, coreMailRequests as coremail, coreMailAdminRequests as coremailAdmin, corestoreRequests as corestore, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, fleetCutoverRequests as fleetcutover, 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, palletRequests as pallet, platformRequests as platform, routingRequests as routing, runtimeSessionRequests as runtimesession, secretRequests as secret, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, webPushRequests as webpush, };
40
41
  export * from './inform.js';
41
42
  export * from './hostedapp.js';
42
43
  export * from './mail.js';
43
44
  export * from './webpush.js';
44
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yZXF1ZXN0cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEtBQUssYUFBYSxNQUFNLFlBQVksQ0FBQztBQUM1QyxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssbUJBQW1CLE1BQU0sa0JBQWtCLENBQUM7QUFDeEQsT0FBTyxLQUFLLGVBQWUsTUFBTSxjQUFjLENBQUM7QUFDaEQsT0FBTyxLQUFLLHNCQUFzQixNQUFNLHFCQUFxQixDQUFDO0FBQzlELE9BQU8sS0FBSyxjQUFjLE1BQU0sYUFBYSxDQUFDO0FBQzlDLE9BQU8sS0FBSyxnQkFBZ0IsTUFBTSxlQUFlLENBQUM7QUFDbEQsT0FBTyxLQUFLLHFCQUFxQixNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssa0JBQWtCLE1BQU0saUJBQWlCLENBQUM7QUFDdEQsT0FBTyxLQUFLLFdBQVcsTUFBTSxVQUFVLENBQUM7QUFDeEMsT0FBTyxLQUFLLGNBQWMsTUFBTSxhQUFhLENBQUM7QUFDOUMsT0FBTyxLQUFLLHdCQUF3QixNQUFNLHVCQUF1QixDQUFDO0FBQ2xFLE9BQU8sS0FBSyxlQUFlLE1BQU0sY0FBYyxDQUFDO0FBQ2hELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxhQUFhLE1BQU0sWUFBWSxD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
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yZXF1ZXN0cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEtBQUssYUFBYSxNQUFNLFlBQVksQ0FBQztBQUM1QyxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssbUJBQW1CLE1BQU0sa0JBQWtCLENBQUM7QUFDeEQsT0FBTyxLQUFLLGVBQWUsTUFBTSxjQUFjLENBQUM7QUFDaEQsT0FBTyxLQUFLLHNCQUFzQixNQUFNLHFCQUFxQixDQUFDO0FBQzlELE9BQU8sS0FBSyxjQUFjLE1BQU0sYUFBYSxDQUFDO0FBQzlDLE9BQU8sS0FBSyxnQkFBZ0IsTUFBTSxlQUFlLENBQUM7QUFDbEQsT0FBTyxLQUFLLHFCQUFxQixNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssa0JBQWtCLE1BQU0saUJBQWlCLENBQUM7QUFDdEQsT0FBTyxLQUFLLFdBQVcsTUFBTSxVQUFVLENBQUM7QUFDeEMsT0FBTyxLQUFLLGNBQWMsTUFBTSxhQUFhLENBQUM7QUFDOUMsT0FBTyxLQUFLLHdCQUF3QixNQUFNLHVCQUF1QixDQUFDO0FBQ2xFLE9BQU8sS0FBSyxvQkFBb0IsTUFBTSxtQkFBbUIsQ0FBQztBQUMxRCxPQUFPLEtBQUssZUFBZSxNQUFNLGNBQWMsQ0FBQztBQUNoRCxPQUFPLEtBQUssaUJBQWlCLE1BQU0sZ0JBQWdCLENBQUM7QUFDcEQsT0FBTyxLQUFLLGdCQUFnQixNQUFNLGVB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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "32.12.0",
3
+ "version": "32.14.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.",
6
6
  "exports": {
package/readme.md CHANGED
@@ -173,6 +173,10 @@ bodies and a pallet node posts this one, and the family retires with coreflow
173
173
  rather than with this release. `ISparkSwarmNodeHeartbeatRequest` is now owned here,
174
174
  so Cloudly and Spark no longer carry private copies of it, and every Swarm-era body
175
175
  — request and answer alike — carries `protocol` and is judged in the same order.
176
+ For fleet cutover, that same observation may carry a bounded local Docker snapshot from the
177
+ reporting node and, only when control is available, a manager-visible service/task snapshot. The
178
+ existing node-token, reporter-session, sequence, digest and accepted-receipt rules authenticate
179
+ both; no separate fleet-report route exists.
176
180
 
177
181
  Each of the four routes has its validator here, so a server never writes its own
178
182
  member checks: `data.validateSparkSwarmNodeHeartbeatRequest`,
@@ -1035,6 +1039,131 @@ the record. Which phase may follow which belongs to the cutover, whose requests
1035
1039
  (`service-multi-cluster-scope`, `service-authority-unsupported`, `platform-binding-present`) name
1036
1040
  the `serviceId`.
1037
1041
 
1042
+ ### Fleet Runtime Cutover Authority
1043
+
1044
+ `data.IFleetCutoverCensus` is Cloudly's accepted, Spark-authenticated Docker census. It carries
1045
+ only immutable Docker service/spec identity, exact mode and replica count, hashed constraint
1046
+ identity, the ownership labels used by the cutover, exact tasks and value-free mounts. A manager
1047
+ reports only manager-visible `/nodes`, `/services` and `/tasks` state. Every node separately reports
1048
+ its own complete local physical-container list through the existing authenticated
1049
+ `sparkSwarmNodeContracts.swarmObservation` route; a manager never attests remote Docker-daemon
1050
+ contents. The local list is fenced by exact sorted container-ID set digests read before and after
1051
+ all bounded inspect calls, so a container appearing or disappearing during inspection refuses the
1052
+ snapshot. The accepted census references two consecutive manager observations with identical
1053
+ Swarm and inventory digests and one current accepted local observation for every target node.
1054
+ Every reference preserves the authenticating node, credential generation, reporter session,
1055
+ sequence, observation time and fixed `freshUntil`; assembling a later census cannot renew an old
1056
+ observation. It never transports environment, arbitrary labels, mount paths, volume names,
1057
+ registry credentials or secret values.
1058
+
1059
+ Mount identity has three explicit canonical domains. `serve.zone/fleet-cutover-mount-source-identity`
1060
+ hashes `{ type, source }`, where `source` is the exact UTF-8 `Mount.Source` returned by Docker,
1061
+ including an empty string. `serve.zone/fleet-cutover-mount-target-identity` hashes `{ target }`,
1062
+ where `target` is the exact UTF-8 `Mount.Destination`. `serve.zone/fleet-cutover-mount-identity`
1063
+ then hashes `{ type, classification, sourceIdentityDigest, targetIdentityDigest, readOnly }`.
1064
+ All three use strict canonical JSON and no case, slash, path, volume-name or alias normalization.
1065
+ Only the digests and classification cross the wire. `unknown` type/classification remains visible
1066
+ and prevents Cloudly accepting a complete scope; missing, unmanaged or conflicting service/container
1067
+ ownership also prevents completion rather than omitting the container. Structural validation does
1068
+ not establish freshness, authentication, manager consensus, ownership or Docker truth; Cloudly
1069
+ establishes those policy facts while dereferencing the accepted observations.
1070
+
1071
+ `data.IFleetCutoverScope` is the server-owned authoritative service set. It starts `incomplete`;
1072
+ every `complete` entry binds an exact Docker service id to the current service authority and an
1073
+ accepted classification authority. `unknown` cannot appear in a complete structural snapshot.
1074
+ An authenticated administrator may submit `IFleetCutoverScopeClassificationRequest` against the
1075
+ exact current census, including for an unlabeled legacy Coretraffic or Corestore service. Cloudly
1076
+ still compares the declaration with current service, platform-service, credential, storage and
1077
+ census authority before accepting it. A classification is an operator decision, never a client
1078
+ proof boolean or a service-name inference.
1079
+
1080
+ `data.TFleetCutoverPhaseAdvance` permits only `swarm -> draining -> switching -> pallet` and carries
1081
+ opaque references to owner-accepted records. `requests.fleetcutover.advanceFleetCutoverPhase`
1082
+ dereferences and joins them inside Cloudly's phase CAS. Leaving `draining` requires the accepted
1083
+ fresh census/quiescence decision, the complete current scope and target set, every runtime spec
1084
+ held, and the accepted set of root-local volume fences. Entering `pallet` still requires every
1085
+ spec held. `switching` grants session and network preparation only; it runs no service. Structural
1086
+ snapshots enforce the closed forward shape but do not claim the referenced records exist or are
1087
+ current.
1088
+
1089
+ Before the first `swarm -> draining` CAS, Spark starts the replacement Coreflow32 relay as the
1090
+ exact Docker service/spec/image, delivers only its new generation-bearing credential and obtains
1091
+ the live accepted relay registration. Cloudly then revokes the old credential and accepts the
1092
+ current Spark bundle/unit/configuration and old-mode refusal evidence. This is a pre-switch Docker
1093
+ owner; it is never represented as a Pallet assignment. Downstream service holds and storage fences
1094
+ therefore depend on a live relay without requiring assignment authority that cannot exist yet.
1095
+
1096
+ The storage bootstrap has two different authorities. `IFleetCutoverVolumeHandoffIntent` is
1097
+ Cloudly's accepted pre-switch statement of exact service, volume, source-lineage and storage-request
1098
+ identity. It also binds the exact persistent `mountIdentityDigest` and accepted source-node
1099
+ observation. It is not a ready `IRuntimeStorageClaim`. Pallet persists a root-local
1100
+ `TFleetCutoverVolumeFence` in `held` state while the cluster is draining. That state carries no
1101
+ claim, session, assignment, attachment, reservation, confirmation or execution authority, and the
1102
+ storage owner must block all those operations for the volume. After the cluster reaches `pallet`,
1103
+ Corestore performs its one-shot initial lineage/ReadWriteOnce CAS for the same mount identity under
1104
+ that held native fence and returns `IFleetCutoverCorestoreAdoptionReceipt`, which for the first time
1105
+ binds the real ready
1106
+ `IRuntimeStorageClaim` reference. Only that exact accepted receipt can consume the Pallet fence.
1107
+ This separation prevents a pre-switch fence from fabricating provider readiness merely to satisfy
1108
+ cutover ordering.
1109
+
1110
+ `IFleetCutoverCoreflowRetirementEvidence` binds the real pre-switch Docker Coreflow32 relay by exact
1111
+ service ID, container ID, spec version/spec digest and image digest to accepted manager and local
1112
+ node observations. It requires no Pallet assignment. Cloudly dereferences those observations to
1113
+ require a live exact container without Docker/cgroup mounts, then joins its generation-bearing
1114
+ relay credential and accepted live registration to the current Spark credential, bundle, unit and
1115
+ accepted observation. It separately binds invalidation of the
1116
+ legacy credential, refusal of the old callable mode, and Spark's configuration CAS. The legacy
1117
+ source is identified by SHA-256 and may be `retained-inert` or `removed`; deletion and secure
1118
+ erasure are not cutover requirements. Its exact owner generation is retained with that disposition.
1119
+ Retained recovery evidence is valid only while the released
1120
+ owner cannot consume it into live mode and the old credential remains revoked.
1121
+
1122
+ Before any post-pallet assignment exists, an administrator calls
1123
+ `requests.fleetcutover.prepareFleetCutoverIngress` with the exact server-created service ID,
1124
+ current `pallet` runtime, complete accepted scope and target set, held exact-cluster spec revision,
1125
+ and `expectedDesignation`. Null creates the first designation; an exact current designation
1126
+ reference permits only same-service credential rotation. Replacing the designated service is a
1127
+ different owner flow and is refused here. Cloudly's one owning transaction verifies the admin,
1128
+ same-organization live service, current references, held exact-cluster spec, zero configured and
1129
+ actual published/public ports, and absence of a conflicting designation. It generates the managed
1130
+ launcher-environment bearer privately, stores its active version and hash authority, advances the
1131
+ held spec if its secret input changed, and accepts `IFleetCutoverIngressDesignation`. The public
1132
+ designation exposes only credential ID/generation and the active `ISecretVersionReference`; neither
1133
+ it nor the response exposes the bearer, hash, private key, or any other secret value. Preparation
1134
+ requires no assignment, runtime session, ingress registration, legacy absence, publication,
1135
+ port-transfer, readback, or `IFleetCutoverIngressAuthority`.
1136
+
1137
+ The preparation request is a closed compare-and-swap body. A replay requires the same mutation ID
1138
+ and exactly the original normalized request payload and returns the recorded designation/spec
1139
+ result; it does not renew generation, acceptance time, freshness, or authority. Every downstream
1140
+ authorization must dereference the current designation, held spec, runtime, scope, and target set.
1141
+ A historical replay response never grants current authority. `snapshotFleetCutoverIngressPreparationRequest`
1142
+ and `snapshotFleetCutoverIngressDesignation` check exact structure, reference relationships and the
1143
+ designation's canonical digest. They cannot establish admin identity, currentness, organization,
1144
+ service liveness, held state, zero ports, or absence of a conflicting designation; Cloudly owns all
1145
+ of those acceptance checks.
1146
+
1147
+ The remaining post-pallet order is represented without a second route or publication model. First
1148
+ Cloudly releases only the designated new ingress spec under an accepted empty published-port
1149
+ policy. It then accepts
1150
+ the existing cluster-ingress registration and route-table revision, exact Spark evidence that the
1151
+ old ingress is absent, the current source and target publication records and owning port-transfer
1152
+ receipt, and a readback of the current route revision as `IFleetCutoverIngressAuthority`. Only an
1153
+ application release may cite that authority. The legacy Docker Coretraffic instance therefore
1154
+ remains through `switching`; the new ingress runs without public ports before exact port ownership
1155
+ moves, and applications remain held until the new authoritative route is read back.
1156
+
1157
+ The owner methods live under `requests.fleetcutover`: administrator scope classification, ingress
1158
+ preparation and forward phase CAS, root-local Pallet volume-fence hold/read/
1159
+ consume, one-shot Corestore adoption, ingress-authority read, and ingress/application spec release.
1160
+ Spark transports local and manager evidence through its existing authenticated Swarm-observation
1161
+ route, and Cloudly assembles census and Coreflow-retirement records from accepted owner state; there
1162
+ is no caller-supplied census or retirement proof endpoint.
1163
+ Accepted evidence references are opaque `{ id, generation, digest }` records. They contain no
1164
+ secret bytes and gain meaning only when the named server owner dereferences them under current
1165
+ authorization and policy.
1166
+
1038
1167
  ### Service Runtime Specs And Status
1039
1168
 
1040
1169
  `data.IServiceRuntimeSpec` is what Cloudly runs for one service on a Pallet cluster:
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '32.12.0',
6
+ version: '32.14.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
@@ -1,6 +1,12 @@
1
1
  import * as plugins from '../plugins.js';
2
2
  import type { TSha256Digest, TImmutableContainerPlatform } from './immutableimage.js';
3
3
  import type { ISparkNodeReportRecord } from './sparknodereport.js';
4
+ import {
5
+ validateFleetCutoverLocalNodeSnapshot,
6
+ validateFleetCutoverManagerSnapshot,
7
+ type IFleetCutoverLocalNodeSnapshot,
8
+ type IFleetCutoverManagerSnapshot,
9
+ } from './fleetcutover.js';
4
10
  import { protocolRefusalHttpStatus, validateProtocolOfferOn, type IProtocolOffer } from '../protocol.js';
5
11
  import {
6
12
  canonicalizeStrictJson,
@@ -119,13 +125,13 @@ export const sparkSwarmNodeContracts = Object.freeze({
119
125
  maxResponseBytes: 2048,
120
126
  } as const),
121
127
  /**
122
- * By far the largest of the four: a manager snapshot carries up to the 1024 observed nodes
123
- * `validateSparkSwarmObservationRequest` admits, each with two identifiers of up to 200
124
- * characters, which is close to 600 KiB of body this route must still be able to read.
128
+ * The largest route: beside 1024 observed nodes, a cutover observation may carry independently
129
+ * bounded local-container and manager-service snapshots. Four MiB covers those validators while
130
+ * preserving one transport-level refusal before JSON is accepted.
125
131
  */
126
132
  swarmObservation: Object.freeze({
127
133
  endpoint: '/spark/swarm-nodes/swarm-observation',
128
- maxRequestBytes: 786_432,
134
+ maxRequestBytes: 4_194_304,
129
135
  maxResponseBytes: 2048,
130
136
  } as const),
131
137
  protocolRefusalStatus: protocolRefusalHttpStatus,
@@ -229,6 +235,8 @@ export type TSparkSwarmObservation =
229
235
  state: 'member';
230
236
  localSwarmNodeId: string;
231
237
  controlAvailable: false;
238
+ /** Local Docker-daemon evidence; it is accepted under this node's own credential. */
239
+ fleetCutoverLocalSnapshot?: IFleetCutoverLocalNodeSnapshot;
232
240
  })
233
241
  | (ISparkSwarmObservationBase & {
234
242
  state: 'member';
@@ -236,6 +244,10 @@ export type TSparkSwarmObservation =
236
244
  localSwarmNodeId: string;
237
245
  controlAvailable: true;
238
246
  managerSnapshot?: ISwarmManagerSnapshot;
247
+ /** A manager still reports physical containers only from its own local Docker daemon. */
248
+ fleetCutoverLocalSnapshot?: IFleetCutoverLocalNodeSnapshot;
249
+ /** Manager-visible services/tasks only; it never claims remote physical containers. */
250
+ fleetCutoverManagerSnapshot?: IFleetCutoverManagerSnapshot;
239
251
  });
240
252
 
241
253
  export type TSparkSwarmObservationRejectionCode =
@@ -573,7 +585,13 @@ export const validateSparkSwarmObservation = async (
573
585
  : observation.state === 'not-member'
574
586
  ? commonKeys
575
587
  : observation.state === 'member' && observation.controlAvailable === false
576
- ? [...commonKeys, 'localSwarmNodeId', 'controlAvailable']
588
+ ? [
589
+ ...commonKeys,
590
+ 'localSwarmNodeId',
591
+ 'controlAvailable',
592
+ ...(observation.fleetCutoverLocalSnapshot === undefined
593
+ ? [] : ['fleetCutoverLocalSnapshot']),
594
+ ]
577
595
  : observation.state === 'member' && observation.controlAvailable === true
578
596
  ? [
579
597
  ...commonKeys,
@@ -581,6 +599,10 @@ export const validateSparkSwarmObservation = async (
581
599
  'localSwarmNodeId',
582
600
  'controlAvailable',
583
601
  ...(observation.managerSnapshot === undefined ? [] : ['managerSnapshot']),
602
+ ...(observation.fleetCutoverLocalSnapshot === undefined
603
+ ? [] : ['fleetCutoverLocalSnapshot']),
604
+ ...(observation.fleetCutoverManagerSnapshot === undefined
605
+ ? [] : ['fleetCutoverManagerSnapshot']),
584
606
  ]
585
607
  : [];
586
608
  if (expectedKeys.length === 0 || !hasExactKeys(observation, expectedKeys)) {
@@ -602,6 +624,17 @@ export const validateSparkSwarmObservation = async (
602
624
  || typeof observation.controlAvailable !== 'boolean') {
603
625
  errors.push('Spark Swarm member observation must have canonical local authority');
604
626
  }
627
+ if (observation.fleetCutoverLocalSnapshot !== undefined) {
628
+ const localErrors = await validateFleetCutoverLocalNodeSnapshot(
629
+ observation.fleetCutoverLocalSnapshot,
630
+ );
631
+ errors.push(...localErrors.map(errorArg => `Spark Swarm observation ${errorArg}`));
632
+ if (isRuntimeRecord(observation.fleetCutoverLocalSnapshot)
633
+ && observation.fleetCutoverLocalSnapshot.swarmNodeId
634
+ !== observation.localSwarmNodeId) {
635
+ errors.push('Spark Swarm cutover local snapshot must name the local Swarm node');
636
+ }
637
+ }
605
638
  if (observation.controlAvailable === true) {
606
639
  if (!isRuntimeIdentifier(observation.swarmClusterId)) {
607
640
  errors.push('Spark Swarm manager observation must have canonical cluster authority');
@@ -613,6 +646,23 @@ export const validateSparkSwarmObservation = async (
613
646
  observation.managerSnapshot,
614
647
  ));
615
648
  }
649
+ if (observation.fleetCutoverManagerSnapshot !== undefined) {
650
+ if (observation.managerSnapshot === undefined) {
651
+ errors.push('Spark Swarm cutover manager snapshot requires the same manager observation');
652
+ }
653
+ const managerErrors = await validateFleetCutoverManagerSnapshot(
654
+ observation.fleetCutoverManagerSnapshot,
655
+ );
656
+ errors.push(...managerErrors.map(errorArg => `Spark Swarm observation ${errorArg}`));
657
+ if (isRuntimeRecord(observation.fleetCutoverManagerSnapshot)
658
+ && isRuntimeRecord(observation.fleetCutoverManagerSnapshot.inventory)) {
659
+ const cutoverInventory = observation.fleetCutoverManagerSnapshot.inventory;
660
+ if (cutoverInventory.swarmClusterId !== observation.swarmClusterId
661
+ || cutoverInventory.managerSwarmNodeId !== observation.localSwarmNodeId) {
662
+ errors.push('Spark Swarm cutover manager snapshot must name the observed authority');
663
+ }
664
+ }
665
+ }
616
666
  }
617
667
  }
618
668
  return errors;