@contractspec/lib.progressive-delivery 34.0.5 → 34.0.7

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/README.md CHANGED
@@ -1,32 +1,61 @@
1
1
  # @contractspec/lib.progressive-delivery
2
2
 
3
- Progressive delivery primitives for ContractSpec apps. Manage canary and blue-green deployments with guardrails, integration hooks, and automatic rollback.
3
+ **Progressive delivery and canary release primitives. Provides strategy definitions and rollout logic for safe, incremental deployments.**
4
4
 
5
- ## Features
5
+ ## What It Provides
6
6
 
7
- - Declarative deployment strategies (canary, blue-green, hybrid)
8
- - Stage-based traffic shifting with configurable durations
9
- - Metric-driven guardrails (error rate, latency percentiles, throughput)
10
- - Automatic rollback with structured events
11
- - Event hooks for logging, auditing, and UI updates
12
- - Works with `@contractspec/lib.observability` and feature flag pipelines
7
+ - **Layer**: lib.
8
+ - **Consumers**: bundles.
9
+ - Related ContractSpec packages include `@contractspec/lib.observability`, `@contractspec/tool.bun`, `@contractspec/tool.typescript`.
10
+ - Related ContractSpec packages include `@contractspec/lib.observability`, `@contractspec/tool.bun`, `@contractspec/tool.typescript`.
13
11
 
14
- ## Quick Start
12
+ ## Installation
15
13
 
16
- ```ts
17
- import {
18
- DeploymentCoordinator,
19
- createDefaultCanaryController,
20
- } from '@contractspec/lib.progressive-delivery';
14
+ `npm install @contractspec/lib.progressive-delivery`
21
15
 
22
- const coordinator = new DeploymentCoordinator({
23
- strategy,
24
- controller: createDefaultCanaryController(strategy),
25
- metricsProvider: fetchMetricsFromOtEL,
26
- rollbackManager,
27
- });
16
+ or
28
17
 
29
- await coordinator.run();
30
- ```
18
+ `bun add @contractspec/lib.progressive-delivery`
31
19
 
32
- See the docs in `docs/tech/PHASE_5_ZERO_TOUCH_OPERATIONS.md` for full workflows.
20
+ ## Usage
21
+
22
+ Import the root entrypoint from `@contractspec/lib.progressive-delivery`, or choose a documented subpath when you only need one part of the package surface.
23
+
24
+ ## Architecture
25
+
26
+ - `src/canary-analyzer.ts` is part of the package's public or composition surface.
27
+ - `src/canary-controller.ts` is part of the package's public or composition surface.
28
+ - `src/deployment-coordinator.ts` is part of the package's public or composition surface.
29
+ - `src/events.ts` is package-level event definitions.
30
+ - `src/feature-flags.ts` is part of the package's public or composition surface.
31
+ - `src/index.ts` is the root public barrel and package entrypoint.
32
+ - `src/rollback-manager.ts` is part of the package's public or composition surface.
33
+
34
+ ## Public Entry Points
35
+
36
+ - Export `.` resolves through `./src/index.ts`.
37
+
38
+ ## Local Commands
39
+
40
+ - `bun run dev` — contractspec-bun-build dev
41
+ - `bun run build` — bun run prebuild && bun run build:bundle && bun run build:types
42
+ - `bun run lint` — bun lint:fix
43
+ - `bun run lint:check` — biome check .
44
+ - `bun run lint:fix` — biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .
45
+ - `bun run typecheck` — tsc --noEmit
46
+ - `bun run publish:pkg` — bun publish --tolerate-republish --ignore-scripts --verbose
47
+ - `bun run publish:pkg:canary` — bun publish:pkg --tag canary
48
+ - `bun run clean` — rimraf dist .turbo
49
+ - `bun run build:bundle` — contractspec-bun-build transpile
50
+ - `bun run build:types` — contractspec-bun-build types
51
+ - `bun run prebuild` — contractspec-bun-build prebuild
52
+
53
+ ## Recent Updates
54
+
55
+ - Replace eslint+prettier by biomejs to optimize speed.
56
+
57
+ ## Notes
58
+
59
+ - Delivery strategies must be deterministic — same input must produce same rollout decision.
60
+ - Peer dependency on observability; ensure OTel integration stays aligned.
61
+ - Strategy interface changes affect all deployment pipelines consuming this lib.
@@ -1,37 +1,3 @@
1
- // src/events.ts
2
- class DeploymentEventBus {
3
- listeners = new Set;
4
- on(listener) {
5
- this.listeners.add(listener);
6
- return () => this.listeners.delete(listener);
7
- }
8
- emit(event) {
9
- for (const listener of this.listeners) {
10
- try {
11
- listener(event);
12
- } catch (error) {
13
- console.error("[progressive-delivery] listener error", error);
14
- }
15
- }
16
- }
17
- }
18
- // src/traffic-shifter.ts
19
- class TrafficShifter {
20
- mode;
21
- constructor(mode) {
22
- this.mode = mode;
23
- }
24
- computeSplit(stage) {
25
- if (this.mode === "blue-green") {
26
- return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
27
- }
28
- const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
29
- return {
30
- candidate,
31
- stable: 1 - candidate
32
- };
33
- }
34
- }
35
1
  // src/canary-analyzer.ts
