@serve.zone/interfaces 13.0.1 → 15.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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-07-20 - 15.0.0
4
+
5
+ ### Breaking Changes
6
+
7
+ - add scoped immutable deployment operation contracts (deployment)
8
+ - Replace machine deployment grant fields with an exact organization/service or organization/service-slot grant and use JWT-only credentials on scoped deployment RPCs.
9
+ - Add revisioned reserve, status, route promotion, retry, and cleanup contracts with complete configuration, rollout, wildcard-route, readiness, and TLS evidence validation.
10
+ - Require authenticated registry evidence bound to the operation, actor, service, image, registry host, repository, exact tag, root digest, and OCI index media type.
11
+ - 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.
12
+
13
+ ## 2026-07-19 - 14.0.0
14
+
15
+ ### Breaking Changes
16
+
17
+ - distinguish read-only observed runtime digests from verified immutable rollout digests (deployment)
18
+ - Report explicit observed-digest replica counts without promoting mutable workloads to verified status.
19
+
3
20
  ## 2026-07-19 - 13.0.1
4
21
 
5
22
  ### Fixes
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '13.0.1',
6
+ version: '15.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,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 {};
@@ -0,0 +1,213 @@
1
+ import { normalizeImmutableReleaseTag, normalizeSha256Digest } from './immutableimage.js';
2
+ const canonicalHostnameRegex = /^(?:\*\.)?[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/;
3
+ export const canonicalizeDeploymentHostname = (hostnameArg) => {
4
+ if (typeof hostnameArg !== 'string')
5
+ return undefined;
6
+ const hostname = hostnameArg.trim().toLowerCase().replace(/\.$/, '');
7
+ return hostname.length <= 253 && canonicalHostnameRegex.test(hostname)
8
+ ? hostname
9
+ : undefined;
10
+ };
11
+ /**
12
+ * Wildcards match exactly one label. Exact siblings share a bucket document
13
+ * but may coexist; a wildcard claim excludes every exact name in its bucket.
14
+ */
15
+ export const getDeploymentRouteClaimTarget = (hostnameArg) => {
16
+ const hostname = canonicalizeDeploymentHostname(hostnameArg);
17
+ if (!hostname)
18
+ return undefined;
19
+ const wildcard = hostname.startsWith('*.');
20
+ const labels = (wildcard ? hostname.slice(2) : hostname).split('.');
21
+ const bucketHostname = wildcard ? labels.join('.') : labels.slice(1).join('.');
22
+ if (!bucketHostname || (wildcard && labels.length < 2))
23
+ return undefined;
24
+ return { hostname, bucketHostname, wildcard };
25
+ };
26
+ export const getDeploymentRouteVerificationHostname = (routeArg) => {
27
+ const target = getDeploymentRouteClaimTarget(routeArg.hostname);
28
+ if (!target)
29
+ return undefined;
30
+ if (!target.wildcard) {
31
+ return routeArg.verificationHostname === undefined
32
+ || routeArg.verificationHostname === target.hostname
33
+ ? target.hostname
34
+ : undefined;
35
+ }
36
+ if (!routeArg.verificationHostname)
37
+ return undefined;
38
+ const verificationTarget = getDeploymentRouteClaimTarget(routeArg.verificationHostname);
39
+ return verificationTarget
40
+ && !verificationTarget.wildcard
41
+ && verificationTarget.bucketHostname === target.bucketHostname
42
+ ? verificationTarget.hostname
43
+ : undefined;
44
+ };
45
+ export const normalizeDeploymentReadinessPath = (pathArg) => {
46
+ if (pathArg !== undefined && typeof pathArg !== 'string')
47
+ return undefined;
48
+ const path = pathArg || '/';
49
+ return /^\/(?!\/)[A-Za-z0-9._~!$&'()*+,;=:@%\/-]{0,1023}$/.test(path)
50
+ ? path
51
+ : undefined;
52
+ };
53
+ const deploymentIdentifierRegex = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,199}$/;
54
+ const fullGitRevisionRegex = /^[a-f0-9]{40}$/;
55
+ const semanticVersionRegex = /^(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)(?:-(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
56
+ const isRecord = (valueArg) => (Boolean(valueArg) && typeof valueArg === 'object' && !Array.isArray(valueArg));
57
+ const validateStringArray = (valueArg, maxItemsArg, validatorArg) => Array.isArray(valueArg)
58
+ && valueArg.length <= maxItemsArg
59
+ && valueArg.every((itemArg) => typeof itemArg === 'string'
60
+ && itemArg.length > 0
61
+ && itemArg.length <= 253
62
+ && validatorArg(itemArg))
63
+ && new Set(valueArg).size === valueArg.length;
64
+ export const validateDeploymentProposedConfiguration = (configurationArg) => {
65
+ if (!isRecord(configurationArg))
66
+ return ['proposedConfiguration must be an object'];
67
+ const errors = [];
68
+ if (configurationArg.schemaVersion !== 1)
69
+ errors.push('schemaVersion must be 1');
70
+ if (typeof configurationArg.declarationComplete !== 'boolean') {
71
+ errors.push('declarationComplete must be boolean');
72
+ }
73
+ if (typeof configurationArg.projectName !== 'string'
74
+ || !configurationArg.projectName.trim()
75
+ || configurationArg.projectName.length > 200) {
76
+ errors.push('projectName must be bounded and non-empty');
77
+ }
78
+ if (!validateStringArray(configurationArg.targetPlatforms, 8, (platformArg) => (/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/.test(platformArg)))) {
79
+ errors.push('targetPlatforms must be unique canonical platform identifiers');
80
+ }
81
+ if (!validateStringArray(configurationArg.publicDomains, 32, (domainArg) => (canonicalizeDeploymentHostname(domainArg) === domainArg))) {
82
+ errors.push('publicDomains must be unique canonical exact or wildcard hostnames');
83
+ }
84
+ if (!validateStringArray(configurationArg.environmentVariableNames, 256, (nameArg) => (nameArg.length <= 253 && /^[A-Z_][A-Z0-9_]*$/.test(nameArg)))) {
85
+ errors.push('environmentVariableNames must be unique canonical names');
86
+ }
87
+ if (!validateStringArray(configurationArg.secretReferenceIds, 64, (idArg) => (idArg.length <= 253 && /^[A-Za-z0-9][A-Za-z0-9:._-]*$/.test(idArg)))) {
88
+ errors.push('secretReferenceIds must be unique canonical identifiers');
89
+ }
90
+ if (!Array.isArray(configurationArg.containerPorts)
91
+ || configurationArg.containerPorts.length > 64
92
+ || configurationArg.containerPorts.some((portArg) => !Number.isSafeInteger(portArg)
93
+ || portArg < 1 || portArg > 65535)
94
+ || new Set(configurationArg.containerPorts).size !== configurationArg.containerPorts.length) {
95
+ errors.push('containerPorts must be unique valid ports');
96
+ }
97
+ if (!Array.isArray(configurationArg.volumeMounts)
98
+ || configurationArg.volumeMounts.length > 32
99
+ || configurationArg.volumeMounts.some((mountArg) => !isRecord(mountArg)
100
+ || typeof mountArg.mountPath !== 'string'
101
+ || !/^\/[A-Za-z0-9._/-]{0,254}$/.test(mountArg.mountPath)
102
+ || (mountArg.storageClass !== 'corestore' && mountArg.storageClass !== 'ephemeral')
103
+ || (mountArg.capability !== undefined
104
+ && mountArg.capability !== 'database'
105
+ && mountArg.capability !== 'objectstorage'))) {
106
+ errors.push('volumeMounts must be canonical supported declarations');
107
+ }
108
+ if (!Array.isArray(configurationArg.requiredCapabilities)
109
+ || configurationArg.requiredCapabilities.length > 2
110
+ || configurationArg.requiredCapabilities.some((capabilityArg) => (capabilityArg !== 'database' && capabilityArg !== 'objectstorage'))
111
+ || new Set(configurationArg.requiredCapabilities).size
112
+ !== configurationArg.requiredCapabilities.length) {
113
+ errors.push('requiredCapabilities must be a unique supported capability set');
114
+ }
115
+ return errors;
116
+ };
117
+ export const validateDeploymentReservationInput = (inputArg) => {
118
+ if (!isRecord(inputArg))
119
+ return ['reservation input must be an object'];
120
+ const errors = [];
121
+ if (inputArg.mode !== 'existing-service' && inputArg.mode !== 'greenfield') {
122
+ errors.push('mode must identify an existing-service or greenfield deployment');
123
+ }
124
+ for (const field of ['organizationId', 'serviceId', 'idempotencyKey']) {
125
+ if (typeof inputArg[field] !== 'string'
126
+ || !deploymentIdentifierRegex.test(inputArg[field])) {
127
+ errors.push(`${field} must be a bounded canonical identifier`);
128
+ }
129
+ }
130
+ if (typeof inputArg.sourceRevision !== 'string'
131
+ || !fullGitRevisionRegex.test(inputArg.sourceRevision)) {
132
+ errors.push('sourceRevision must be a full lowercase git revision');
133
+ }
134
+ if (typeof inputArg.version !== 'string' || !semanticVersionRegex.test(inputArg.version)) {
135
+ errors.push('version must be a canonical semantic version');
136
+ }
137
+ if (!normalizeSha256Digest(inputArg.intentDigest)) {
138
+ errors.push('intentDigest must be a canonical sha256 digest');
139
+ }
140
+ if (!normalizeImmutableReleaseTag(inputArg.releaseTag)) {
141
+ errors.push('releaseTag must be a canonical non-latest OCI tag');
142
+ }
143
+ const configuration = isRecord(inputArg.proposedConfiguration)
144
+ ? inputArg.proposedConfiguration
145
+ : undefined;
146
+ errors.push(...validateDeploymentProposedConfiguration(inputArg.proposedConfiguration));
147
+ const containerPorts = configuration && Array.isArray(configuration.containerPorts)
148
+ ? configuration.containerPorts
149
+ : undefined;
150
+ const publicDomains = configuration && Array.isArray(configuration.publicDomains)
151
+ ? configuration.publicDomains.filter((domainArg) => (typeof domainArg === 'string'))
152
+ : undefined;
153
+ if (configuration?.declarationComplete !== true) {
154
+ errors.push('proposedConfiguration must declare itself complete');
155
+ }
156
+ const routes = Array.isArray(inputArg.routes) ? inputArg.routes : undefined;
157
+ const routeHostnames = routes?.map((routeArg) => (isRecord(routeArg) && typeof routeArg.hostname === 'string' ? routeArg.hostname : undefined));
158
+ if (!routes
159
+ || routes.length > 32
160
+ || !routeHostnames
161
+ || new Set(routeHostnames).size !== routeHostnames.length
162
+ || routes.some((routeArg) => {
163
+ if (!isRecord(routeArg)
164
+ || typeof routeArg.hostname !== 'string'
165
+ || canonicalizeDeploymentHostname(routeArg.hostname) !== routeArg.hostname
166
+ || !Number.isSafeInteger(routeArg.targetPort)
167
+ || routeArg.targetPort < 1
168
+ || routeArg.targetPort > 65535
169
+ || !containerPorts?.includes(routeArg.targetPort)) {
170
+ return true;
171
+ }
172
+ const typedRoute = routeArg;
173
+ return getDeploymentRouteVerificationHostname(typedRoute) === undefined
174
+ || (routeArg.readinessPath !== undefined
175
+ && (typeof routeArg.readinessPath !== 'string'
176
+ || normalizeDeploymentReadinessPath(routeArg.readinessPath) !== routeArg.readinessPath))
177
+ || (routeArg.expectedStatusCodes !== undefined
178
+ && (!Array.isArray(routeArg.expectedStatusCodes)
179
+ || routeArg.expectedStatusCodes.length < 1
180
+ || routeArg.expectedStatusCodes.length > 16
181
+ || new Set(routeArg.expectedStatusCodes).size !== routeArg.expectedStatusCodes.length
182
+ || routeArg.expectedStatusCodes.some((statusArg) => !Number.isSafeInteger(statusArg)
183
+ || statusArg < 200 || statusArg > 299)));
184
+ })) {
185
+ errors.push('routes must be unique canonical declarations over declared numeric ports');
186
+ }
187
+ if (inputArg.mode === 'greenfield') {
188
+ if (inputArg.expectedRolloutGeneration !== undefined
189
+ || inputArg.expectedCurrentRolloutId !== undefined) {
190
+ errors.push('greenfield reservation must not carry an existing rollout fence');
191
+ }
192
+ if (publicDomains && routeHostnames) {
193
+ const declared = [...new Set(publicDomains)].sort();
194
+ const routed = [...new Set(routeHostnames.filter((valueArg) => (typeof valueArg === 'string')))].sort();
195
+ if (JSON.stringify(declared) !== JSON.stringify(routed)) {
196
+ errors.push('greenfield routes must exactly match proposed publicDomains');
197
+ }
198
+ }
199
+ }
200
+ if (inputArg.mode === 'existing-service') {
201
+ if (!Number.isSafeInteger(inputArg.expectedRolloutGeneration)
202
+ || inputArg.expectedRolloutGeneration < 0) {
203
+ errors.push('existing-service reservation requires an explicit rollout generation fence');
204
+ }
205
+ if (inputArg.expectedCurrentRolloutId !== undefined
206
+ && (typeof inputArg.expectedCurrentRolloutId !== 'string'
207
+ || !deploymentIdentifierRegex.test(inputArg.expectedCurrentRolloutId))) {
208
+ errors.push('expectedCurrentRolloutId must be a bounded canonical identifier');
209
+ }
210
+ }
211
+ return errors;
212
+ };
213
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95bWVudG9wZXJhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2RhdGEvZGVwbG95bWVudG9wZXJhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsNEJBQTRCLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQXNFMUYsTUFBTSxzQkFBc0IsR0FBRyw0RkFBNEYsQ0FBQztBQUU1SCxNQUFNLENBQUMsTUFBTSw4QkFBOEIsR0FBRyxDQUFDLFdBQW9CLEVBQXNCLEVBQUU7SUFDekYsSUFBSSxPQUFPLFdBQVcsS0FBSyxRQUFRO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDdEQsTUFBTSxRQUFRLEdBQUcsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckUsT0FBTyxRQUFRLENBQUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ3BFLENBQUMsQ0FBQyxRQUFRO1FBQ1YsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUNoQixDQUFDLENBQUM7QUFFRjs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSw2QkFBNkIsR0FBRyxDQUMzQyxXQUFtQixFQUNzQixFQUFFO0lBQzNDLE1BQU0sUUFBUSxHQUFHLDhCQUE4QixDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzdELElBQUksQ0FBQyxRQUFRO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDaEMsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQyxNQUFNLE1BQU0sR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FB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
@@ -1,7 +1,8 @@
1
1
  import type { TOciManifestMediaType, TSha256Digest } from './immutableimage.js';
2
2
  import type { TServiceDeploymentCapability } from './user.js';
3
+ import type { IDeploymentRouteRequest, IServiceDeploymentOperation, TDeploymentOperationMode, TDeploymentOperationPhase } from './deploymentoperation.js';
3
4
  export type TDeploymentPreflightDecision = 'GO' | 'NO-GO';
4
- export type TDeploymentPreflightBlockerCode = 'INVALID_REQUEST' | 'AUTHORIZATION_MISSING' | 'SOURCE_REVISION_INVALID' | 'SOURCE_WORKTREE_DIRTY' | 'VERSION_NOT_RESERVED' | 'VERSION_COLLISION' | 'NAMESPACE_NOT_RESERVED' | 'NAMESPACE_COLLISION' | 'NAMESPACE_NOT_PROVEN_BLANK' | 'CONFIGURATION_DIGEST_INVALID' | 'INTENT_DIGEST_INVALID' | 'PROPOSED_CONFIGURATION_INCOMPLETE' | 'CURRENT_REFERENCE_MUTABLE' | 'CURRENT_RUNTIME_DIGEST_MISSING' | 'OCI_INDEX_DIGEST_REQUIRED' | 'OCI_INDEX_NOT_FOUND' | 'OCI_INDEX_MEDIA_TYPE_REQUIRED' | 'OCI_PLATFORM_MISSING' | 'OCI_PLATFORM_MANIFEST_MISSING' | 'IMMUTABLE_RELEASE_TAG_REQUIRED' | 'IMMUTABLE_RELEASE_TAG_NOT_RESERVED' | 'RELEASE_EVIDENCE_MISSING' | 'RELEASE_EVIDENCE_INVALID' | 'RELEASE_NOT_AUTHORIZED' | 'GREENFIELD_EXECUTION_UNAVAILABLE' | 'ROUTE_PROMOTION_FENCE_UNAVAILABLE' | 'POST_DEPLOYMENT_VERIFICATION_UNAVAILABLE' | 'WOULD_REPLACE_EXISTING_STATE' | 'CORESTORE_INVENTORY_UNAVAILABLE' | 'RUNTIME_ATTESTATION_MISMATCH';
5
+ export type TDeploymentPreflightBlockerCode = 'INVALID_REQUEST' | 'AUTHORIZATION_MISSING' | 'ORGANIZATION_SCOPE_MISSING' | 'SERVICE_OWNERSHIP_MISMATCH' | 'DEPLOYMENT_OPERATION_NOT_FOUND' | 'DEPLOYMENT_OPERATION_CONFLICT' | 'DEPLOY_ON_PUSH_MUST_BE_DISABLED' | 'REGISTRY_AUTHENTICATION_UNAVAILABLE' | 'REGISTRY_REPOSITORY_MISMATCH' | 'REGISTRY_TAG_CONFLICT' | 'SOURCE_REVISION_INVALID' | 'SOURCE_WORKTREE_DIRTY' | 'VERSION_NOT_RESERVED' | 'VERSION_COLLISION' | 'NAMESPACE_NOT_RESERVED' | 'NAMESPACE_COLLISION' | 'NAMESPACE_NOT_PROVEN_BLANK' | 'CONFIGURATION_DIGEST_INVALID' | 'INTENT_DIGEST_INVALID' | 'PROPOSED_CONFIGURATION_INCOMPLETE' | 'CURRENT_REFERENCE_MUTABLE' | 'CURRENT_RUNTIME_DIGEST_MISSING' | 'OCI_INDEX_DIGEST_REQUIRED' | 'OCI_INDEX_NOT_FOUND' | 'OCI_INDEX_MEDIA_TYPE_REQUIRED' | 'OCI_PLATFORM_MISSING' | 'OCI_PLATFORM_MANIFEST_MISSING' | 'IMMUTABLE_RELEASE_TAG_REQUIRED' | 'IMMUTABLE_RELEASE_TAG_NOT_RESERVED' | 'RELEASE_EVIDENCE_MISSING' | 'RELEASE_EVIDENCE_INVALID' | 'RELEASE_EVIDENCE_AMBIGUOUS' | 'RELEASE_NOT_AUTHORIZED' | 'GREENFIELD_EXECUTION_UNAVAILABLE' | 'ROUTE_PROMOTION_FENCE_UNAVAILABLE' | 'POST_DEPLOYMENT_VERIFICATION_UNAVAILABLE' | 'WOULD_REPLACE_EXISTING_STATE' | 'CORESTORE_INVENTORY_UNAVAILABLE' | 'RUNTIME_ATTESTATION_MISMATCH' | 'ROLLOUT_ACTIVE_CONFLICT' | 'ROLLOUT_NOT_SUCCEEDED' | 'ROUTE_UNAVAILABLE' | 'ROUTE_VERIFICATION_FAILED' | 'TLS_VERIFICATION_FAILED';
5
6
  export interface IDeploymentPreflightBlocker {
6
7
  code: TDeploymentPreflightBlockerCode;
7
8
  message: string;
@@ -24,6 +25,7 @@ export interface IDeploymentPreflightRuntimeTask {
24
25
  status: string;
25
26
  healthStatus?: string;
26
27
  imageReference?: string;
28
+ observedDigest?: TSha256Digest;
27
29
  reportedDigest?: TSha256Digest;
28
30
  verificationStatus?: 'not-required' | 'pending' | 'verified' | 'missing' | 'mismatched';
29
31
  }
@@ -82,6 +84,10 @@ export interface IDeploymentReleaseEvidence {
82
84
  export interface IDeploymentPreflightRequestData {
83
85
  requestId: string;
84
86
  serviceId: string;
87
+ organizationId?: string;
88
+ mode?: TDeploymentOperationMode;
89
+ phase?: TDeploymentOperationPhase;
90
+ operationId?: string;
85
91
  sourceRevision: string;
86
92
  sourceDirty: boolean;
87
93
  version: string;
@@ -90,7 +96,9 @@ export interface IDeploymentPreflightRequestData {
90
96
  ociIndexDigest?: string;
91
97
  releaseTag?: string;
92
98
  releaseEvidence?: IDeploymentReleaseEvidence;
93
- greenfield: true;
99
+ routes?: IDeploymentRouteRequest[];
100
+ /** Legacy v14 discriminator. Equivalent to mode: 'greenfield'. */
101
+ greenfield?: true;
94
102
  }
95
103
  export interface IDeploymentPreflightReport {
96
104
  schemaVersion: 2;
@@ -98,6 +106,7 @@ export interface IDeploymentPreflightReport {
98
106
  mutationPerformed: false;
99
107
  generatedAt: number;
100
108
  service: {
109
+ organizationId?: string;
101
110
  serviceId: string;
102
111
  serviceName: string;
103
112
  workspaceIdentity: string;
@@ -105,6 +114,9 @@ export interface IDeploymentPreflightReport {
105
114
  registryRepository: string;
106
115
  deployOnPush: boolean;
107
116
  };
117
+ mode?: TDeploymentOperationMode;
118
+ phase?: TDeploymentOperationPhase;
119
+ operation?: IServiceDeploymentOperation;
108
120
  source: {
109
121
  revision: string;
110
122
  dirty: boolean;
@@ -133,6 +145,8 @@ export interface IDeploymentPreflightReport {
133
145
  observedReplicaCount: number;
134
146
  healthyReplicaCount: number;
135
147
  verifiedReplicaCount: number;
148
+ observedDigestReplicaCount: number;
149
+ observedDigestConsistent: boolean;
136
150
  consistentDigest: boolean;
137
151
  };
138
152
  platformBindings: IDeploymentPreflightPlatformBinding[];
@@ -158,20 +172,8 @@ export interface IGreenfieldDeploymentFence {
158
172
  configurationDigest: TSha256Digest;
159
173
  targetNamespace: string;
160
174
  }
161
- export interface IGreenfieldDeploymentOperation {
162
- id: string;
163
- data: {
164
- idempotencyKey: string;
165
- requestDigest: TSha256Digest;
166
- fence: IGreenfieldDeploymentFence;
167
- candidateServiceId?: string;
168
- state: 'reserved' | 'provisioning' | 'deploying' | 'verifying' | 'ready-for-promotion' | 'promoting' | 'promoted' | 'rolling-back' | 'rolled-back' | 'failed';
169
- routeGeneration?: number;
170
- createdAt: number;
171
- updatedAt: number;
172
- failureCode?: string;
173
- };
174
- }
175
+ /** @deprecated Use IServiceDeploymentOperation. */
176
+ export type IGreenfieldDeploymentOperation = IServiceDeploymentOperation;
175
177
  export declare const validateDeploymentPreflightRequest: (requestArg: unknown) => IDeploymentPreflightBlocker[];
176
178
  export declare const validateDeploymentReleaseEvidence: (argsArg: {
177
179
  evidence: unknown;