@serve.zone/interfaces 14.0.0 → 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +19 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/deploymentadoption.d.ts +95 -0
- package/dist_ts/data/deploymentadoption.js +303 -0
- package/dist_ts/data/deploymentoperation.d.ts +161 -0
- package/dist_ts/data/deploymentoperation.js +213 -0
- package/dist_ts/data/deploymentpreflight.d.ts +15 -16
- package/dist_ts/data/deploymentpreflight.js +75 -42
- package/dist_ts/data/immutableimage.d.ts +33 -1
- package/dist_ts/data/immutableimage.js +88 -1
- package/dist_ts/data/index.d.ts +2 -0
- package/dist_ts/data/index.js +3 -1
- package/dist_ts/data/service.d.ts +3 -1
- package/dist_ts/data/user.d.ts +14 -2
- package/dist_ts/data/user.js +59 -2
- package/dist_ts/requests/admin.d.ts +4 -6
- package/dist_ts/requests/service.d.ts +100 -5
- package/package.json +1 -1
- package/readme.md +14 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/deploymentadoption.ts +445 -0
- package/ts/data/deploymentoperation.ts +441 -0
- package/ts/data/deploymentpreflight.ts +125 -73
- package/ts/data/immutableimage.ts +118 -1
- package/ts/data/index.ts +2 -0
- package/ts/data/service.ts +3 -1
- package/ts/data/user.ts +91 -2
- package/ts/requests/admin.ts +4 -6
- package/ts/requests/service.ts +144 -5
package/changelog.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-07-20 - 16.0.0
|
|
4
|
+
|
|
5
|
+
### Breaking Changes
|
|
6
|
+
|
|
7
|
+
- add attested existing-service adoption contracts (deployment)
|
|
8
|
+
- Add a mutation-free adoption preflight and a digest-fenced, idempotent adoption request.
|
|
9
|
+
- Require explicit service-scoped deployment:adopt-existing authority.
|
|
10
|
+
- Bind registry, release, target-scope, and healthy runtime digest evidence before switching a mutable service to immutable rollout state.
|
|
11
|
+
|
|
12
|
+
## 2026-07-20 - 15.0.0
|
|
13
|
+
|
|
14
|
+
### Breaking Changes
|
|
15
|
+
|
|
16
|
+
- add scoped immutable deployment operation contracts (deployment)
|
|
17
|
+
- Replace machine deployment grant fields with an exact organization/service or organization/service-slot grant and use JWT-only credentials on scoped deployment RPCs.
|
|
18
|
+
- Add revisioned reserve, status, route promotion, retry, and cleanup contracts with complete configuration, rollout, wildcard-route, readiness, and TLS evidence validation.
|
|
19
|
+
- Require authenticated registry evidence bound to the operation, actor, service, image, registry host, repository, exact tag, root digest, and OCI index media type.
|
|
20
|
+
- Require promotion and rollback requests to carry exact operation/repository/tag/digest fences and immutable plans and verified runtime tasks to expose exact rollout and digest evidence.
|
|
21
|
+
|
|
3
22
|
## 2026-07-19 - 14.0.0
|
|
4
23
|
|
|
5
24
|
### Breaking Changes
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/interfaces',
|
|
6
|
-
version: '
|
|
6
|
+
version: '16.0.0',
|
|
7
7
|
description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { IDeploymentPreflightRuntimeTask, IOciPlatformDescriptorSummary } from './deploymentpreflight.js';
|
|
2
|
+
import type { IImmutableImageDeploymentPlan, IImmutableImageTargetScope, TOciManifestMediaType, TSha256Digest } from './immutableimage.js';
|
|
3
|
+
import type { IRegistryTarget } from './registry.js';
|
|
4
|
+
export type TServiceDeploymentAdoptionDecision = 'GO' | 'NO-GO';
|
|
5
|
+
/**
|
|
6
|
+
* Canonical sha256 hash of the complete adoption preflight snapshot. It is a
|
|
7
|
+
* state/TOCTOU fence and must never be substituted with the OCI image digest.
|
|
8
|
+
*/
|
|
9
|
+
export type TServiceDeploymentAdoptionDigest = TSha256Digest & {
|
|
10
|
+
readonly __serviceDeploymentAdoptionDigest: unique symbol;
|
|
11
|
+
};
|
|
12
|
+
export type TServiceDeploymentAdoptionBlockerCode = 'INVALID_REQUEST' | 'AUTHORIZATION_MISSING' | 'SERVICE_NOT_FOUND' | 'SERVICE_OWNERSHIP_MISMATCH' | 'SERVICE_ALREADY_IMMUTABLE' | 'SERVICE_STATE_CONFLICT' | 'REGISTRY_TARGET_MISSING' | 'REGISTRY_REFERENCE_INVALID' | 'REGISTRY_DIGEST_MISSING' | 'OCI_INDEX_REQUIRED' | 'OCI_PLATFORM_MISSING' | 'RELEASE_NOT_FOUND' | 'RELEASE_TAG_AMBIGUOUS' | 'TARGET_SCOPE_UNAVAILABLE' | 'RUNTIME_ATTESTATION_INCOMPLETE' | 'RUNTIME_DIGEST_MISMATCH';
|
|
13
|
+
export interface IServiceDeploymentAdoptionBlocker {
|
|
14
|
+
code: TServiceDeploymentAdoptionBlockerCode;
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
17
|
+
export interface IServiceDeploymentAdoptionPreflightInput {
|
|
18
|
+
requestId: string;
|
|
19
|
+
organizationId: string;
|
|
20
|
+
serviceId: string;
|
|
21
|
+
}
|
|
22
|
+
export interface IServiceDeploymentAdoptionInput extends IServiceDeploymentAdoptionPreflightInput {
|
|
23
|
+
idempotencyKey: string;
|
|
24
|
+
expectedAdoptionDigest: TServiceDeploymentAdoptionDigest;
|
|
25
|
+
}
|
|
26
|
+
interface IServiceDeploymentAdoptionReportBase {
|
|
27
|
+
schemaVersion: 1;
|
|
28
|
+
mutationPerformed: false;
|
|
29
|
+
requestId: string;
|
|
30
|
+
generatedAt: number;
|
|
31
|
+
runtimeAttestation: {
|
|
32
|
+
requiredReplicaCount: number;
|
|
33
|
+
observedReplicaCount: number;
|
|
34
|
+
healthyReplicaCount: number;
|
|
35
|
+
observedDigestReplicaCount: number;
|
|
36
|
+
observedDigestConsistent: boolean;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
interface IServiceDeploymentAdoptionServiceSnapshot {
|
|
40
|
+
organizationId: string;
|
|
41
|
+
serviceId: string;
|
|
42
|
+
serviceName: string;
|
|
43
|
+
imageId: string;
|
|
44
|
+
deployOnPush: boolean;
|
|
45
|
+
immutableImageRequired: boolean;
|
|
46
|
+
configuredReference: string;
|
|
47
|
+
registryTarget: IRegistryTarget;
|
|
48
|
+
}
|
|
49
|
+
interface IServiceDeploymentAdoptionRegistrySnapshot {
|
|
50
|
+
tag?: string;
|
|
51
|
+
digest?: TSha256Digest;
|
|
52
|
+
mediaType?: TOciManifestMediaType;
|
|
53
|
+
platforms: IOciPlatformDescriptorSummary[];
|
|
54
|
+
releaseId?: string;
|
|
55
|
+
releaseTag?: string;
|
|
56
|
+
}
|
|
57
|
+
export interface IServiceDeploymentAdoptionGoReport extends IServiceDeploymentAdoptionReportBase {
|
|
58
|
+
decision: 'GO';
|
|
59
|
+
service: IServiceDeploymentAdoptionServiceSnapshot & {
|
|
60
|
+
deployOnPush: true;
|
|
61
|
+
immutableImageRequired: false;
|
|
62
|
+
};
|
|
63
|
+
registry: IServiceDeploymentAdoptionRegistrySnapshot & {
|
|
64
|
+
tag: string;
|
|
65
|
+
digest: TSha256Digest;
|
|
66
|
+
mediaType: 'application/vnd.oci.image.index.v1+json' | 'application/vnd.docker.distribution.manifest.list.v2+json';
|
|
67
|
+
platforms: [IOciPlatformDescriptorSummary, ...IOciPlatformDescriptorSummary[]];
|
|
68
|
+
releaseId: string;
|
|
69
|
+
releaseTag: string;
|
|
70
|
+
};
|
|
71
|
+
runtimeTasks: [IDeploymentPreflightRuntimeTask, ...IDeploymentPreflightRuntimeTask[]];
|
|
72
|
+
targetScope: IImmutableImageTargetScope;
|
|
73
|
+
adoptionDigest: TServiceDeploymentAdoptionDigest;
|
|
74
|
+
blockers: [];
|
|
75
|
+
}
|
|
76
|
+
export interface IServiceDeploymentAdoptionNoGoReport extends IServiceDeploymentAdoptionReportBase {
|
|
77
|
+
decision: 'NO-GO';
|
|
78
|
+
service?: IServiceDeploymentAdoptionServiceSnapshot;
|
|
79
|
+
registry: IServiceDeploymentAdoptionRegistrySnapshot;
|
|
80
|
+
runtimeTasks: IDeploymentPreflightRuntimeTask[];
|
|
81
|
+
targetScope?: IImmutableImageTargetScope;
|
|
82
|
+
adoptionDigest?: never;
|
|
83
|
+
blockers: [IServiceDeploymentAdoptionBlocker, ...IServiceDeploymentAdoptionBlocker[]];
|
|
84
|
+
}
|
|
85
|
+
export type IServiceDeploymentAdoptionReport = IServiceDeploymentAdoptionGoReport | IServiceDeploymentAdoptionNoGoReport;
|
|
86
|
+
export interface IServiceDeploymentAdoptionResult {
|
|
87
|
+
adoptionId: string;
|
|
88
|
+
adoptionDigest: TServiceDeploymentAdoptionDigest;
|
|
89
|
+
idempotentReplay: boolean;
|
|
90
|
+
plan: IImmutableImageDeploymentPlan;
|
|
91
|
+
}
|
|
92
|
+
export declare const validateServiceDeploymentAdoptionPreflightInput: (inputArg: unknown) => string[];
|
|
93
|
+
export declare const validateServiceDeploymentAdoptionInput: (inputArg: unknown) => string[];
|
|
94
|
+
export declare const validateServiceDeploymentAdoptionReport: (reportArg: unknown) => string[];
|
|
95
|
+
export {};
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { normalizeImmutableReleaseTag, normalizeSha256Digest } from './immutableimage.js';
|
|
2
|
+
const boundaryIdentifierRegex = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,199}$/;
|
|
3
|
+
const indexMediaTypes = new Set([
|
|
4
|
+
'application/vnd.oci.image.index.v1+json',
|
|
5
|
+
'application/vnd.docker.distribution.manifest.list.v2+json',
|
|
6
|
+
]);
|
|
7
|
+
const adoptionBlockerCodes = new Set([
|
|
8
|
+
'INVALID_REQUEST',
|
|
9
|
+
'AUTHORIZATION_MISSING',
|
|
10
|
+
'SERVICE_NOT_FOUND',
|
|
11
|
+
'SERVICE_OWNERSHIP_MISMATCH',
|
|
12
|
+
'SERVICE_ALREADY_IMMUTABLE',
|
|
13
|
+
'SERVICE_STATE_CONFLICT',
|
|
14
|
+
'REGISTRY_TARGET_MISSING',
|
|
15
|
+
'REGISTRY_REFERENCE_INVALID',
|
|
16
|
+
'REGISTRY_DIGEST_MISSING',
|
|
17
|
+
'OCI_INDEX_REQUIRED',
|
|
18
|
+
'OCI_PLATFORM_MISSING',
|
|
19
|
+
'RELEASE_NOT_FOUND',
|
|
20
|
+
'RELEASE_TAG_AMBIGUOUS',
|
|
21
|
+
'TARGET_SCOPE_UNAVAILABLE',
|
|
22
|
+
'RUNTIME_ATTESTATION_INCOMPLETE',
|
|
23
|
+
'RUNTIME_DIGEST_MISMATCH',
|
|
24
|
+
]);
|
|
25
|
+
const isRecord = (valueArg) => Boolean(valueArg) && typeof valueArg === 'object' && !Array.isArray(valueArg);
|
|
26
|
+
const isBoundedIdentifier = (valueArg) => typeof valueArg === 'string' && boundaryIdentifierRegex.test(valueArg);
|
|
27
|
+
const isCanonicalDigest = (valueArg) => Boolean(normalizeSha256Digest(valueArg)) && normalizeSha256Digest(valueArg) === valueArg;
|
|
28
|
+
const isNonNegativeInteger = (valueArg) => Number.isSafeInteger(valueArg) && valueArg >= 0;
|
|
29
|
+
export const validateServiceDeploymentAdoptionPreflightInput = (inputArg) => {
|
|
30
|
+
if (!isRecord(inputArg))
|
|
31
|
+
return ['adoption preflight input must be an object'];
|
|
32
|
+
const errors = [];
|
|
33
|
+
if (!isBoundedIdentifier(inputArg.requestId)) {
|
|
34
|
+
errors.push('requestId must be a bounded canonical identifier');
|
|
35
|
+
}
|
|
36
|
+
for (const key of ['organizationId', 'serviceId']) {
|
|
37
|
+
if (!isBoundedIdentifier(inputArg[key])) {
|
|
38
|
+
errors.push(`${key} must be a bounded canonical identifier`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return errors;
|
|
42
|
+
};
|
|
43
|
+
export const validateServiceDeploymentAdoptionInput = (inputArg) => {
|
|
44
|
+
const errors = validateServiceDeploymentAdoptionPreflightInput(inputArg);
|
|
45
|
+
if (!isRecord(inputArg))
|
|
46
|
+
return errors;
|
|
47
|
+
if (!isBoundedIdentifier(inputArg.idempotencyKey)) {
|
|
48
|
+
errors.push('idempotencyKey must be a bounded canonical identifier');
|
|
49
|
+
}
|
|
50
|
+
if (!isCanonicalDigest(inputArg.expectedAdoptionDigest)) {
|
|
51
|
+
errors.push('expectedAdoptionDigest must be a canonical sha256 digest');
|
|
52
|
+
}
|
|
53
|
+
return errors;
|
|
54
|
+
};
|
|
55
|
+
export const validateServiceDeploymentAdoptionReport = (reportArg) => {
|
|
56
|
+
if (!isRecord(reportArg))
|
|
57
|
+
return ['adoption report must be an object'];
|
|
58
|
+
const errors = [];
|
|
59
|
+
if (reportArg.schemaVersion !== 1)
|
|
60
|
+
errors.push('schemaVersion must be 1');
|
|
61
|
+
if (reportArg.mutationPerformed !== false) {
|
|
62
|
+
errors.push('adoption preflight must be mutation-free');
|
|
63
|
+
}
|
|
64
|
+
if (!isBoundedIdentifier(reportArg.requestId)) {
|
|
65
|
+
errors.push('requestId must be a bounded canonical identifier');
|
|
66
|
+
}
|
|
67
|
+
if (!isNonNegativeInteger(reportArg.generatedAt)) {
|
|
68
|
+
errors.push('generatedAt must be a non-negative integer');
|
|
69
|
+
}
|
|
70
|
+
if (reportArg.decision !== 'GO' && reportArg.decision !== 'NO-GO') {
|
|
71
|
+
errors.push('decision must be GO or NO-GO');
|
|
72
|
+
}
|
|
73
|
+
const attestation = reportArg.runtimeAttestation;
|
|
74
|
+
if (!isRecord(attestation)) {
|
|
75
|
+
errors.push('runtimeAttestation must be an object');
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
for (const key of [
|
|
79
|
+
'requiredReplicaCount',
|
|
80
|
+
'observedReplicaCount',
|
|
81
|
+
'healthyReplicaCount',
|
|
82
|
+
'observedDigestReplicaCount',
|
|
83
|
+
]) {
|
|
84
|
+
if (!isNonNegativeInteger(attestation[key])) {
|
|
85
|
+
errors.push(`runtimeAttestation.${key} must be a non-negative integer`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (typeof attestation.observedDigestConsistent !== 'boolean') {
|
|
89
|
+
errors.push('runtimeAttestation.observedDigestConsistent must be boolean');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const blockers = reportArg.blockers;
|
|
93
|
+
if (!Array.isArray(blockers)) {
|
|
94
|
+
errors.push('blockers must be an array');
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
for (const blocker of blockers) {
|
|
98
|
+
if (!isRecord(blocker)
|
|
99
|
+
|| !adoptionBlockerCodes.has(blocker.code)
|
|
100
|
+
|| typeof blocker.message !== 'string'
|
|
101
|
+
|| !blocker.message.trim()) {
|
|
102
|
+
errors.push('each blocker must contain a supported code and non-empty message');
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (reportArg.decision === 'NO-GO') {
|
|
108
|
+
if (Array.isArray(blockers) && blockers.length === 0) {
|
|
109
|
+
errors.push('a NO-GO report must contain at least one blocker');
|
|
110
|
+
}
|
|
111
|
+
if (reportArg.adoptionDigest !== undefined) {
|
|
112
|
+
errors.push('a NO-GO report must not contain an adoption digest');
|
|
113
|
+
}
|
|
114
|
+
return errors;
|
|
115
|
+
}
|
|
116
|
+
if (reportArg.decision !== 'GO')
|
|
117
|
+
return errors;
|
|
118
|
+
if (Array.isArray(blockers) && blockers.length !== 0) {
|
|
119
|
+
errors.push('a GO report must not contain blockers');
|
|
120
|
+
}
|
|
121
|
+
if (!isCanonicalDigest(reportArg.adoptionDigest)) {
|
|
122
|
+
errors.push('a GO report requires a canonical adoption digest');
|
|
123
|
+
}
|
|
124
|
+
const service = reportArg.service;
|
|
125
|
+
const registry = reportArg.registry;
|
|
126
|
+
const targetScope = reportArg.targetScope;
|
|
127
|
+
const runtimeTasks = reportArg.runtimeTasks;
|
|
128
|
+
if (!isRecord(service)) {
|
|
129
|
+
errors.push('a GO report requires a service snapshot');
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
for (const key of ['organizationId', 'serviceId', 'serviceName', 'imageId']) {
|
|
133
|
+
if (!isBoundedIdentifier(service[key]))
|
|
134
|
+
errors.push(`service.${key} is invalid`);
|
|
135
|
+
}
|
|
136
|
+
if (service.deployOnPush !== true || service.immutableImageRequired !== false) {
|
|
137
|
+
errors.push('a GO report requires the legacy mutable service state');
|
|
138
|
+
}
|
|
139
|
+
if (typeof service.configuredReference !== 'string' || !service.configuredReference.trim()) {
|
|
140
|
+
errors.push('service.configuredReference must be non-empty');
|
|
141
|
+
}
|
|
142
|
+
if (!isRecord(service.registryTarget)) {
|
|
143
|
+
errors.push('service.registryTarget must be present');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
let registryDigest;
|
|
147
|
+
if (!isRecord(registry)) {
|
|
148
|
+
errors.push('a GO report requires a registry snapshot');
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
if (!normalizeImmutableReleaseTag(registry.tag) || registry.tag !== registry.releaseTag) {
|
|
152
|
+
errors.push('registry tag and releaseTag must be the same immutable tag');
|
|
153
|
+
}
|
|
154
|
+
if (!isCanonicalDigest(registry.digest)) {
|
|
155
|
+
errors.push('registry.digest must be a canonical sha256 digest');
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
registryDigest = registry.digest;
|
|
159
|
+
if (reportArg.adoptionDigest === registry.digest) {
|
|
160
|
+
errors.push('adoption digest must be a distinct full-state fence, not the image digest');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (!indexMediaTypes.has(registry.mediaType)) {
|
|
164
|
+
errors.push('registry.mediaType must identify an OCI image index');
|
|
165
|
+
}
|
|
166
|
+
if (!isBoundedIdentifier(registry.releaseId)) {
|
|
167
|
+
errors.push('registry.releaseId must be a bounded canonical identifier');
|
|
168
|
+
}
|
|
169
|
+
if (!Array.isArray(registry.platforms) || registry.platforms.length === 0) {
|
|
170
|
+
errors.push('registry.platforms must contain OCI platform evidence');
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
for (const architecture of ['amd64', 'arm64']) {
|
|
174
|
+
if (!registry.platforms.some((platformArg) => isRecord(platformArg)
|
|
175
|
+
&& platformArg.os === 'linux'
|
|
176
|
+
&& platformArg.architecture === architecture
|
|
177
|
+
&& platformArg.runnable === true
|
|
178
|
+
&& platformArg.manifestPresent === true
|
|
179
|
+
&& isCanonicalDigest(platformArg.digest))) {
|
|
180
|
+
errors.push(`registry.platforms must contain runnable linux/${architecture} evidence`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
let requiredReplicaCount;
|
|
186
|
+
let targetNodeNames = [];
|
|
187
|
+
let replicasPerNode;
|
|
188
|
+
if (!isRecord(targetScope)) {
|
|
189
|
+
errors.push('a GO report requires an immutable target scope');
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
const clusterIds = targetScope.targetClusterIds;
|
|
193
|
+
const nodeNames = targetScope.targetNodeNames;
|
|
194
|
+
replicasPerNode = targetScope.replicasPerNode;
|
|
195
|
+
requiredReplicaCount = targetScope.requiredReplicaCount;
|
|
196
|
+
if (!Array.isArray(clusterIds) || clusterIds.length !== 1
|
|
197
|
+
|| clusterIds.some((valueArg) => !isBoundedIdentifier(valueArg))
|
|
198
|
+
|| new Set(clusterIds).size !== clusterIds.length) {
|
|
199
|
+
errors.push('targetScope.targetClusterIds must identify exactly one attested cluster');
|
|
200
|
+
}
|
|
201
|
+
if (!Array.isArray(nodeNames) || nodeNames.length === 0
|
|
202
|
+
|| nodeNames.some((valueArg) => !isBoundedIdentifier(valueArg))
|
|
203
|
+
|| new Set(nodeNames).size !== nodeNames.length) {
|
|
204
|
+
errors.push('targetScope.targetNodeNames must be non-empty and unique');
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
targetNodeNames = nodeNames;
|
|
208
|
+
}
|
|
209
|
+
if (!Number.isSafeInteger(replicasPerNode) || replicasPerNode < 1) {
|
|
210
|
+
errors.push('targetScope.replicasPerNode must be a positive integer');
|
|
211
|
+
}
|
|
212
|
+
if (!Number.isSafeInteger(requiredReplicaCount) || requiredReplicaCount < 1
|
|
213
|
+
|| requiredReplicaCount !== targetNodeNames.length * (replicasPerNode || 0)) {
|
|
214
|
+
errors.push('targetScope.requiredReplicaCount must match nodes times replicas');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (!Array.isArray(runtimeTasks) || runtimeTasks.length === 0) {
|
|
218
|
+
errors.push('a GO report requires runtime task evidence');
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
if (requiredReplicaCount !== undefined && runtimeTasks.length !== requiredReplicaCount) {
|
|
222
|
+
errors.push('runtime task count must equal the required replica count');
|
|
223
|
+
}
|
|
224
|
+
const deploymentIds = new Set();
|
|
225
|
+
const taskCountsByNode = new Map();
|
|
226
|
+
for (const task of runtimeTasks) {
|
|
227
|
+
if (!isRecord(task)
|
|
228
|
+
|| !isBoundedIdentifier(task.deploymentId)
|
|
229
|
+
|| deploymentIds.has(task.deploymentId)) {
|
|
230
|
+
errors.push('runtime task deployment IDs must be valid and unique');
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
deploymentIds.add(task.deploymentId);
|
|
234
|
+
if (!isBoundedIdentifier(task.nodeName) || !targetNodeNames.includes(task.nodeName)) {
|
|
235
|
+
errors.push('every runtime task must belong to the exact target node scope');
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
taskCountsByNode.set(task.nodeName, (taskCountsByNode.get(task.nodeName) || 0) + 1);
|
|
239
|
+
}
|
|
240
|
+
if (task.status !== 'running' || task.healthStatus !== 'healthy') {
|
|
241
|
+
errors.push('every runtime task must be running and healthy');
|
|
242
|
+
}
|
|
243
|
+
if (!registryDigest || task.observedDigest !== registryDigest) {
|
|
244
|
+
errors.push('every runtime task must attest the exact registry digest');
|
|
245
|
+
}
|
|
246
|
+
if (typeof task.imageReference !== 'string' || !task.imageReference.trim()) {
|
|
247
|
+
errors.push('every runtime task must identify its image reference');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (replicasPerNode !== undefined
|
|
251
|
+
&& targetNodeNames.some((nodeNameArg) => taskCountsByNode.get(nodeNameArg) !== replicasPerNode)) {
|
|
252
|
+
errors.push('runtime task evidence must cover every target node and replica');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (isRecord(attestation) && requiredReplicaCount !== undefined) {
|
|
256
|
+
if (attestation.requiredReplicaCount !== requiredReplicaCount
|
|
257
|
+
|| attestation.observedReplicaCount !== requiredReplicaCount
|
|
258
|
+
|| attestation.healthyReplicaCount !== requiredReplicaCount
|
|
259
|
+
|| attestation.observedDigestReplicaCount !== requiredReplicaCount
|
|
260
|
+
|| attestation.observedDigestConsistent !== true) {
|
|
261
|
+
errors.push('runtime attestation must consistently cover every required replica');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (isRecord(service) && isRecord(service.registryTarget) && isRecord(registry)) {
|
|
265
|
+
const target = service.registryTarget;
|
|
266
|
+
if (target.protocol !== 'oci'
|
|
267
|
+
|| target.tag !== registry.tag
|
|
268
|
+
|| target.serviceId !== service.serviceId
|
|
269
|
+
|| target.imageId !== service.imageId
|
|
270
|
+
|| typeof target.registryHost !== 'string'
|
|
271
|
+
|| !target.registryHost
|
|
272
|
+
|| typeof target.repository !== 'string'
|
|
273
|
+
|| !target.repository
|
|
274
|
+
|| target.imageUrl !== `${target.registryHost}/${target.repository}:${target.tag}`) {
|
|
275
|
+
errors.push('service registry target must exactly bind the adopted service, image, and tag');
|
|
276
|
+
}
|
|
277
|
+
if (registryDigest) {
|
|
278
|
+
const digestPinnedReference = `${target.registryHost}/${target.repository}@${registryDigest}`;
|
|
279
|
+
const tagAndDigestReference = `${target.imageUrl}@${registryDigest}`;
|
|
280
|
+
const configuredReferences = new Set([
|
|
281
|
+
target.tag,
|
|
282
|
+
target.imageUrl,
|
|
283
|
+
digestPinnedReference,
|
|
284
|
+
tagAndDigestReference,
|
|
285
|
+
]);
|
|
286
|
+
if (!configuredReferences.has(service.configuredReference)) {
|
|
287
|
+
errors.push('service configured reference must exactly bind the adopted registry target');
|
|
288
|
+
}
|
|
289
|
+
const runtimeReferences = new Set([
|
|
290
|
+
target.imageUrl,
|
|
291
|
+
digestPinnedReference,
|
|
292
|
+
tagAndDigestReference,
|
|
293
|
+
]);
|
|
294
|
+
if (Array.isArray(runtimeTasks)
|
|
295
|
+
&& runtimeTasks.some((taskArg) => !isRecord(taskArg)
|
|
296
|
+
|| !runtimeReferences.has(taskArg.imageReference))) {
|
|
297
|
+
errors.push('every runtime task image reference must exactly bind the adopted registry target');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return errors;
|
|
302
|
+
};
|
|
303
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95bWVudGFkb3B0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9kZXBsb3ltZW50YWRvcHRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBVUEsT0FBTyxFQUFFLDRCQUE0QixFQUFFLHFCQUFxQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUErSDFGLE1BQU0sdUJBQXVCLEdBQUcscUNBQXFDLENBQUM7QUFDdEUsTUFBTSxlQUFlLEdBQUcsSUFBSSxHQUFHLENBQXdCO0lBQ3JELHlDQUF5QztJQUN6QywyREFBMkQ7Q0FDNUQsQ0FBQyxDQUFDO0FBQ0gsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLEdBQUcsQ0FBd0M7SUFDMUUsaUJBQWlCO0lBQ2pCLHVCQUF1QjtJQUN2QixtQkFBbUI7SUFDbkIsNEJBQTRCO0lBQzVCLDJCQUEyQjtJQUMzQix3QkFBd0I7SUFDeEIseUJBQXlCO0lBQ3pCLDRCQUE0QjtJQUM1Qix5QkFBeUI7SUFDekIsb0JBQW9CO0lBQ3BCLHNCQUFzQjtJQUN0QixtQkFBbUI7SUFDbkIsdUJBQXVCO0lBQ3ZCLDBCQUEwQjtJQUMxQixnQ0FBZ0M7SUFDaEMseUJBQXlCO0NBQzFCLENBQUMsQ0FBQztBQUVILE1BQU0sUUFBUSxHQUFHLENBQUMsUUFBaUIsRUFBdUMsRUFBRSxDQUMxRSxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUVoRixNQUFNLG1CQUFtQixHQUFHLENBQUMsUUFBaUIsRUFBc0IsRUFBRSxDQUNwRSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksdUJBQXVCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBRXpFLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxRQUFpQixFQUE2QixFQUFFLENBQ3pFLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLENBQUMs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
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type { IDeploymentPreflightProposedConfiguration, IDeploymentPreflightRuntimeTask } from './deploymentpreflight.js';
|
|
2
|
+
import type { IImageRolloutStatus, IImmutableImageDeploymentPlan, TSha256Digest } from './immutableimage.js';
|
|
3
|
+
import type { IRegistryTarget } from './registry.js';
|
|
4
|
+
import type { TServiceTargetPortRef } from './serviceports.js';
|
|
5
|
+
export type TDeploymentOperationMode = 'existing-service' | 'greenfield';
|
|
6
|
+
export type TDeploymentOperationPhase = 'reserve' | 'promote' | 'route';
|
|
7
|
+
interface IDeploymentReservationInputBase {
|
|
8
|
+
organizationId: string;
|
|
9
|
+
serviceId: string;
|
|
10
|
+
idempotencyKey: string;
|
|
11
|
+
sourceRevision: string;
|
|
12
|
+
version: string;
|
|
13
|
+
intentDigest: TSha256Digest;
|
|
14
|
+
proposedConfiguration: IDeploymentPreflightProposedConfiguration;
|
|
15
|
+
releaseTag: string;
|
|
16
|
+
routes: IDeploymentRouteRequest[];
|
|
17
|
+
}
|
|
18
|
+
export interface IExistingServiceDeploymentReservationInput extends IDeploymentReservationInputBase {
|
|
19
|
+
mode: 'existing-service';
|
|
20
|
+
expectedRolloutGeneration: number;
|
|
21
|
+
expectedCurrentRolloutId?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface IGreenfieldServiceDeploymentReservationInput extends IDeploymentReservationInputBase {
|
|
24
|
+
mode: 'greenfield';
|
|
25
|
+
expectedRolloutGeneration?: never;
|
|
26
|
+
expectedCurrentRolloutId?: never;
|
|
27
|
+
}
|
|
28
|
+
export type IDeploymentReservationInput = IExistingServiceDeploymentReservationInput | IGreenfieldServiceDeploymentReservationInput;
|
|
29
|
+
export type TDeploymentOperationState = 'reserving' | 'reserved' | 'provisioning' | 'awaiting-image' | 'image-recorded' | 'promoting-image' | 'rolling-out' | 'ready-for-route' | 'promoting-route' | 'verifying-route' | 'succeeded' | 'rolling-back' | 'rolled-back' | 'failed' | 'cleaning' | 'cleaned';
|
|
30
|
+
export interface IDeploymentRouteRequest {
|
|
31
|
+
hostname: string;
|
|
32
|
+
targetPort: Extract<TServiceTargetPortRef, number>;
|
|
33
|
+
/** Required exact one-label hostname used to verify a wildcard route. */
|
|
34
|
+
verificationHostname?: string;
|
|
35
|
+
readinessPath?: string;
|
|
36
|
+
expectedStatusCodes?: number[];
|
|
37
|
+
}
|
|
38
|
+
export interface IDeploymentRouteClaimTarget {
|
|
39
|
+
hostname: string;
|
|
40
|
+
bucketHostname: string;
|
|
41
|
+
wildcard: boolean;
|
|
42
|
+
}
|
|
43
|
+
export declare const canonicalizeDeploymentHostname: (hostnameArg: unknown) => string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Wildcards match exactly one label. Exact siblings share a bucket document
|
|
46
|
+
* but may coexist; a wildcard claim excludes every exact name in its bucket.
|
|
47
|
+
*/
|
|
48
|
+
export declare const getDeploymentRouteClaimTarget: (hostnameArg: string) => IDeploymentRouteClaimTarget | undefined;
|
|
49
|
+
export declare const getDeploymentRouteVerificationHostname: (routeArg: IDeploymentRouteRequest) => string | undefined;
|
|
50
|
+
export declare const normalizeDeploymentReadinessPath: (pathArg?: unknown) => string | undefined;
|
|
51
|
+
export declare const validateDeploymentProposedConfiguration: (configurationArg: unknown) => string[];
|
|
52
|
+
export declare const validateDeploymentReservationInput: (inputArg: unknown) => string[];
|
|
53
|
+
interface IDeploymentRouteVerificationEvidenceBase {
|
|
54
|
+
hostname: string;
|
|
55
|
+
url: string;
|
|
56
|
+
checkedAt: number;
|
|
57
|
+
resolvedAddresses: string[];
|
|
58
|
+
rolloutId: string;
|
|
59
|
+
rolloutGeneration: number;
|
|
60
|
+
expectedDigest: TSha256Digest;
|
|
61
|
+
}
|
|
62
|
+
export interface IDeploymentRouteVerificationSuccessEvidence extends IDeploymentRouteVerificationEvidenceBase {
|
|
63
|
+
outcome: 'succeeded';
|
|
64
|
+
tls: {
|
|
65
|
+
authorized: true;
|
|
66
|
+
servername: string;
|
|
67
|
+
subjectAlternativeNames: string[];
|
|
68
|
+
validFrom?: string;
|
|
69
|
+
validTo?: string;
|
|
70
|
+
};
|
|
71
|
+
http: {
|
|
72
|
+
statusCode: number;
|
|
73
|
+
redirected: false;
|
|
74
|
+
};
|
|
75
|
+
readiness: {
|
|
76
|
+
path: string;
|
|
77
|
+
expectedStatusCodes: number[];
|
|
78
|
+
ready: true;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export interface IDeploymentRouteVerificationFailureEvidence extends IDeploymentRouteVerificationEvidenceBase {
|
|
82
|
+
outcome: 'failed';
|
|
83
|
+
stage: 'dns' | 'address-policy' | 'connect' | 'tls' | 'http' | 'readiness';
|
|
84
|
+
code: string;
|
|
85
|
+
message: string;
|
|
86
|
+
tls?: IDeploymentRouteVerificationSuccessEvidence['tls'];
|
|
87
|
+
http?: IDeploymentRouteVerificationSuccessEvidence['http'];
|
|
88
|
+
readiness?: IDeploymentRouteVerificationSuccessEvidence['readiness'];
|
|
89
|
+
}
|
|
90
|
+
export type IDeploymentRouteVerificationEvidence = IDeploymentRouteVerificationSuccessEvidence | IDeploymentRouteVerificationFailureEvidence;
|
|
91
|
+
export interface IDeploymentOperationFailure {
|
|
92
|
+
code: string;
|
|
93
|
+
message: string;
|
|
94
|
+
retryable: boolean;
|
|
95
|
+
failedAt: number;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Durable deployment fence. All state transitions compare-and-set both id and
|
|
99
|
+
* revision. Claim keys are server-generated and never accepted as authority.
|
|
100
|
+
*/
|
|
101
|
+
export interface IServiceDeploymentOperation {
|
|
102
|
+
id: string;
|
|
103
|
+
revision: number;
|
|
104
|
+
data: {
|
|
105
|
+
mode: TDeploymentOperationMode;
|
|
106
|
+
organizationId: string;
|
|
107
|
+
serviceId: string;
|
|
108
|
+
actorUserId: string;
|
|
109
|
+
idempotencyKey: string;
|
|
110
|
+
requestDigest: TSha256Digest;
|
|
111
|
+
sourceRevision: string;
|
|
112
|
+
version: string;
|
|
113
|
+
intentDigest: TSha256Digest;
|
|
114
|
+
configurationDigest: TSha256Digest;
|
|
115
|
+
proposedConfiguration: IDeploymentPreflightProposedConfiguration;
|
|
116
|
+
namespace: string;
|
|
117
|
+
registryTarget: IRegistryTarget;
|
|
118
|
+
releaseTag: string;
|
|
119
|
+
routes: IDeploymentRouteRequest[];
|
|
120
|
+
claimKeys: string[];
|
|
121
|
+
state: TDeploymentOperationState;
|
|
122
|
+
releaseId?: string;
|
|
123
|
+
registryRootDigest?: TSha256Digest;
|
|
124
|
+
rolloutId?: string;
|
|
125
|
+
rolloutGeneration?: number;
|
|
126
|
+
routeGeneration?: number;
|
|
127
|
+
routeVerification?: IDeploymentRouteVerificationEvidence[];
|
|
128
|
+
failure?: IDeploymentOperationFailure;
|
|
129
|
+
createdAt: number;
|
|
130
|
+
updatedAt: number;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
export interface IServiceDeploymentStatus {
|
|
134
|
+
operation: IServiceDeploymentOperation;
|
|
135
|
+
imageDeployment?: IImmutableImageDeploymentPlan;
|
|
136
|
+
imageRolloutStatus?: IImageRolloutStatus;
|
|
137
|
+
runtimeTasks: IDeploymentRuntimeTaskEvidence[];
|
|
138
|
+
routeVerification: IDeploymentRouteVerificationEvidence[];
|
|
139
|
+
immutableRolloutSucceeded: boolean;
|
|
140
|
+
runtimeDigestVerified: boolean;
|
|
141
|
+
routeVerified: boolean;
|
|
142
|
+
succeeded: boolean;
|
|
143
|
+
}
|
|
144
|
+
interface IDeploymentRuntimeTaskEvidenceBase extends Omit<IDeploymentPreflightRuntimeTask, 'verificationStatus' | 'observedDigest' | 'reportedDigest'> {
|
|
145
|
+
rolloutId: string;
|
|
146
|
+
rolloutGeneration: number;
|
|
147
|
+
expectedDigest: TSha256Digest;
|
|
148
|
+
observedAt: number;
|
|
149
|
+
}
|
|
150
|
+
export interface IVerifiedDeploymentRuntimeTaskEvidence extends IDeploymentRuntimeTaskEvidenceBase {
|
|
151
|
+
verificationStatus: 'verified';
|
|
152
|
+
observedDigest: TSha256Digest;
|
|
153
|
+
reportedDigest: TSha256Digest;
|
|
154
|
+
}
|
|
155
|
+
export interface IUnverifiedDeploymentRuntimeTaskEvidence extends IDeploymentRuntimeTaskEvidenceBase {
|
|
156
|
+
verificationStatus: 'missing' | 'mismatched';
|
|
157
|
+
observedDigest?: TSha256Digest;
|
|
158
|
+
reportedDigest?: TSha256Digest;
|
|
159
|
+
}
|
|
160
|
+
export type IDeploymentRuntimeTaskEvidence = IVerifiedDeploymentRuntimeTaskEvidence | IUnverifiedDeploymentRuntimeTaskEvidence;
|
|
161
|
+
export {};
|