36
2
  class CanaryAnalyzer {
37
3
  defaults;
@@ -109,23 +75,6 @@ function createDefaultCanaryController(strategy, metricsProvider, eventBus) {
109
75
  eventBus
110
76
  });
111
77
  }
112
- // src/rollback-manager.ts
113
- class RollbackManager {
114
- options;
115
- constructor(options) {
116
- this.options = options;
117
- }
118
- async execute(stage, reason) {
119
- await this.options.rollback(stage, reason);
120
- const action = {
121
- reason,
122
- stage,
123
- triggeredAt: new Date
124
- };
125
- this.options.onRollback?.(action);
126
- return action;
127
- }
128
- }
129
78
  // src/deployment-coordinator.ts
130
79
  class DeploymentCoordinator {
131
80
  options;
@@ -167,6 +116,23 @@ class DeploymentCoordinator {
167
116
  return { status: "completed" };
168
117
  }
169
118
  }
119
+ // src/events.ts
120
+ class DeploymentEventBus {
121
+ listeners = new Set;
122
+ on(listener) {
123
+ this.listeners.add(listener);
124
+ return () => this.listeners.delete(listener);
125
+ }
126
+ emit(event) {
127
+ for (const listener of this.listeners) {
128
+ try {
129
+ listener(event);
130
+ } catch (error) {
131
+ console.error("[progressive-delivery] listener error", error);
132
+ }
133
+ }
134
+ }
135
+ }
170
136
  // src/feature-flags.ts
