@serve.zone/interfaces 32.67.0 → 32.69.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.
Files changed (38) hide show
  1. package/changelog.md +20 -0
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/data/clusternode.d.ts +15 -2
  4. package/dist_ts/data/clusternode.js +1 -1
  5. package/dist_ts/data/deploymentoperation.d.ts +17 -3
  6. package/dist_ts/data/deploymentoperation.js +4 -1
  7. package/dist_ts/data/deploymentreleaseredeploy.d.ts +88 -0
  8. package/dist_ts/data/deploymentreleaseredeploy.js +120 -0
  9. package/dist_ts/data/immutableimage.d.ts +17 -3
  10. package/dist_ts/data/immutableimage.js +18 -1
  11. package/dist_ts/data/index.d.ts +3 -0
  12. package/dist_ts/data/index.js +4 -1
  13. package/dist_ts/data/nodeaction.d.ts +439 -0
  14. package/dist_ts/data/nodeaction.js +434 -0
  15. package/dist_ts/data/sparkfleettarget.d.ts +80 -0
  16. package/dist_ts/data/sparkfleettarget.js +71 -0
  17. package/dist_ts/data/sparknodereport.d.ts +19 -0
  18. package/dist_ts/data/sparknodereport.js +21 -4
  19. package/dist_ts/data/user.d.ts +7 -1
  20. package/dist_ts/data/user.js +6 -1
  21. package/dist_ts/requests/deployment.d.ts +5 -0
  22. package/dist_ts/requests/node.d.ts +100 -0
  23. package/dist_ts/requests/service.d.ts +42 -0
  24. package/package.json +2 -2
  25. package/readme.md +56 -0
  26. package/ts/00_commitinfo_data.ts +1 -1
  27. package/ts/data/clusternode.ts +17 -2
  28. package/ts/data/deploymentoperation.ts +21 -2
  29. package/ts/data/deploymentreleaseredeploy.ts +182 -0
  30. package/ts/data/immutableimage.ts +36 -3
  31. package/ts/data/index.ts +3 -0
  32. package/ts/data/nodeaction.ts +755 -0
  33. package/ts/data/sparkfleettarget.ts +138 -0
  34. package/ts/data/sparknodereport.ts +42 -3
  35. package/ts/data/user.ts +12 -1
  36. package/ts/requests/deployment.ts +5 -0
  37. package/ts/requests/node.ts +118 -0
  38. package/ts/requests/service.ts +55 -0
@@ -1,4 +1,5 @@
1
1
  import { type IProtocolOffer } from '../protocol.js';
2
+ import type { TNodeActionName } from './clusternode.js';
2
3
  /** Host observations only. Container and workload readiness belong to Pallet. */
3
4
  export interface ISparkNodeReport {
4
5
  observedAt: number;
@@ -27,6 +28,24 @@ export interface ISparkNodeReport {
27
28
  * it made one since it started. Whether the node carries the hostname is `runtime.hostname`.
28
29
  */
29
30
  hostApply?: ISparkNodeHostApply;
31
+ /**
32
+ * The host's boot, stated by a Spark that executes node actions: how Cloudly verifies an action
33
+ * that reboots (`nodeActionVerification`) and whether the host waits for a reboot.
34
+ */
35
+ boot?: ISparkNodeBoot;
36
+ /**
37
+ * The node actions this Spark executes (`sparkNodeActionContracts`), in canonical order. Cloudly
38
+ * admits a node runtime action only for a node whose report states its executor, so an action
39
+ * Spark cannot execute is refused when it is requested rather than left to expire.
40
+ */
41
+ actionExecutors?: TNodeActionName[];
42
+ }
43
+ /** One boot of the host. */
44
+ export interface ISparkNodeBoot {
45
+ /** The kernel's `boot_id` (`/proc/sys/kernel/random/boot_id`), a lowercase UUID; it changes with every boot. */
46
+ id: string;
47
+ /** Whether the host states that a package it installed waits for a reboot (`/var/run/reboot-required`). */
48
+ rebootRequired: boolean;
30
49
  }
31
50
  /** Whether Spark applied a desired hostname: `applied` once the host carries it. */
32
51
  export type TSparkNodeHostApplyOutcome = 'applied' | 'failed';
@@ -3,6 +3,7 @@ import { readDataProperties, readExactDataRecord } from '../private/dataproperti
3
3
  import { isClusterNodeId } from '../private/nodeidentifier.js';
4
4
  import { protocolRefusalHttpStatus, readProtocolOffer } from '../protocol.js';
5
5
  import { isClusterNodeHostname } from './clusternodehostname.js';
6
+ import { isHostBootId, isNodeActionNameList } from './nodeaction.js';
6
7
  /** Bounds of `ISparkNodeHostApply.reason`. */
7
8
  export const sparkNodeHostApplyContract = Object.freeze({
8
9
  maximumReasonLength: 512,
@@ -72,8 +73,10 @@ export const snapshotSparkNodeReport = (valueArg) => {
72
73
  const reportKeys = ['observedAt', 'metrics', 'runtime'];
73
74
  const properties = readDataProperties(valueArg);
74
75
  requireValue(properties !== null);
75
- const hasHostApply = Object.hasOwn(properties, 'hostApply');
76
- const value = record(valueArg, hasHostApply ? [...reportKeys, 'hostApply'] : reportKeys);
76
+ // Each optional member is read exactly when the report states it, so a report without them is
77
+ // the report an earlier Spark sends and is read the way an earlier reader read it.
78
+ const optionalKeys = ['hostApply', 'boot', 'actionExecutors'].filter((keyArg) => Object.hasOwn(properties, keyArg));
79
+ const value = record(valueArg, [...reportKeys, ...optionalKeys]);
77
80
  const metrics = record(value.metrics, ['cpuUsagePercent', 'memoryUsedMB', 'memoryAvailableMB',
78
81
  'diskUsedGB', 'diskAvailableGB']);
79
82
  const runtime = record(value.runtime, ['hostname', 'platform', 'arch', 'osRelease', 'bundle',
@@ -100,9 +103,23 @@ export const snapshotSparkNodeReport = (valueArg) => {
100
103
  }),
101
104
  localRuntimeReady: true, workloadReadiness: 'unverified',
102
105
  }),
103
- ...(hasHostApply ? { hostApply: snapshotSparkNodeHostApply(value.hostApply) } : {}),
106
+ ...(optionalKeys.includes('hostApply') ? { hostApply: snapshotSparkNodeHostApply(value.hostApply) } : {}),
107
+ ...(optionalKeys.includes('boot') ? { boot: snapshotSparkNodeBoot(value.boot) } : {}),
108
+ ...(optionalKeys.includes('actionExecutors')
109
+ ? { actionExecutors: snapshotActionExecutors(value.actionExecutors) } : {}),
104
110
  });
105
111
  };
