@modernedi/configuration-runner 0.2.0-rc.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAEA,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,MAAM,GACP,MAAM,UAAU,CAAC;AAElB,IAAI,CAAC;IACH,OAAO,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5C,OAAO,CAAC,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { type ConfigurationPlanRequest, type ModernEdiClient } from "@modernedi/sdk";
2
+ import { type ConfigurationApplyResultArtifact, type ConfigurationPlanArtifact } from "./artifacts.js";
3
+ export declare const DEFAULT_APPLY_TIMEOUT_MS: number;
4
+ type ConfigurationAsCodeClient = Pick<ModernEdiClient["configurationAsCode"], "applyIntegrationConfigurationRaw" | "getIntegrationConfigurationApplyOperation" | "planIntegrationConfiguration">;
5
+ export interface ConfigurationRunnerClient {
6
+ configurationAsCode: ConfigurationAsCodeClient;
7
+ }
8
+ export interface ApplyReviewedOptions {
9
+ client: ConfigurationRunnerClient;
10
+ request: ConfigurationPlanRequest;
11
+ reviewedPlan: ConfigurationPlanArtifact;
12
+ idempotencyKey: string;
13
+ timeoutMs?: number;
14
+ appUrl?: string;
15
+ now?: () => number;
16
+ sleep?: (milliseconds: number) => Promise<void>;
17
+ onResult?: (result: ConfigurationApplyResultArtifact) => Promise<void>;
18
+ }
19
+ export interface WaitForConfigurationApplyOptions {
20
+ client: ConfigurationRunnerClient;
21
+ result: ConfigurationApplyResultArtifact;
22
+ timeoutMs?: number;
23
+ appUrl?: string;
24
+ now?: () => number;
25
+ sleep?: (milliseconds: number) => Promise<void>;
26
+ onResult?: (result: ConfigurationApplyResultArtifact) => Promise<void>;
27
+ }
28
+ export declare function planConfiguration(client: ConfigurationRunnerClient, request: ConfigurationPlanRequest): Promise<ConfigurationPlanArtifact>;
29
+ export declare function applyReviewedConfiguration(options: ApplyReviewedOptions): Promise<ConfigurationApplyResultArtifact>;
30
+ export declare function waitForConfigurationApply(options: WaitForConfigurationApplyOptions): Promise<ConfigurationApplyResultArtifact>;
31
+ export {};
32
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,wBAAwB,EAE7B,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAGL,KAAK,gCAAgC,EACrC,KAAK,yBAAyB,EAC/B,MAAM,gBAAgB,CAAC;AAKxB,eAAO,MAAM,wBAAwB,QAAc,CAAC;AAEpD,KAAK,yBAAyB,GAAG,IAAI,CACnC,eAAe,CAAC,qBAAqB,CAAC,EACpC,kCAAkC,GAClC,2CAA2C,GAC3C,8BAA8B,CACjC,CAAC;AAEF,MAAM,WAAW,yBAAyB;IACxC,mBAAmB,EAAE,yBAAyB,CAAC;CAChD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,yBAAyB,CAAC;IAClC,OAAO,EAAE,wBAAwB,CAAC;IAClC,YAAY,EAAE,yBAAyB,CAAC;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,gCAAgC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAED,MAAM,WAAW,gCAAgC;IAC/C,MAAM,EAAE,yBAAyB,CAAC;IAClC,MAAM,EAAE,gCAAgC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,gCAAgC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,yBAAyB,EACjC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,yBAAyB,CAAC,CAGpC;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,gCAAgC,CAAC,CAuD3C;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,gCAAgC,CAAC,CAgD3C"}
package/dist/runner.js ADDED
@@ -0,0 +1,174 @@
1
+ import { ConfigurationPlanResponseToJSON, getModernEdiResponseMetadata, } from "@modernedi/sdk";
2
+ import { configurationApplyResultArtifact, configurationPlanArtifact, } from "./artifacts.js";
3
+ import { canonicalJson } from "./canonical-json.js";
4
+ import { runnerError } from "./errors.js";
5
+ const DEFAULT_POLL_INTERVAL_MS = 15_000;
6
+ export const DEFAULT_APPLY_TIMEOUT_MS = 15 * 60_000;
7
+ export async function planConfiguration(client, request) {
8
+ const plan = await currentPlan(client, request);
9
+ return configurationPlanArtifact(plan);
10
+ }
11
+ export async function applyReviewedConfiguration(options) {
12
+ const timeoutMs = options.timeoutMs ?? DEFAULT_APPLY_TIMEOUT_MS;
13
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) {
14
+ throw runnerError("APPLY_TIMEOUT_INVALID", "Apply timeout must be a positive whole number of milliseconds.", 64);
15
+ }
16
+ assertIdempotencyKey(options.idempotencyKey);
17
+ assertReviewedPlanApplicable(options.reviewedPlan);
18
+ const replanned = await currentPlan(options.client, options.request);
19
+ assertReviewedPlanMatches(options.reviewedPlan, replanned);
20
+ const submitted = await options.client.configurationAsCode
21
+ .applyIntegrationConfigurationRaw({
22
+ idempotencyKey: options.idempotencyKey,
23
+ ifMatch: replanned.currentSnapshotEtag,
24
+ configurationApplyRequest: {
25
+ planSha256: replanned.planSha256,
26
+ files: options.request.files,
27
+ },
28
+ });
29
+ const metadata = getModernEdiResponseMetadata(submitted.raw);
30
+ let result = await submitted.value();
31
+ assertOperationMatchesReviewedPlan(options.reviewedPlan, result);
32
+ const submittedOperationId = result.operation.operationId;
33
+ let artifact = configurationApplyResultArtifact(options.reviewedPlan, result, metadata.idempotencyReplayed ?? false, options.appUrl);
34
+ await options.onResult?.(artifact);
35
+ result = await waitForApplyOperation(options.client, result, {
36
+ timeoutMs,
37
+ initialPollIntervalMs: retryAfterMilliseconds(metadata.retryAfter),
38
+ now: options.now,
39
+ sleep: options.sleep,
40
+ onOperation: async (operation) => {
41
+ assertOperationMatchesReviewedPlan(options.reviewedPlan, operation, submittedOperationId);
42
+ artifact = configurationApplyResultArtifact(options.reviewedPlan, operation, metadata.idempotencyReplayed ?? false, options.appUrl);
43
+ await options.onResult?.(artifact);
44
+ },
45
+ });
46
+ return artifact;
47
+ }
48
+ export async function waitForConfigurationApply(options) {
49
+ const timeoutMs = options.timeoutMs ?? DEFAULT_APPLY_TIMEOUT_MS;
50
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) {
51
+ throw runnerError("APPLY_TIMEOUT_INVALID", "Apply timeout must be a positive whole number of milliseconds.", 64);
52
+ }
53
+ const operationId = requireStoredOperationString(options.result, "operationId");
54
+ const storedStatus = requireStoredOperationString(options.result, "status");
55
+ if (storedStatus !== "PENDING" && storedStatus !== "SUCCEEDED") {
56
+ throw runnerError("APPLY_RESULT_STATUS_INVALID", `Stored configuration apply ${operationId} has unsupported status ${storedStatus}.`, 4);
57
+ }
58
+ let response = await options.client.configurationAsCode
59
+ .getIntegrationConfigurationApplyOperation({ operationId });
60
+ assertOperationMatchesStoredResult(options.result, response);
61
+ let artifact = configurationApplyResultArtifact(options.result.reviewed, response, options.result.idempotencyReplayed, options.appUrl);
62
+ await options.onResult?.(artifact);
63
+ response = await waitForApplyOperation(options.client, response, {
64
+ timeoutMs,
65
+ now: options.now,
66
+ sleep: options.sleep,
67
+ onOperation: async (operation) => {
68
+ assertOperationMatchesStoredResult(options.result, operation);
69
+ artifact = configurationApplyResultArtifact(options.result.reviewed, operation, options.result.idempotencyReplayed, options.appUrl);
70
+ await options.onResult?.(artifact);
71
+ },
72
+ });
73
+ return artifact;
74
+ }
75
+ async function currentPlan(client, request) {
76
+ return client.configurationAsCode.planIntegrationConfiguration({
77
+ configurationPlanRequest: request,
78
+ });
79
+ }
80
+ async function waitForApplyOperation(client, initial, options) {
81
+ const now = options.now ?? Date.now;
82
+ const sleep = options.sleep ?? delay;
83
+ const startedAt = now();
84
+ const deadline = startedAt + options.timeoutMs;
85
+ const pollIntervalMs = options.initialPollIntervalMs
86
+ ?? DEFAULT_POLL_INTERVAL_MS;
87
+ let current = initial;
88
+ const operationId = initial.operation.operationId;
89
+ while (current.operation.status === "PENDING") {
90
+ const remaining = deadline - now();
91
+ if (remaining <= 0) {
92
+ throw runnerError("APPLY_POLL_TIMEOUT", `Configuration apply ${current.operation.operationId} is still PENDING after ${options.timeoutMs} ms. The database change may already be committed; resume polling this operation instead of submitting another apply.`, 4);
93
+ }
94
+ await sleep(Math.min(pollIntervalMs, remaining));
95
+ current = await client.configurationAsCode
96
+ .getIntegrationConfigurationApplyOperation({
97
+ operationId,
98
+ });
99
+ if (current.operation.operationId !== operationId) {
100
+ throw runnerError("APPLY_OPERATION_IDENTITY_MISMATCH", `ModernEDI returned operation ${current.operation.operationId} while polling ${operationId}.`, 4);
101
+ }
102
+ await options.onOperation?.(current);
103
+ }
104
+ if (current.operation.status !== "SUCCEEDED") {
105
+ throw runnerError("APPLY_STATUS_UNSUPPORTED", `Configuration apply ${current.operation.operationId} returned unsupported status ${current.operation.status}.`);
106
+ }
107
+ return current;
108
+ }
109
+ function assertOperationMatchesReviewedPlan(reviewed, current, operationId) {
110
+ if ((operationId !== undefined && current.operation.operationId !== operationId)
111
+ || current.operation.desiredBundleSha256 !== reviewed.desiredBundleSha256
112
+ || current.operation.planSha256 !== reviewed.planSha256) {
113
+ throw runnerError("APPLY_OPERATION_IDENTITY_MISMATCH", "ModernEDI returned an apply operation that does not match the reviewed bundle and plan identities.", 4);
114
+ }
115
+ }
116
+ function assertOperationMatchesStoredResult(stored, current) {
117
+ const operationId = requireStoredOperationString(stored, "operationId");
118
+ if (current.operation.operationId !== operationId
119
+ || current.operation.desiredBundleSha256
120
+ !== stored.reviewed.desiredBundleSha256
121
+ || current.operation.planSha256 !== stored.reviewed.planSha256) {
122
+ throw runnerError("APPLY_OPERATION_IDENTITY_MISMATCH", `ModernEDI returned an operation that does not match stored apply ${operationId}.`, 4);
123
+ }
124
+ }
125
+ function requireStoredOperationString(stored, field) {
126
+ const value = stored.operation[field];
127
+ if (typeof value !== "string" || !value) {
128
+ throw runnerError("APPLY_RESULT_INVALID", `Stored apply operation ${field} must be a non-empty string.`, 4);
129
+ }
130
+ return value;
131
+ }
132
+ function assertReviewedPlanApplicable(reviewed) {
133
+ if (reviewed.planSha256 === null
134
+ || reviewed.plan.applicable !== true) {
135
+ throw runnerError("REVIEWED_PLAN_NOT_APPLICABLE", "Reviewed plan is not applicable and cannot authorize configuration changes.", 3);
136
+ }
137
+ }
138
+ function assertReviewedPlanMatches(reviewed, current) {
139
+ if (!current.applicable || current.planSha256 === null) {
140
+ throw runnerError("REVIEWED_PLAN_NO_LONGER_APPLICABLE", "Protected apply re-plan is not applicable. Review the new diagnostics; no apply was submitted.", 3);
141
+ }
142
+ if (current.desiredBundleSha256 !== reviewed.desiredBundleSha256) {
143
+ throw runnerError("REVIEWED_BUNDLE_MISMATCH", `Protected apply bundle ${current.desiredBundleSha256} does not match reviewed bundle ${reviewed.desiredBundleSha256}. No apply was submitted.`, 3);
144
+ }
145
+ if (current.planSha256 !== reviewed.planSha256) {
146
+ throw runnerError("REVIEWED_PLAN_MISMATCH", `Protected apply plan ${current.planSha256} does not match reviewed plan ${reviewed.planSha256}. Workspace state or validation context changed; review a fresh plan before applying.`, 3);
147
+ }
148
+ const currentWire = JSON.parse(JSON.stringify(ConfigurationPlanResponseToJSON(current)));
149
+ if (canonicalJson(currentWire) !== canonicalJson(reviewed.plan)) {
150
+ throw runnerError("REVIEWED_PLAN_CONTENT_MISMATCH", "Fresh protected apply plan does not exactly match the complete reviewed plan artifact. No apply was submitted.", 3);
151
+ }
152
+ }
153
+ function assertIdempotencyKey(value) {
154
+ if (!value.trim()
155
+ || value !== value.trim()
156
+ || value.length > 200
157
+ || /[\r\n]/u.test(value)) {
158
+ throw runnerError("IDEMPOTENCY_KEY_INVALID", "MODERNEDI_IDEMPOTENCY_KEY must be a persisted non-empty value of at most 200 characters without surrounding whitespace or line breaks.", 64);
159
+ }
160
+ }
161
+ function retryAfterMilliseconds(value) {
162
+ if (value === undefined) {
163
+ return undefined;
164
+ }
165
+ const seconds = Number(value);
166
+ if (!Number.isFinite(seconds) || seconds < 0) {
167
+ return undefined;
168
+ }
169
+ return Math.max(1, Math.ceil(seconds * 1_000));
170
+ }
171
+ function delay(milliseconds) {
172
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
173
+ }
174
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@modernedi/configuration-runner",
3
+ "version": "0.2.0-rc.0",
4
+ "description": "Vendor-neutral CI runner for reviewed ModernEDI configuration plans",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/brcolow/modernedi.git",
9
+ "directory": "automation/configuration-runner"
10
+ },
11
+ "type": "module",
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js"
18
+ }
19
+ },
20
+ "bin": {
21
+ "modernedi-configuration": "./dist/main.js"
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "schemas",
26
+ "README.md",
27
+ "LICENSE"
28
+ ],
29
+ "sideEffects": false,
30
+ "engines": {
31
+ "node": ">=20"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public",
35
+ "registry": "https://registry.npmjs.org/"
36
+ },
37
+ "scripts": {
38
+ "clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
39
+ "build": "npm run clean && tsc -p tsconfig.json",
40
+ "build:repo": "npm --prefix ../../sdks/typescript run build && node ./scripts/link-repository-sdk.mjs && npm run clean && node ../../sdks/typescript/node_modules/typescript/bin/tsc -p tsconfig.json",
41
+ "test": "npm run build && node --test test/*.test.mjs",
42
+ "test:repo": "npm run build:repo && node --test test/*.test.mjs",
43
+ "verify:dependency-contract": "node ./scripts/verify-dependency-contract.mjs",
44
+ "verify": "npm run verify:dependency-contract && npm test && npm pack --dry-run",
45
+ "verify:repo": "npm run verify:dependency-contract && npm run test:repo && npm run verify:dependency-contract && npm pack --dry-run --ignore-scripts",
46
+ "prepack": "npm run build",
47
+ "prepublishOnly": "npm run verify"
48
+ },
49
+ "dependencies": {
50
+ "@modernedi/sdk": "0.3.0"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "20.19.43",
54
+ "typescript": "^7.0.2"
55
+ }
56
+ }
@@ -0,0 +1,218 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://www.modernedi.com/schemas/configuration-runner/v1/configuration-apply-result-artifact.schema.json",
4
+ "title": "ModernEDI Configuration Apply Result Artifact",
5
+ "description": "Deterministic result artifact emitted by @modernedi/configuration-runner after a reviewed apply.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "apiVersion",
10
+ "kind",
11
+ "reviewed",
12
+ "idempotencyReplayed",
13
+ "workspaceUrl",
14
+ "operation"
15
+ ],
16
+ "properties": {
17
+ "apiVersion": {
18
+ "const": "modernedi.com/configuration-runner/v1"
19
+ },
20
+ "kind": {
21
+ "const": "ConfigurationApplyResultArtifact"
22
+ },
23
+ "reviewed": {
24
+ "type": "object",
25
+ "additionalProperties": false,
26
+ "required": [
27
+ "desiredBundleSha256",
28
+ "planSha256"
29
+ ],
30
+ "properties": {
31
+ "desiredBundleSha256": {
32
+ "$ref": "configuration-plan-artifact.schema.json#/$defs/sha256"
33
+ },
34
+ "planSha256": {
35
+ "$ref": "configuration-plan-artifact.schema.json#/$defs/sha256"
36
+ }
37
+ }
38
+ },
39
+ "idempotencyReplayed": {
40
+ "type": [
41
+ "boolean",
42
+ "null"
43
+ ]
44
+ },
45
+ "workspaceUrl": {
46
+ "type": "string",
47
+ "format": "uri"
48
+ },
49
+ "operation": {
50
+ "$ref": "#/$defs/applyOperation"
51
+ }
52
+ },
53
+ "$defs": {
54
+ "runtimePublication": {
55
+ "type": "object",
56
+ "additionalProperties": false,
57
+ "required": [
58
+ "state",
59
+ "retrying"
60
+ ],
61
+ "properties": {
62
+ "state": {
63
+ "type": "string",
64
+ "enum": [
65
+ "published",
66
+ "pending",
67
+ "not_provisioned"
68
+ ]
69
+ },
70
+ "retrying": {
71
+ "type": "boolean"
72
+ },
73
+ "message": {
74
+ "type": "string"
75
+ }
76
+ }
77
+ },
78
+ "applyOperation": {
79
+ "type": "object",
80
+ "additionalProperties": false,
81
+ "allOf": [
82
+ {
83
+ "if": {
84
+ "properties": {
85
+ "status": {
86
+ "const": "PENDING"
87
+ }
88
+ },
89
+ "required": [
90
+ "status"
91
+ ]
92
+ },
93
+ "then": {
94
+ "properties": {
95
+ "completedAt": {
96
+ "type": "null"
97
+ },
98
+ "runtimePublication": {
99
+ "properties": {
100
+ "state": {
101
+ "const": "pending"
102
+ },
103
+ "retrying": {
104
+ "const": true
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
110
+ },
111
+ {
112
+ "if": {
113
+ "properties": {
114
+ "status": {
115
+ "const": "SUCCEEDED"
116
+ }
117
+ },
118
+ "required": [
119
+ "status"
120
+ ]
121
+ },
122
+ "then": {
123
+ "properties": {
124
+ "completedAt": {
125
+ "type": "string",
126
+ "format": "date-time"
127
+ },
128
+ "runtimePublication": {
129
+ "properties": {
130
+ "state": {
131
+ "enum": [
132
+ "published",
133
+ "not_provisioned"
134
+ ]
135
+ },
136
+ "retrying": {
137
+ "const": false
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ ],
145
+ "required": [
146
+ "operationId",
147
+ "status",
148
+ "desiredBundleSha256",
149
+ "planSha256",
150
+ "baseSnapshotEtag",
151
+ "appliedSnapshotEtag",
152
+ "runtimeConfigurationRevision",
153
+ "summary",
154
+ "operations",
155
+ "runtimePublication",
156
+ "requestedAt",
157
+ "committedAt",
158
+ "completedAt"
159
+ ],
160
+ "properties": {
161
+ "operationId": {
162
+ "type": "string",
163
+ "pattern": "^apply-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
164
+ },
165
+ "status": {
166
+ "type": "string",
167
+ "enum": [
168
+ "PENDING",
169
+ "SUCCEEDED"
170
+ ]
171
+ },
172
+ "desiredBundleSha256": {
173
+ "$ref": "configuration-plan-artifact.schema.json#/$defs/sha256"
174
+ },
175
+ "planSha256": {
176
+ "$ref": "configuration-plan-artifact.schema.json#/$defs/sha256"
177
+ },
178
+ "baseSnapshotEtag": {
179
+ "$ref": "configuration-plan-artifact.schema.json#/$defs/etag"
180
+ },
181
+ "appliedSnapshotEtag": {
182
+ "$ref": "configuration-plan-artifact.schema.json#/$defs/etag"
183
+ },
184
+ "runtimeConfigurationRevision": {
185
+ "type": "integer",
186
+ "minimum": 0
187
+ },
188
+ "summary": {
189
+ "$ref": "configuration-plan-artifact.schema.json#/$defs/summary"
190
+ },
191
+ "operations": {
192
+ "type": "array",
193
+ "items": {
194
+ "$ref": "configuration-plan-artifact.schema.json#/$defs/operation"
195
+ }
196
+ },
197
+ "runtimePublication": {
198
+ "$ref": "#/$defs/runtimePublication"
199
+ },
200
+ "requestedAt": {
201
+ "type": "string",
202
+ "format": "date-time"
203
+ },
204
+ "committedAt": {
205
+ "type": "string",
206
+ "format": "date-time"
207
+ },
208
+ "completedAt": {
209
+ "type": [
210
+ "string",
211
+ "null"
212
+ ],
213
+ "format": "date-time"
214
+ }
215
+ }
216
+ }
217
+ }
218
+ }