171
137
  var ContractSpecFeatureFlags = {
172
138
  LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha",
@@ -194,6 +160,40 @@ var studioFlags = [
194
160
  ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,
195
161
  ContractSpecFeatureFlags.STUDIO_TEMPLATES
196
162
  ];
163
+ // src/rollback-manager.ts
164
+ class RollbackManager {
165
+ options;
166
+ constructor(options) {
167
+ this.options = options;
168
+ }
169
+ async execute(stage, reason) {
170
+ await this.options.rollback(stage, reason);
171
+ const action = {
172
+ reason,
173
+ stage,
174
+ triggeredAt: new Date
175
+ };
176
+ this.options.onRollback?.(action);
177
+ return action;
178
+ }
179
+ }
180
+ // src/traffic-shifter.ts
181
+ class TrafficShifter {
182
+ mode;
183
+ constructor(mode) {
184
+ this.mode = mode;
185
+ }
186
+ computeSplit(stage) {
187
+ if (this.mode === "blue-green") {
188
+ return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
189
+ }
190
+ const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
191
+ return {
192
+ candidate,
193
+ stable: 1 - candidate
194
+ };
195
+ }
196
+ }
197
197
  export {
198
198
  studioFlags,
199
199
  lifecycleFlags,
@@ -1,4 +1,4 @@
1
- import { CanaryAnalyzer, type AnalysisResult } from './canary-analyzer';
1
+ import { type AnalysisResult, CanaryAnalyzer } from './canary-analyzer';
2
2
  import { DeploymentEventBus } from './events';
3
3
  import type { CanaryStage, DeploymentStrategy, MetricsProvider } from './types';
4
4
  export interface CanaryControllerOptions {
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- export * from './types';
2
- export * from './events';
3
- export * from './traffic-shifter';
4
1
  export * from './canary-analyzer';
5
2
  export * from './canary-controller';
6
- export * from './rollback-manager';
7
3
  export * from './deployment-coordinator';
4
+ export * from './events';
8
5
  export * from './feature-flags';
6
+ export * from './rollback-manager';
7
+ export * from './traffic-shifter';
8
+ export * from './types';
package/dist/index.js CHANGED
@@ -1,38 +1,4 @@
1
1
  // @bun
2
- // src/events.ts
3
- class DeploymentEventBus {
4
- listeners = new Set;
5
- on(listener) {
6
- this.listeners.add(listener);
7
- return () => this.listeners.delete(listener);
8
- }
9
- emit(event) {
10
- for (const listener of this.listeners) {
11
- try {
12
- listener(event);
13
- } catch (error) {
14
- console.error("[progressive-delivery] listener error", error);
15
- }
16
- }
17
- }
18
- }
19
- // src/traffic-shifter.ts
20
- class TrafficShifter {
21
- mode;
22
- constructor(mode) {
23
- this.mode = mode;
24
- }
25
- computeSplit(stage) {
26
- if (this.mode === "blue-green") {
27
- return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
28
- }
29
- const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
30
- return {
31
- candidate,
32
- stable: 1 - candidate
33
- };
34
- }
35
- }
36
2
  // src/canary-analyzer.ts
37
3
  class CanaryAnalyzer {
38
4
  defaults;
@@ -110,23 +76,6 @@ function createDefaultCanaryController(strategy, metricsProvider, eventBus) {
110
76
  eventBus
111
77
  });
112
78
  }
113
- // src/rollback-manager.ts
114
- class RollbackManager {
115
- options;
116
- constructor(options) {
117
- this.options = options;
118
- }
119
- async execute(stage, reason) {
120
- await this.options.rollback(stage, reason);
121
- const action = {
122
- reason,
123
- stage,
124
- triggeredAt: new Date
125
- };
126
- this.options.onRollback?.(action);
127
- return action;
128
- }
129
- }
130
79
  // src/deployment-coordinator.ts
131
80
  class DeploymentCoordinator {
132
81
  options;
@@ -168,6 +117,23 @@ class DeploymentCoordinator {
168
117
  return { status: "completed" };
169
118
  }
170
119
  }
120
+ // src/events.ts
121
+ class DeploymentEventBus {
122
+ listeners = new Set;
123
+ on(listener) {
124
+ this.listeners.add(listener);
125
+ return () => this.listeners.delete(listener);
126
+ }
127
+ emit(event) {
128
+ for (const listener of this.listeners) {
129
+ try {
130
+ listener(event);
131
+ } catch (error) {
132
+ console.error("[progressive-delivery] listener error", error);
133
+ }
134
+ }
135
+ }
136
+ }
171
137
  // src/feature-flags.ts
172
138
  var ContractSpecFeatureFlags = {
173
139
  LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha",
@@ -195,6 +161,40 @@ var studioFlags = [
195
161
  ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,
196
162
  ContractSpecFeatureFlags.STUDIO_TEMPLATES
197
163
  ];
164
+ // src/rollback-manager.ts
165
+ class RollbackManager {
166
+ options;
167
+ constructor(options) {
168
+ this.options = options;
169
+ }
170
+ async execute(stage, reason) {
171
+ await this.options.rollback(stage, reason);
172
+ const action = {
173
+ reason,
174
+ stage,
175
+ triggeredAt: new Date
176
+ };
177
+ this.options.onRollback?.(action);
178
+ return action;
179
+ }
180
+ }
181
+ // src/traffic-shifter.ts
182
+ class TrafficShifter {
183
+ mode;
184
+ constructor(mode) {
185
+ this.mode = mode;
186
+ }
187
+ computeSplit(stage) {
188
+ if (this.mode === "blue-green") {
189
+ return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
190
+ }
191
+ const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
192
+ return {
193
+ candidate,
194
+ stable: 1 - candidate
195
+ };
196
+ }
197
+ }
198
198
  export {
199
199
  studioFlags,
200
200
  lifecycleFlags,
@@ -1,37 +1,3 @@
1
- // src/events.ts
2
- class DeploymentEventBus {
3
- listeners = new Set;
4
- on(listener) {
5
- this.listeners.add(listener);
6
- return () => this.listeners.delete(listener);
7
- }
8
- emit(event) {
9
- for (const listener of this.listeners) {
10
- try {
11
- listener(event);
12
- } catch (error) {
13
- console.error("[progressive-delivery] listener error", error);
14
- }
15
- }
16
- }
17
- }
18
- // src/traffic-shifter.ts
19
- class TrafficShifter {
20
- mode;
21
- constructor(mode) {
22
- this.mode = mode;
23
- }
24
- computeSplit(stage) {
25
- if (this.mode === "blue-green") {
26
- return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
27
- }
28
- const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
29
- return {
30
- candidate,
31
- stable: 1 - candidate
32
- };
33
- }
34
- }
35
1
  // src/canary-analyzer.ts
36
2
  class CanaryAnalyzer {
37
3
  defaults;
@@ -109,23 +75,6 @@ function createDefaultCanaryController(strategy, metricsProvider, eventBus) {
109
75
  eventBus
110
76
  });
111
77
  }
112
- // src/rollback-manager.ts
113
- class RollbackManager {
114
- options;
115
- constructor(options) {
116
- this.options = options;
117
- }
118
- async execute(stage, reason) {
119
- await this.options.rollback(stage, reason);
120
- const action = {
121
- reason,
122
- stage,
123
- triggeredAt: new Date
124
- };
125
- this.options.onRollback?.(action);
126
- return action;
127
- }
128
- }
129
78
  // src/deployment-coordinator.ts
130
79
  class DeploymentCoordinator {
131
80
  options;
@@ -167,6 +116,23 @@ class DeploymentCoordinator {
167
116
  return { status: "completed" };
168
117
  }
169
118
  }
119
+ // src/events.ts
120
+ class DeploymentEventBus {
121
+ listeners = new Set;
122
+ on(listener) {
123
+ this.listeners.add(listener);
124
+ return () => this.listeners.delete(listener);
125
+ }
126
+ emit(event) {
127
+ for (const listener of this.listeners) {
128
+ try {
129
+ listener(event);
130
+ } catch (error) {
131
+ console.error("[progressive-delivery] listener error", error);
132
+ }
133
+ }
134
+ }
135
+ }
170
136
  // src/feature-flags.ts
171
137
  var ContractSpecFeatureFlags = {
172
138
  LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha",
@@ -194,6 +160,40 @@ var studioFlags = [
194
160
  ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,
195
161
  ContractSpecFeatureFlags.STUDIO_TEMPLATES
196
162
  ];
163
+ // src/rollback-manager.ts
164
+ class RollbackManager {
165
+ options;
166
+ constructor(options) {
167
+ this.options = options;
168
+ }
169
+ async execute(stage, reason) {
170
+ await this.options.rollback(stage, reason);
171
+ const action = {
172
+ reason,
173
+ stage,
174
+ triggeredAt: new Date
175
+ };
176
+ this.options.onRollback?.(action);
177
+ return action;
178
+ }
179
+ }
180
+ // src/traffic-shifter.ts
181
+ class TrafficShifter {
182
+ mode;
183
+ constructor(mode) {
184
+ this.mode = mode;
185
+ }
186
+ computeSplit(stage) {
187
+ if (this.mode === "blue-green") {
188
+ return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
189
+ }
190
+ const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
191
+ return {
192
+ candidate,
193
+ stable: 1 - candidate
194
+ };
195
+ }
196
+ }
197
197
  export {
198
198
  studioFlags,
199
199
  lifecycleFlags,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contractspec/lib.progressive-delivery",
3
- "version": "34.0.5",
3
+ "version": "34.0.7",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -16,8 +16,8 @@
16
16
  "dev": "contractspec-bun-build dev",
17
17
  "clean": "rimraf dist .turbo",
18
18
  "lint": "bun lint:fix",
19
- "lint:fix": "eslint src --fix",
20
- "lint:check": "eslint src",
19
+ "lint:fix": "biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .",
20
+ "lint:check": "biome check .",
21
21
  "prebuild": "contractspec-bun-build prebuild",
22
22
  "typecheck": "tsc --noEmit"
23
23
  },
@@ -27,12 +27,12 @@
27
27
  "directory": "packages/libs/progressive-delivery"
28
28
  },
29
29
  "peerDependencies": {
30
- "@contractspec/lib.observability": "3.7.5"
30
+ "@contractspec/lib.observability": "3.7.7"
31
31
  },
32
32
  "devDependencies": {
33
- "@contractspec/tool.typescript": "3.7.5",
33
+ "@contractspec/tool.typescript": "3.7.6",
34
34
  "typescript": "^5.9.3",
35
- "@contractspec/tool.bun": "3.7.5"
35
+ "@contractspec/tool.bun": "3.7.6"
36
36
  },
37
37
  "exports": {
38
38
  ".": {