112
+ /** One `boot`: exactly its keys. */
113
+ const snapshotSparkNodeBoot = (valueArg) => {
114
+ const value = record(valueArg, ['id', 'rebootRequired']);
115
+ requireValue(isHostBootId(value.id) && typeof value.rebootRequired === 'boolean');
116
+ return Object.freeze({ id: value.id, rebootRequired: value.rebootRequired });
117
+ };
118
+ /** One `actionExecutors`: a canonical list of at least one action name, detached and frozen. */
119
+ const snapshotActionExecutors = (valueArg) => {
120
+ requireValue(isNodeActionNameList(valueArg));
121
+ return Object.freeze([...valueArg]);
122
+ };
106
123
  export const snapshotSparkNodeHeartbeatRequest = (valueArg) => {
107
124
  const value = record(valueArg, ['nodeId', 'nodeToken', 'protocol', 'report']);
108
125
  return Object.freeze({
@@ -163,4 +180,4 @@ export const snapshotSparkNodeDesiredHost = (valueArg) => {
163
180
  protocol: readProtocolOffer(value),
164
181
  });
165
182
  };
166
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Bhcmtub2RlcmVwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9zcGFya25vZGVyZXBvcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLG1CQUFtQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdkYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQy9ELE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxpQkFBaUIsRUFBdUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQTBDakUsOENBQThDO0FBQzlDLE1BQU0sQ0FBQyxNQUFNLDBCQUEwQixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDdEQsbUJBQW1CLEVBQUUsR0FBRztDQUNoQixDQUFDLENBQUM7QUE0Qlo7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ3RELFFBQVEsRUFBRSx3QkFBd0I7SUFDbEMsZUFBZSxFQUFFLElBQUk7SUFDckIsZ0JBQWdCLEVBQUUsSUFBSTtJQUN0QixxQkFBcUIsRUFBRSx5QkFBeUI7Q0FDeEMsQ0FBQyxDQUFDO0FBRVosTUFBTSxJQUFJLEdBQUcsR0FBVSxFQUFFLEdBQUcsTUFBTSxJQUFJLEtBQUssQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzFGLFNBQVMsWUFBWSxDQUFDLFFBQWlCO0lBQ3JDLElBQUksQ0FBQyxRQUFRO1FBQUUsSUFBSSxFQUFFLENBQUM7QUFDeEIsQ0FBQztBQUNELHNHQUFzRztBQUN0RyxNQUFNLE1BQU0sR0FBRyxDQUFDLFFBQWlCLEVBQUUsT0FBMEIsRUFBMkIsRUFBRTtJQUN4RixNQUFN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
183
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Bhcmtub2RlcmVwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9zcGFya25vZGVyZXBvcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLG1CQUFtQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdkYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQy9ELE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxpQkFBaUIsRUFBdUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUVqRSxPQUFPLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUE2RHJFLDhDQUE4QztBQUM5QyxNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ3RELG1CQUFtQixFQUFFLEdBQUc7Q0FDaEIsQ0FBQyxDQUFDO0FBNEJaOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUN0RCxRQUFRLEVBQUUsd0JBQXdCO0lBQ2xDLGVBQWUsRUFBRSxJQUFJO0lBQ3JCLGdCQUFnQixFQUFFLElBQUk7SUFDdEIscUJBQXFCLEVBQUUseUJBQXlCO0NBQ3hDLENBQUMsQ0FBQztBQUVaLE1BQU0sSUFBSSxHQUFHLEdBQVUsRUFBRSxHQUFHLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMxRixTQUFTLFlBQVksQ0FBQyxRQUFpQjtJQUNyQyxJQUFJLENBQUMsUUFBUTtRQUFFLElBQUksRUFBRSxDQUFDO0FBQ3hCLENBQUM7QUFDRCxzR0FBc0c7QUFDdEcsTUFBTSxNQUFNLEdBQUcsQ0FBQyxRQUFpQixFQUFFLE9BQTBCLEVBQTJCLEVBQUU7SUFDeEYsTUFBTSxNQUFNLEdBQUcsbUJBQW1CLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3RELFlBQVksQ0FBQyxNQUFNLEtBQUssSUFBSSxDQUFDLENBQUM7SUFDOUIsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQyxDQUFDO0FBQ0YsTUFBTSxJQUFJLEdBQUcsQ0FBQyxRQUFpQixFQUFFLFVBQWtCLEVBQUUsWUFBb0IsRUFBVSxFQUFFO0lBQ25GLFlBQVksQ0FBQyxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksUUFBUSxDQUFDLE1BQU0sSUFBSSxZQUFZO1dBQ3ZFLFFBQVEsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLENBQUMsQ0FBQztJQUNuRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFDRixrR0FBa0c7QUFDbEcsTUFBTSxNQUFNLEdBQUcsQ0FBQyxRQUFpQixFQUFVLEVBQUUsQ0FBQyxDQUM1QyxlQUFlLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQzlDLENBQUM7QUFDRiwwRkFBMEY7QUFDMUYsMEZBQTBGO0FBQzFGLE1BQU0sY0FBYyxHQUFHLENBQUMsUUFBaUIsRUFBVSxFQUFFLENBQUMsQ0FDcEQsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQy9DLENBQUM7QUFDRixNQUFNLE1BQU0sR0FBRyxDQUFDLFFBQWlCLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBVSxFQUFFO0lBQzdFLFlBQVksQ0FBQyxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7V0FDakUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLFFBQVEsSUFBSSxDQUFDLElBQUksUUFBUSxJQUFJLE1BQU0sQ0FBQyxDQUFDO0lBQ3RFLE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMsQ0FBQztBQUNGLE1BQU0sT0FBTyxHQUFHLENBQUMsUUFBaUIsRUFBRSxVQUFrQixFQUFVLEVBQUU7SUFDaEUsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQy9CLFlBQVksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSSxVQUFVLENBQUMsQ0FBQztJQUNqRSxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMsQ0FBQztBQUVGLDBFQUEwRTtBQUMxRSxNQUFNLDBCQUEwQixHQUFHLENBQUMsUUFBaUIsRUFBdUIsRUFBRTtJQUM1RSxNQUFNLElBQUksR0FBRyxDQUFDLFlBQVksRUFBRSxVQUFVLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDbkQsTUFBTSxLQUFLLEdBQUcsbUJBQW1CLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxHQUFHLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQzNGLFlBQVksQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUNwRCxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRCxJQUFJLEtBQUssQ0FBQyxPQUFPLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDaEMsWUFBWSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDLENBQUM7UUFDekMsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7SUFDRCxZQUFZLENBQUMsS0FBSyxDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsQ0FBQztJQUN6QyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVE7UUFDNUUsTUFBTSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLGdCQUFnQixFQUFFLDBCQUEwQixDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3BHLENBQUMsQ0FBQztBQUVGLGlGQUFpRjtBQUNqRixNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxDQUFDLFFBQWlCLEVBQW9CLEVBQUU7SUFDN0UsTUFBTSxVQUFVLEdBQUcsQ0FBQyxZQUFZLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sVUFBVSxHQUFHLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2hELFlBQVksQ0FBQyxVQUFVLEtBQUssSUFBSSxDQUFDLENBQUM7SUFDbEMsOEZBQThGO0lBQzlGLG1GQUFtRjtJQUNuRixNQUFNLFlBQVksR0FBRyxDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEgsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsVUFBVSxFQUFFLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUNqRSxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxtQkFBbUI7UUFDM0YsWUFBWSxFQUFFLGlCQUFpQixDQUFDLENBQUMsQ0FBQztJQUNwQyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxRQUFRO1FBQzFGLG1CQUFtQixFQUFFLG1CQUFtQixDQUFDLENBQUMsQ0FBQztJQUM3QyxZQUFZLENBQUMsT0FBTyxDQUFDLFFBQVEsS0FBSyxPQUFPLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFjLENBQUM7V0FDOUYsT0FBTyxDQUFDLGlCQUFpQixLQUFLLElBQUksSUFBSSxPQUFPLENBQUMsaUJBQWlCLEtBQUssWUFBWSxDQUFDLENBQUM7SUFDdkYsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsZUFBZSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzlELFlBQVksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsd0NBQXdDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6RyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO0lBQ3JGLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUNuQixVQUFVLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQ3hDLE9BQU8sRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQ3JCLGVBQWUsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxHQUFHLENBQUM7WUFDckQsWUFBWSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQztZQUNoRyxVQUFVLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUM7U0FDekYsQ0FBQztRQUNGLE9BQU8sRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQ3JCLFFBQVEsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsSUFBNEI7WUFDdkUsU0FBUyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLGdCQUFnQixFQUFFLEdBQUcsQ0FBQztZQUN6RCxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQztnQkFDcEIsT0FBTyxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO2dCQUN2QyxZQUFZLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDO2dCQUM3RCxjQUFjLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDO2FBQ2xFLENBQUM7WUFDRixpQkFBaUIsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsWUFBWTtTQUN6RCxDQUFDO1FBQ0YsR0FBRyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxFQUFFLDBCQUEwQixDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDekcsR0FBRyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDckYsR0FBRyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUM7WUFDMUMsQ0FBQyxDQUFDLEVBQUUsZUFBZSxFQUFFLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7S0FDOUUsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDO0FBRUYsb0NBQW9DO0FBQ3BDLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxRQUFpQixFQUFrQixFQUFFO0lBQ2xFLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO0lBQ3pELFlBQVksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLE9BQU8sS0FBSyxDQUFDLGNBQWMsS0FBSyxTQUFTLENBQUMsQ0FBQztJQUNsRixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxjQUFjLEVBQUUsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7QUFDL0UsQ0FBQyxDQUFDO0FBRUYsZ0dBQWdHO0FBQ2hHLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxRQUFpQixFQUFxQixFQUFFO0lBQ3ZFLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQzdDLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQXNCLENBQUM7QUFDM0QsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0saUNBQWlDLEdBQUcsQ0FBQyxRQUFpQixFQUE4QixFQUFFO0lBQ2pHLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQzlFLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUNuQixNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDNUIsbUZBQW1GO1FBQ25GLFNBQVMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSwyQkFBMkIsRUFBRSxFQUFFLENBQUM7UUFDakUsUUFBUSxFQUFFLGlCQUFpQixDQUFDLEtBQUssQ0FBQztRQUNsQyxNQUFNLEVBQUUsdUJBQXVCLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztLQUM5QyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxpQ0FBaUMsR0FBRyxDQUFDLFFBQWlCLEVBQThCLEVBQUU7SUFDakcsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsc0JBQXNCO1FBQzFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUM3QyxZQUFZLENBQUMsS0FBSyxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsQ0FBQztJQUN0QyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUM7UUFDbkIsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDNUMsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLENBQUM7UUFDNUQsWUFBWSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDdEYsUUFBUSxFQUFFLGlCQUFpQixDQUFDLEtBQUssQ0FBQztLQUNuQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUM7QUEwQkY7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ2pELFFBQVEsRUFBRSxtQkFBbUI7SUFDN0IsZUFBZSxFQUFFLElBQUk7SUFDckIsZ0JBQWdCLEVBQUUsSUFBSTtJQUN0QixxQkFBcUIsRUFBRSx5QkFBeUI7Q0FDeEMsQ0FBQyxDQUFDO0FBRVosTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQUcsQ0FBQyxRQUFpQixFQUF5QixFQUFFO0lBQ3ZGLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLEVBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDcEUsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQ25CLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUM1QixTQUFTLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsMkJBQTJCLEVBQUUsRUFBRSxDQUFDO1FBQ2pFLFFBQVEsRUFBRSxpQkFBaUIsQ0FBQyxLQUFLLENBQUM7S0FDbkMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQUcsQ0FBQyxRQUFpQixFQUF5QixFQUFFO0lBQ3ZGLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ2pGLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUM7SUFDaEMsSUFBSSxRQUFRLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDdEIsWUFBWSxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDdkMsQ0FBQztTQUFNLENBQUM7UUFDTixZQUFZLENBQUMscUJBQXFCLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQ25CLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUM1QixRQUFRO1FBQ1IsVUFBVSxFQUFFLFFBQVEsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLFFBQVEsRUFBRSxpQkFBaUIsQ0FBQyxLQUFLLENBQUM7S0FDbkMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDIn0=
@@ -8,7 +8,13 @@ export type TServiceDeploymentCapability = 'deployment:preflight' | 'deployment:
8
8
  * Reserve a greenfield successor whose image Cloudly imports from an attested legacy service,
9
9
  * and have Cloudly import it. Granted on an organization-service-slot grant only.
10
10
  */
11
- | 'deployment:import-legacy' | 'deployment:promote-route' | 'deployment:rollback-image' | 'deployment:rollback-route' | 'deployment:retry' | 'deployment:cleanup';
11
+ | 'deployment:import-legacy' | 'deployment:promote-route' | 'deployment:rollback-image' | 'deployment:rollback-route' | 'deployment:retry' | 'deployment:cleanup'
12
+ /**
13
+ * Start a release redeploy of the service (`startServiceReleaseDeployment`): Cloudly deploys one
14
+ * of the service's own accepted, retained releases again and runs the operation itself. Granted
15
+ * on an existing-service grant only; administrators hold it implicitly.
16
+ */
17
+ | 'deployment:redeploy-release';
12
18
  /**
13
19
  * Server-persisted authority for one logical service. These grants are never
14
20
  * accepted from the identity payload supplied by a caller; Cloudly reloads
@@ -13,6 +13,7 @@ const serviceDeploymentCapabilities = new Set([
13
13
  'deployment:rollback-route',
14
14
  'deployment:retry',
15
15
  'deployment:cleanup',
16
+ 'deployment:redeploy-release',
16
17
  ]);
17
18
  const deploymentBoundaryIdentifierRegex = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,199}$/;
18
19
  export const validateServiceDeploymentGrant = (grantArg) => {
@@ -55,10 +56,14 @@ export const validateServiceDeploymentGrant = (grantArg) => {
55
56
  && capabilities.includes('deployment:adopt-existing')) {
56
57
  errors.push('deployment:adopt-existing requires an existing-service grant');
57
58
  }
59
+ if (capabilities && grant.scope !== 'service'
60
+ && capabilities.includes('deployment:redeploy-release')) {
61
+ errors.push('deployment:redeploy-release requires an existing-service grant');
62
+ }
58
63
  if (capabilities && grant.scope !== 'organization-service-slot'
59
64
  && capabilities.includes('deployment:import-legacy')) {
60
65
  errors.push('deployment:import-legacy requires an organization-service-slot grant');
61
66
  }
62
67
  return errors;
63
68
  };
64
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2RhdGEvdXNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFtREEsTUFBTSw2QkFBNkIsR0FBRyxJQUFJLEdBQUcsQ0FBK0I7SUFDMUUsc0JBQXNCO0lBQ3RCLG9CQUFvQjtJQUNwQiwwQkFBMEI7SUFDMUIseUJBQXlCO0lBQ3pCLDBCQUEwQjtJQUMxQiwyQkFBMkI7SUFDM0IsbUJBQW1CO0lBQ25CLDhCQUE4QjtJQUM5QiwwQkFBMEI7SUFDMUIsMEJBQTBCO0lBQzFCLDJCQUEyQjtJQUMzQiwyQkFBMkI7SUFDM0Isa0JBQWtCO0lBQ2xCLG9CQUFvQjtDQUNyQixDQUFDLENBQUM7QUFFSCxNQUFNLGlDQUFpQyxHQUFHLHFDQUFxQyxDQUFDO0FBRWhGLE1BQU0sQ0FBQyxNQUFNLDhCQUE4QixHQUFHLENBQzVDLFFBQWlCLEVBQ1AsRUFBRTtJQUNaLE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUM1QixJQUFJLENBQUMsUUFBUSxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDekUsT0FBTyxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDckMsQ0FBQztJQUNELE1BQU0sS0FBSyxHQUFHLFFBQW1DLENBQUM7SUFDbEQsSUFBSSxLQUFLLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsS0FBSyxLQUFLLDJCQUEyQixFQUFFLENBQUM7UUFDN0UsTUFBTSxDQUFDLElBQUksQ0FBQyx5RUFBeUUsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFDRCxJQUFJLE9BQU8sS0FBSyxDQUFDLGNBQWMsS0FBSyxRQUFRO1dBQ3ZDLENBQUMsaUNBQWlDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO1FBQ25FLE1BQU0sQ0FBQyxJQUFJLENBQUMsdURBQXVELENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQUssQ0FBQyxTQUFTLEtBQUssUUFBUTtXQUNsQyxDQUFDLGlDQUFpQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUM5RCxNQUFNLENBQUMsSUFBSSxDQUFDLGtEQUFrRCxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUNELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQztRQUNwRCxDQUFDLENBQUMsS0FBSyxDQUFDLFlBQVk7UUFDcEIsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUNkLElBQUksQ0FBQyxZQUFZO1dBQ1osWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDO1dBQ3ZCLFlBQVksQ0FBQyxNQUFNLEdBQUcsNkJBQTZCLENBQUMsSUFBSTtXQUN4RCxJQUFJLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLEtBQUssWUFBWSxDQUFDLE1BQU07V0FDbEQsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FDdEMsT0FBTyxhQUFhLEtBQUssUUFBUTtlQUM5QixDQUFDLDZCQUE2QixDQUFDLEdBQUcsQ0FBQyxhQUE2QyxDQUFDLENBQ3JGLENBQUMsRUFBRSxDQUFDO1FBQ0wsTUFBTSxDQUFDLElBQUksQ0FBQyxrRkFBa0YsQ0FBQyxDQUFDO0lBQ2xHLENBQUM7SUFDRCxJQUFJLFlBQVksSUFBSSxLQUFLLENBQUMsS0FBSyxLQUFLLFNBQVM7V0FDeEMsWUFBWSxDQUFDLFFBQVEsQ0FBQyw4QkFBOEIsQ0FBQyxFQUFFLENBQUM7UUFDM0QsTUFBTSxDQUFDLElBQUksQ0FBQyxnRUFBZ0UsQ0FBQyxDQUFDO0lBQ2hGLENBQUM7SUFDRCxJQUFJLFlBQVksSUFBSSxLQUFLLENBQUMsS0FBSyxLQUFLLDJCQUEyQjtXQUMxRCxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsOEJBQThCLENBQUMsRUFBRSxDQUFDO1FBQzVELE1BQU0sQ0FBQyxJQUFJLENBQUMsdUVBQXVFLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBQ0QsSUFBSSxZQUFZLElBQUksS0FBSyxDQUFDLEtBQUssS0FBSyxTQUFTO1dBQ3hDLFlBQVksQ0FBQyxRQUFRLENBQUMsMkJBQTJCLENBQUMsRUFBRSxDQUFDO1FBQ3hELE1BQU0sQ0FBQyxJQUFJLENBQUMsOERBQThELENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBQ0QsSUFBSSxZQUFZLElBQUksS0FBSyxDQUFDLEtBQUssS0FBSywyQkFBMkI7V0FDMUQsWUFBWSxDQUFDLFFBQVEsQ0FBQywwQkFBMEIsQ0FBQyxFQUFFLENBQUM7UUFDdkQsTUFBTSxDQUFDLElBQUksQ0FBQyxzRUFBc0UsQ0FBQyxDQUFDO0lBQ3RGLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDLENBQUMifQ==
69
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2RhdGEvdXNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUF5REEsTUFBTSw2QkFBNkIsR0FBRyxJQUFJLEdBQUcsQ0FBK0I7SUFDMUUsc0JBQXNCO0lBQ3RCLG9CQUFvQjtJQUNwQiwwQkFBMEI7SUFDMUIseUJBQXlCO0lBQ3pCLDBCQUEwQjtJQUMxQiwyQkFBMkI7SUFDM0IsbUJBQW1CO0lBQ25CLDhCQUE4QjtJQUM5QiwwQkFBMEI7SUFDMUIsMEJBQTBCO0lBQzFCLDJCQUEyQjtJQUMzQiwyQkFBMkI7SUFDM0Isa0JBQWtCO0lBQ2xCLG9CQUFvQjtJQUNwQiw2QkFBNkI7Q0FDOUIsQ0FBQyxDQUFDO0FBRUgsTUFBTSxpQ0FBaUMsR0FBRyxxQ0FBcUMsQ0FBQztBQUVoRixNQUFNLENBQUMsTUFBTSw4QkFBOEIsR0FBRyxDQUM1QyxRQUFpQixFQUNQLEVBQUU7SUFDWixNQUFNLE1BQU0sR0FBYSxFQUFFLENBQUM7SUFDNUIsSUFBSSxDQUFDLFFBQVEsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQ3pFLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFDRCxNQUFNLEtBQUssR0FBRyxRQUFtQyxDQUFDO0lBQ2xELElBQUksS0FBSyxDQUFDLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxDQUFDLEtBQUssS0FBSywyQkFBMkIsRUFBRSxDQUFDO1FBQzdFLE1BQU0sQ0FBQyxJQUFJLENBQUMseUVBQXlFLENBQUMsQ0FBQztJQUN6RixDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQUssQ0FBQyxjQUFjLEtBQUssUUFBUTtXQUN2QyxDQUFDLGlDQUFpQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztRQUNuRSxNQUFNLENBQUMsSUFBSSxDQUFDLHVEQUF1RCxDQUFDLENBQUM7SUFDdkUsQ0FBQztJQUNELElBQUksT0FBTyxLQUFLLENBQUMsU0FBUyxLQUFLLFFBQVE7V0FDbEMsQ0FBQyxpQ0FBaUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDOUQsTUFBTSxDQUFDLElBQUksQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFDRCxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUM7UUFDcEQsQ0FBQyxDQUFDLEtBQUssQ0FBQyxZQUFZO1FBQ3BCLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDZCxJQUFJLENBQUMsWUFBWTtXQUNaLFlBQVksQ0FBQyxNQUFNLEdBQUcsQ0FBQztXQUN2QixZQUFZLENBQUMsTUFBTSxHQUFHLDZCQUE2QixDQUFDLElBQUk7V0FDeEQsSUFBSSxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUMsSUFBSSxLQUFLLFlBQVksQ0FBQyxNQUFNO1dBQ2xELFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQ3RDLE9BQU8sYUFBYSxLQUFLLFFBQVE7ZUFDOUIsQ0FBQyw2QkFBNkIsQ0FBQyxHQUFHLENBQUMsYUFBNkMsQ0FBQyxDQUNyRixDQUFDLEVBQUUsQ0FBQztRQUNMLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0ZBQWtGLENBQUMsQ0FBQztJQUNsRyxDQUFDO0lBQ0QsSUFBSSxZQUFZLElBQUksS0FBSyxDQUFDLEtBQUssS0FBSyxTQUFTO1dBQ3hDLFlBQVksQ0FBQyxRQUFRLENBQUMsOEJBQThCLENBQUMsRUFBRSxDQUFDO1FBQzNELE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0VBQWdFLENBQUMsQ0FBQztJQUNoRixDQUFDO0lBQ0QsSUFBSSxZQUFZLElBQUksS0FBSyxDQUFDLEtBQUssS0FBSywyQkFBMkI7V0FDMUQsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLDhCQUE4QixDQUFDLEVBQUUsQ0FBQztRQUM1RCxNQUFNLENBQUMsSUFBSSxDQUFDLHVFQUF1RSxDQUFDLENBQUM7SUFDdkYsQ0FBQztJQUNELElBQUksWUFBWSxJQUFJLEtBQUssQ0FBQyxLQUFLLEtBQUssU0FBUztXQUN4QyxZQUFZLENBQUMsUUFBUSxDQUFDLDJCQUEyQixDQUFDLEVBQUUsQ0FBQztRQUN4RCxNQUFNLENBQUMsSUFBSSxDQUFDLDhEQUE4RCxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUNELElBQUksWUFBWSxJQUFJLEtBQUssQ0FBQyxLQUFLLEtBQUssU0FBUztXQUN4QyxZQUFZLENBQUMsUUFBUSxDQUFDLDZCQUE2QixDQUFDLEVBQUUsQ0FBQztRQUMxRCxNQUFNLENBQUMsSUFBSSxDQUFDLGdFQUFnRSxDQUFDLENBQUM7SUFDaEYsQ0FBQztJQUNELElBQUksWUFBWSxJQUFJLEtBQUssQ0FBQyxLQUFLLEtBQUssMkJBQTJCO1dBQzFELFlBQVksQ0FBQyxRQUFRLENBQUMsMEJBQTBCLENBQUMsRUFBRSxDQUFDO1FBQ3ZELE1BQU0sQ0FBQyxJQUFJLENBQUMsc0VBQXNFLENBQUMsQ0FBQztJQUN0RixDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQyxDQUFDIn0=
@@ -50,6 +50,11 @@ export interface IReq_Any_Cloudly_GetDeploymentsByNode extends plugins.typedrequ
50
50
  deployments: IDeployment[];
51
51
  };
52
52
  }
53
+ /**
54
+ * @deprecated Stores a deployment record and deploys nothing; no runtime writes these records.
55
+ * A deployment is a release redeploy (`startServiceReleaseDeployment`) or a tsdeploy deployment.
56
+ * It is removed in the next Cloudly major.
57
+ */
53
58
  export interface IReq_Any_Cloudly_CreateDeployment extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_CreateDeployment> {
54
59
  method: 'createDeployment';
55
60
  request: {
@@ -3,6 +3,8 @@ import type { IBareMetal } from '../data/baremetal.js';
3
3
  import type { ICluster } from '../data/cluster.js';
4
4
  import type { IClusterNode, INodeAction, INodeMetricsSample, TNodeActionName } from '../data/clusternode.js';
5
5
  import type { IDeployment } from '../data/deployment.js';
6
+ import type { INodeActionConfirmation, INodeActionPreview } from '../data/nodeaction.js';
7
+ import type { ISparkFleetTarget, ISparkFleetTargetChange, ISparkNodeTargetHold } from '../data/sparkfleettarget.js';
6
8
  import type { IIdentity } from '../data/user.js';
7
9
  import type { IPlatformObjectStorageEndpoint } from '../platform/objectstorage.js';
8
10
  import type { IPlatformDatabaseEndpoint } from '../platform/database.js';
@@ -342,6 +344,18 @@ export interface IReq_Any_Cloudly_ResetClusterNodeHostname extends plugins.typed
342
344
  node: IClusterNode;
343
345
  };
344
346
  }
347
+ /**
348
+ * An administrator requests one action on one node.
349
+ *
350
+ * A node whose Swarm-era daemon reports last receives it as before, in the metrics-sample answer;
351
+ * `confirmation` is not read for it. A node that reports through the node runtime is sent the
352
+ * action only with a `confirmation` (`data.validateNodeActionConfirmation`) of the preview the
353
+ * administrator read (`getNodeActionPreview`): the typed hostname, the impact digest, when the
354
+ * impact names a Corestore on the node the consent to restart it, and for an update the fleet Spark
355
+ * target revision the preview showed. The action then carries
356
+ * `lifecycle`, with the confirmation, the impact and, for an update, the fleet target frozen in it.
357
+ * Every refusal is one of `data.nodeActionRefusals` and changes nothing.
358
+ */
345
359
  export interface IReq_Any_Cloudly_CreateNodeAction extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_CreateNodeAction> {
346
360
  method: 'createNodeAction';
347
361
  request: {
@@ -349,11 +363,97 @@ export interface IReq_Any_Cloudly_CreateNodeAction extends plugins.typedrequestI
349
363
  nodeId: string;
350
364
  actionName: TNodeActionName;
351
365
  payload?: INodeAction['payload'];
366
+ confirmation?: INodeActionConfirmation;
367
+ };
368
+ response: {
369
+ action: INodeAction;
370
+ };
371
+ }
372
+ /**
373
+ * An administrator previews one action on one node that reports through the node runtime: what it
374
+ * interrupts, read from Cloudly's database, the digest a confirmation names, and every reason a
375
+ * request would be refused now. A preview changes nothing.
376
+ */
377
+ export interface IReq_Any_Cloudly_GetNodeActionPreview extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetNodeActionPreview> {
378
+ method: 'getNodeActionPreview';
379
+ request: {
380
+ identity: IIdentity;
381
+ nodeId: string;
382
+ actionName: TNodeActionName;
383
+ };
384
+ response: {
385
+ preview: INodeActionPreview;
386
+ };
387
+ }
388
+ /**
389
+ * An administrator withdraws one node runtime action while it is still `pending`, at the revision
390
+ * they read. A claimed action is never withdrawn: Spark may already have stopped the node.
391
+ */
392
+ export interface IReq_Any_Cloudly_CancelNodeAction extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_CancelNodeAction> {
393
+ method: 'cancelNodeAction';
394
+ request: {
395
+ identity: IIdentity;
396
+ nodeId: string;
397
+ actionId: string;
398
+ expectedRevision: number;
352
399
  };
353
400
  response: {
354
401
  action: INodeAction;
355
402
  };
356
403
  }
404
+ /**
405
+ * An administrator reads the fleet Spark target (`data.ISparkFleetTarget`, `null` while there is
406
+ * none), its newest changes and every node hold.
407
+ */
408
+ export interface IReq_Any_Cloudly_GetSparkFleetTarget extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetSparkFleetTarget> {
409
+ method: 'getSparkFleetTarget';
410
+ request: {
411
+ identity: IIdentity;
412
+ };
413
+ response: {
414
+ target: ISparkFleetTarget | null;
415
+ /** Newest first, at most `data.sparkFleetTargetContract.historyLimit`. */
416
+ history: ISparkFleetTargetChange[];
417
+ /** Sorted by node id. */
418
+ holds: ISparkNodeTargetHold[];
419
+ };
420
+ }
421
+ /**
422
+ * An administrator sets the fleet Spark target to one release version, at the revision they read
423
+ * (`0` while there is none). Cloudly reads the release's `SHA256SUMS.txt` and `install.sh`, refuses
424
+ * any mismatch between them, and stores the version with the SHA-256 it checked. Every refusal is
425
+ * one of `data.sparkFleetTargetRefusals`.
426
+ */
427
+ export interface IReq_Any_Cloudly_SetSparkFleetTarget extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_SetSparkFleetTarget> {
428
+ method: 'setSparkFleetTarget';
429
+ request: {
430
+ identity: IIdentity;
431
+ /** `data.validateSetSparkFleetTargetInput` judges these two. */
432
+ version: string;
433
+ expectedRevision: number;
434
+ };
435
+ response: {
436
+ target: ISparkFleetTarget;
437
+ };
438
+ }
439
+ /**
440
+ * An administrator holds one node at the release it runs (`hold: { reason }`) or releases it
441
+ * (`hold: null`). Answers the hold as it now stands.
442
+ */
443
+ export interface IReq_Any_Cloudly_SetSparkNodeTargetHold extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_SetSparkNodeTargetHold> {
444
+ method: 'setSparkNodeTargetHold';
445
+ request: {
446
+ identity: IIdentity;
447
+ nodeId: string;
448
+ /** `data.validateSparkNodeTargetHoldInput` judges it. */
449
+ hold: {
450
+ reason: string;
451
+ } | null;
452
+ };
453
+ response: {
454
+ hold: ISparkNodeTargetHold | null;
455
+ };
456
+ }
357
457
  export interface IReq_Any_Cloudly_GetNodeActions extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetNodeActions> {
358
458
  method: 'getNodeActions';
359
459
  request: {
@@ -9,6 +9,7 @@ import type { IImageRelease } from '../data/immutableimage.js';
9
9
  import type { IDeploymentPreflightReport, IDeploymentPreflightRequestData } from '../data/deploymentpreflight.js';
10
10
  import type { IDeploymentReservationInput, IServiceDeploymentOperation, IServiceDeploymentStatus } from '../data/deploymentoperation.js';
11
11
  import type { TSha256Digest } from '../data/immutableimage.js';
12
+ import type { IServiceDeploymentOperationHistoryQuery, IServiceReleaseDeploymentStartInput } from '../data/deploymentreleaseredeploy.js';
12
13
  import type { ILegacyServiceHostObservation, ILegacyServiceRuntimeAttestation } from '../data/deploymentlegacyimport.js';
13
14
  import type { IProtocolOffer } from '../protocol.js';
14
15
  import type { IRuntimeAssignmentLogAttemptPage, IRuntimeAssignmentLogPage } from '../data/runtimeassignmentlogs.js';
@@ -135,6 +136,11 @@ export interface IRequest_Any_Cloudly_PromoteServiceImageRelease extends plugins
135
136
  operation: IServiceDeploymentOperation;
136
137
  };
137
138
  }
139
+ /**
140
+ * @deprecated Rolls back by re-opening an earlier operation; nothing calls it and it is not
141
+ * maintained. A rollback is a release redeploy (`startServiceReleaseDeployment`) of the earlier
142
+ * release. It is removed in the next Cloudly major.
143
+ */
138
144
  export interface IRequest_Any_Cloudly_RollbackServiceImageRelease extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IRequest_Any_Cloudly_RollbackServiceImageRelease> {
139
145
  method: 'rollbackServiceImageRelease';
140
146
  request: {
@@ -173,6 +179,42 @@ export interface IRequest_Any_Cloudly_ReserveServiceDeployment extends plugins.t
173
179
  registryTarget: IRegistryTarget;
174
180
  };
175
181
  }
182
+ /**
183
+ * Starts a release redeploy: Cloudly deploys one of the service's own accepted, retained and whole
184
+ * releases again (`data.deploymentreleaseredeploy`) and runs the operation itself to `succeeded` or
185
+ * `failed`. The answer is the operation as it stands once it was started; its state, failure and
186
+ * evidence are read with `readServiceDeploymentStatus`, never assumed from the answer.
187
+ *
188
+ * An administrator or a deployment machine user holding `deployment:redeploy-release` on the
189
+ * service may start one; the operation's actor is the caller. A refusal carries one of
190
+ * `data.serviceReleaseDeploymentRefusalCodes` or a shared deployment code in its `code`. The same
191
+ * `idempotencyKey` with the same request answers the operation it started.
192
+ */
193
+ export interface IRequest_Any_Cloudly_StartServiceReleaseDeployment extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IRequest_Any_Cloudly_StartServiceReleaseDeployment> {
194
+ method: 'startServiceReleaseDeployment';
195
+ request: {
196
+ identity: IIdentityCredential;
197
+ } & IServiceReleaseDeploymentStartInput;
198
+ response: {
199
+ operation: IServiceDeploymentOperation;
200
+ };
201
+ }
202
+ /**
203
+ * One page of a service's deployment operations, newest first: every operation of every origin
204
+ * (tsdeploy's and Cloudly's own). `nextBefore` names the operation the next page starts after and
205
+ * is absent on the last page. Administrators, or a deployment machine user holding
206
+ * `deployment:status` on the service.
207
+ */
208
+ export interface IRequest_Any_Cloudly_GetServiceDeploymentOperations extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IRequest_Any_Cloudly_GetServiceDeploymentOperations> {
209
+ method: 'getServiceDeploymentOperations';
210
+ request: {
211
+ identity: IIdentityCredential;
212
+ } & IServiceDeploymentOperationHistoryQuery;
213
+ response: {
214
+ operations: IServiceDeploymentOperation[];
215
+ nextBefore?: string;
216
+ };
217
+ }
176
218
  /**
177
219
  * Answers one deployment operation's status and advances it: a rolling-out operation whose runtime
178
220
  * evidence proves success or failure is transitioned before the answer. A deployment that polls
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "32.67.0",
3
+ "version": "32.69.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.",
6
6
  "exports": {
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "devDependencies": {
30
30
  "@git.zone/tsrepo": "^1.1.1",
31
- "@types/node": "26.6.5",
31
+ "@types/node": "26.6.6",
32
32
  "typescript": "^6.0.3"
33
33
  },
34
34
  "files": [
package/readme.md CHANGED
@@ -216,6 +216,53 @@ next heartbeat; the node has converged when `runtime.hostname` states the intent
216
216
  hostname. A Spark that sends `hostApply` raises its `minimumPeerVersion` so it
217
217
  reaches only a Cloudly that reads it.
218
218
 
219
+ ### Node Actions
220
+
221
+ A node action (`INodeAction`: reboot, serve.zone service update, system upgrade)
222
+ that a node runtime executes carries `lifecycle` (`INodeActionLifecycle`): the
223
+ administrator's confirmation (`INodeActionConfirmation`: the typed hostname, the
224
+ digest of the impact preview they read, when the impact names a Corestore on the
225
+ node the consent to restart it, and for an update the fleet Spark target revision
226
+ the preview showed, refused `target-changed` once the target moved), the impact (`INodeActionImpact`), the fleet
227
+ Spark target an update moves the node to, a revision, the current deadline, the
228
+ claim, a failure with its remedy and a timeline. A Swarm-era record carries none of
229
+ it and travels only in the Swarm-era metrics-sample answer. `TNodeActionStatus`
230
+ keeps the four shipped values (`pending` is the requested state) and adds
231
+ `claimed`, `executing`, `draining`, `rebooting`, `verifying`, `expired`,
232
+ `cancelled` and `unverified`; `data.nodeActionStatusKinds` states which are open.
233
+
234
+ `data.sparkNodeActionContracts` defines the node runtime's two action routes,
235
+ authenticated and judged in the heartbeat's order: `offer` (`/spark/nodes/action`)
236
+ answers the node's one open action (`ISparkNodeActionAssignment`) or `null`, and
237
+ `transition` (`/spark/nodes/action/transition`) takes one step at the revision the
238
+ assignment states — `claim` with the host's boot id, a forward `phase`
239
+ (`sparkNodeActionPhaseOrder`), `complete` (a host upgrade without a reboot) or
240
+ `fail` with one of `sparkNodeActionFailureCodes` — and answers `applied`,
241
+ `replayed` (the same step again at the same revision) or a named refusal.
242
+ `data.admitsSparkNodeActionTransition` states which step an action admits.
243
+ Cloudly verifies every action from what the node reports
244
+ (`data.nodeActionVerification`): a new `boot.id`, the target bundle version, or a
245
+ completed host upgrade; a heartbeat stating `boot.rebootRequired` after a host
246
+ upgrade fails it `reboot-required` rather than rebooting. A deadline
247
+ (`data.nodeActionCompletionBudgetMs`, `nodeActionContract`) that passes ends an
248
+ action `unverified`.
249
+
250
+ A Spark that executes actions states `ISparkNodeReport.boot` (the kernel boot id
251
+ and whether the host waits for a reboot) and `actionExecutors`, the canonical list
252
+ of action names it executes; Cloudly admits an action only for a node that states
253
+ its executor. Both are optional members an earlier reader refuses, so a Spark sends
254
+ them only to a Cloudly that reads them, like `hostApply`.
255
+
256
+ `data.ISparkFleetTarget` is the one fleet Spark target: a version and the SHA-256
257
+ its release's `SHA256SUMS.txt` states for `install.sh`, with a revision, who set
258
+ it and when, an append-only history (`ISparkFleetTargetChange`) and per-node
259
+ holds (`ISparkNodeTargetHold`). `data.readSparkNodeTargetStanding` places a node
260
+ at, behind or ahead of it, held, unreported or untargeted. The admin requests
261
+ (`getNodeActionPreview`, `createNodeAction` with `confirmation`,
262
+ `cancelNodeAction`, `getSparkFleetTarget`, `setSparkFleetTarget`,
263
+ `setSparkNodeTargetHold`) answer refusals by name from `data.nodeActionRefusals`
264
+ and `data.sparkFleetTargetRefusals`.
265
+
219
266
  The snapshot functions reject unknown keys, accessors, malformed identities and
220
267
  nonfinite/out-of-range numbers, then return detached frozen records. Transports
221
268
  own byte limits, timeouts and cancellation. These contracts do not implement a
@@ -4005,6 +4052,15 @@ A legacy `deployOnPush` service without deployable source moves to a greenfield
4005
4052
  - Instead of the registry push, the deployer calls `importServiceDeploymentLegacyImage`: Cloudly imports the attested image from its own registry into the reserved tag — an index root as it is, a single platform manifest under a one-descriptor index of the manifest's own family — and records release evidence of source `cloudly-legacy-import` naming the legacy source. Steps 3 to 5 follow unchanged; `selectTrustedImageReleaseEvidence` accepts that evidence only with `evidenceSource: 'cloudly-legacy-import'`.
4006
4053
  - The reservation and the import need the capability `deployment:import-legacy`, which only an organization-service-slot grant can carry.
4007
4054
 
4055
+ An existing service deploys one of its own releases again with a release redeploy, which needs no build, push or reservation:
4056
+
4057
+ - `startServiceReleaseDeployment` (`requests.service.IRequest_Any_Cloudly_StartServiceReleaseDeployment`) names the service, the release, an idempotency key and the service's current rollout fence (`expectedRolloutGeneration` at least 1 and `expectedCurrentRolloutId`, both required: a redeploy needs a current plan). `data.validateServiceReleaseDeploymentStartInput` states its shape.
4058
+ - An administrator, or a deployment machine user holding `deployment:redeploy-release` on an existing-service grant, may start one; the operation's actor is the caller. Only a release that was accepted, is still retained and is still whole is deployed; the refusals are `data.serviceReleaseDeploymentRefusalCodes`.
4059
+ - Cloudly creates an existing-service operation whose origin is `releaseRedeploy` (`data.IReleaseRedeployReference`) and whose release tag is the operation id (`redeploy-…`, `data.releaseRedeployContract.tagPrefix`, never a version string), tags the release's root under it in the same repository, records `cloudly-release-redeploy` evidence (`data.IImageReleaseRedeployEvidence`) naming the source release, its earlier tag and its root (`selectTrustedImageReleaseEvidence` accepts it only on a release row that was accepted before), promotes it and runs the operation through rollout, route promotion and public verification itself. It declares what is in force now: the routes and proposed configuration of the operation that owns the service's current plan.
4060
+ - The answer is the operation as started; whether the deploy happened is read with `readServiceDeploymentStatus`. `getServiceDeploymentOperations` lists a service's operations, newest first, a page at a time (`nextBefore`).
4061
+
4062
+ `rollbackServiceImageRelease` and `createDeployment` are deprecated: the first re-opens an earlier operation and nothing calls it, the second stores a deployment record and deploys nothing.
4063
+
4008
4064
  `data.IDeploymentRouteRequest.proxied` carries provider-specific DNS proxy intent as an optional boolean. New route declarations should set it explicitly; omission remains valid for persisted historical operations and legacy callers.
4009
4065
 
4010
4066
  `data.IServiceDeploymentOperation` is the durable revisioned compare-and-set fence for this workflow. Image promotion requires Cloudly-created trusted evidence that binds the operation, actor, repository, exact tag, root digest, and OCI index media type. The service request group also exposes deployment preflight, exact-digest rollback, retry, and cleanup contracts.
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '32.67.0',
6
+ version: '32.69.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../plugins.js';
2
2
  import { isSha256Digest, type TSha256Digest, type TImmutableContainerPlatform } from './immutableimage.js';
3
3
  import type { ISparkNodeReportRecord } from './sparknodereport.js';
4
+ import type { INodeActionExpiry, INodeActionLifecycle } from './nodeaction.js';
4
5
  import type { IClusterNodeHostnameIntent } from './clusternodehostname.js';
5
6
  import type { IPlatformObjectStorageEndpoint } from '../platform/objectstorage.js';
6
7
  import type { IPlatformDatabaseEndpoint } from '../platform/database.js';
@@ -74,11 +75,21 @@ export interface INodeMetricsSample {
74
75
 
75
76
  export type TNodeActionName = 'systemUpgrade' | 'reboot' | 'serveZoneServiceUpdate';
76
77
 
77
- export type TNodeActionStatus = 'pending' | 'running' | 'succeeded' | 'failed';
78
+ /**
79
+ * Every state of a node action; `nodeActionStatusKinds` states which are open and what each means.
80
+ * The first four are the ones the Swarm-era carrier shipped and keep their meaning.
81
+ */
82
+ export type TNodeActionStatus = 'pending' | 'running' | 'succeeded' | 'failed'
83
+ | 'claimed' | 'executing' | 'draining' | 'rebooting' | 'verifying'
84
+ | 'expired' | 'cancelled' | 'unverified';
78
85
 
79
86
  /**
80
87
  * An operator-requested action executed by spark on a node.
81
- * Delivered to spark in metrics-sample responses; results posted back.
88
+ *
89
+ * A Swarm-era record is delivered to the Swarm-era daemon in metrics-sample responses, which
90
+ * posts results back; it carries no `lifecycle`. A node runtime action carries `lifecycle`: Spark
91
+ * takes it from `sparkNodeActionContracts.offer` and states each step on
92
+ * `sparkNodeActionContracts.transition`, and Cloudly verifies it from the node's reports.
82
93
  */
83
94
  export interface INodeAction {
84
95
  id: string;
@@ -94,6 +105,10 @@ export interface INodeAction {
94
105
  startedAt?: number;
95
106
  finishedAt?: number;
96
107
  resultText?: string;
108
+ /** The node runtime's lifecycle; absent on a Swarm-era record. */
109
+ lifecycle?: INodeActionLifecycle;
110
+ /** Why the action ended `expired`; present exactly then. */
111
+ expiry?: INodeActionExpiry;
97
112
  }
98
113
 
99
114
  export interface IServeZoneServiceRuntimeInfo {
@@ -4,6 +4,7 @@ import type { IImageRolloutStatus, IImmutableImageDeploymentPlan, TSha256Digest
4
4
  import { normalizeImmutableReleaseTag, normalizeSha256Digest } from './immutableimage.js';
5
5
  import type { ILegacyImageImportReference } from './deploymentlegacyimport.js';
6
6
  import { validateLegacyImageImportReference } from './deploymentlegacyimport.js';
7
+ import type { IReleaseRedeployReference } from './deploymentreleaseredeploy.js';
7
8
  import type { IRegistryTarget } from './registry.js';
8
9
  import { hasExactKeys } from '../private/dataproperties.js';
9
10
  import { normalizeServiceAbsolutePath, validateServiceContainerArgs } from './service.js';
@@ -27,6 +28,7 @@ interface IDeploymentReservationInputBase {
27
28
  interface ISourceDeploymentOrigin {
28
29
  sourceRevision: string;
29
30
  legacyImport?: never;
31
+ releaseRedeploy?: never;
30
32
  }
31
33
 
32
34
  /**
@@ -36,6 +38,18 @@ interface ISourceDeploymentOrigin {
36
38
  interface ILegacyImportDeploymentOrigin {
37
39
  legacyImport: ILegacyImageImportReference;
38
40
  sourceRevision?: never;
41
+ releaseRedeploy?: never;
42
+ }
43
+
44
+ /**
45
+ * An existing-service deployment Cloudly started and runs itself, of one of the service's own
46
+ * accepted releases (`startServiceReleaseDeployment`): nothing is built or pushed, so no source
47
+ * revision is stated. Never reserved through `reserveServiceDeployment`.
48
+ */
49
+ interface IReleaseRedeployDeploymentOrigin {
50
+ releaseRedeploy: IReleaseRedeployReference;
51
+ sourceRevision?: never;
52
+ legacyImport?: never;
39
53
  }
40
54
 
41
55
  export interface IExistingServiceDeploymentReservationInput
@@ -265,6 +279,9 @@ export const validateDeploymentReservationInput = (inputArg: unknown): string[]
265
279
  errors.push(`${field} must be a bounded canonical identifier`);
266
280
  }
267
281
  }
282
+ if (inputArg.releaseRedeploy !== undefined) {
283
+ errors.push('a release redeploy is started by startServiceReleaseDeployment, never reserved');
284
+ }
268
285
  if (inputArg.legacyImport !== undefined) {
269
286
  errors.push(...validateLegacyImageImportReference(inputArg.legacyImport));
270
287
  if (inputArg.mode !== 'greenfield') {
@@ -432,12 +449,14 @@ export interface IServiceDeploymentOperation {
432
449
 
433
450
  /**
434
451
  * An operation's durable state. It states where its image comes from exactly as its reservation
435
- * did: a `sourceRevision` for an image its deployer builds, or a `legacyImport` (greenfield only)
436
- * for a legacy service's attested image Cloudly imports.
452
+ * did: a `sourceRevision` for an image its deployer builds, a `legacyImport` (greenfield only)
453
+ * for a legacy service's attested image Cloudly imports, or a `releaseRedeploy` (existing-service
454
+ * only, never reserved) for one of the service's own releases Cloudly deploys again.
437
455
  */
438
456
  export type IServiceDeploymentOperationData = IServiceDeploymentOperationStateData & (
439
457
  | ISourceDeploymentOrigin
440
458
  | ILegacyImportDeploymentOrigin
459
+ | IReleaseRedeployDeploymentOrigin
441
460
  );
442
461
 
443
462
  interface IServiceDeploymentOperationStateData {