specshield 3.2.2 → 3.2.4
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 +75 -0
- package/README.md +468 -568
- package/package.json +4 -1
- package/src/cli.js +2 -0
- package/src/commands/bdct.js +180 -2
- package/src/commands/whoami.js +105 -0
- package/src/core/conformance/index.js +52 -0
- package/src/core/conformance/pathResolver.js +108 -0
- package/src/core/conformance/probeBuilder.js +92 -0
- package/src/core/conformance/responseValidator.js +114 -0
- package/src/core/conformance/runner.js +133 -0
- package/src/core/har/emitOpenapi.js +125 -0
- package/src/core/har/index.js +68 -0
- package/src/core/har/parseHar.js +136 -0
- package/src/core/har/pathTemplate.js +92 -0
- package/src/core/har/schemaInfer.js +100 -0
- package/src/util/versionStrip.js +24 -0
package/README.md
CHANGED
|
@@ -7,19 +7,24 @@
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
> **OpenAPI Diff ·
|
|
10
|
+
> **OpenAPI Diff · Breaking-Change Detection · Bi-Directional Contract Testing · `can-i-deploy` Gate · Pact-File Ingest · Live-Traffic Capture · Spec-vs-Production Conformance · GitHub PR Checks**
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Never ship a breaking change to your API consumers.
|
|
15
15
|
|
|
16
|
-
**SpecShield**
|
|
16
|
+
**SpecShield** is the one CLI that does four things to keep your API safe:
|
|
17
|
+
|
|
18
|
+
1. **Diff** two OpenAPI specs and fail CI on breaking changes.
|
|
19
|
+
2. **Bi-directional contract testing** with `can-i-deploy` — block a deploy that would break a consumer.
|
|
20
|
+
3. **`bdct capture from-har`** — turn recorded traffic into an accurate consumer contract (no Pact DSL).
|
|
21
|
+
4. **`bdct verify-provider`** — prove the running provider actually matches its OpenAPI spec.
|
|
17
22
|
|
|
18
23
|
```
|
|
19
|
-
OpenAPI diff +
|
|
24
|
+
OpenAPI diff + BDCT + HAR → consumer contract + spec-vs-production conformance — in one CLI.
|
|
20
25
|
```
|
|
21
26
|
|
|
22
|
-
No broker. No
|
|
27
|
+
No broker. No Pact DSL. Language-agnostic. Works in 30 seconds. Local mode never uploads your specs.
|
|
23
28
|
|
|
24
29
|
---
|
|
25
30
|
|
|
@@ -27,48 +32,36 @@ No broker. No complex setup. Works in 30 seconds.
|
|
|
27
32
|
|
|
28
33
|
**APIs break silently. Your users feel it first.**
|
|
29
34
|
|
|
30
|
-
- A backend
|
|
31
|
-
- An endpoint gets removed — the frontend breaks with no error in your logs
|
|
32
|
-
- A required field changes — partner integrations
|
|
33
|
-
- You
|
|
35
|
+
- A backend rename of `status` → `paymentStatus` — the mobile app crashes for 10,000 users.
|
|
36
|
+
- An endpoint gets removed — the frontend breaks with no error in your logs.
|
|
37
|
+
- A required field changes — partner integrations fail at 2am.
|
|
38
|
+
- You find out from an angry customer, not from CI.
|
|
34
39
|
|
|
35
|
-
Manual
|
|
36
|
-
**You need a contract between your services — and something that enforces it.**
|
|
40
|
+
Manual review doesn't catch it. Integration tests run too late.
|
|
41
|
+
**You need a contract between your services — and something that enforces it on every PR and every deploy.**
|
|
37
42
|
|
|
38
43
|
---
|
|
39
44
|
|
|
40
45
|
## The Solution
|
|
41
46
|
|
|
42
|
-
Think of SpecShield as **unit tests for your API contracts
|
|
47
|
+
Think of SpecShield as **unit tests for your API contracts.**
|
|
43
48
|
|
|
44
|
-
-
|
|
45
|
-
- The provider proves it satisfies those expectations before deploying
|
|
46
|
-
-
|
|
49
|
+
- Consumers declare (or record) what they expect from the provider.
|
|
50
|
+
- The provider proves it satisfies those expectations before deploying.
|
|
51
|
+
- The pipeline blocks the deploy if anything breaks.
|
|
47
52
|
|
|
48
53
|
```
|
|
49
|
-
Consumer publishes contract → Provider verifies it → CI
|
|
54
|
+
Consumer publishes contract → Provider verifies it → CI passes or blocks
|
|
50
55
|
```
|
|
51
56
|
|
|
52
57
|
No runtime surprise. No production incident. No 3am page.
|
|
53
58
|
|
|
54
59
|
---
|
|
55
60
|
|
|
56
|
-
## 🎥 Demo
|
|
57
|
-
|
|
58
|
-
[](https://www.youtube.com/watch?v=mugDyQQGqZw)
|
|
59
|
-
|
|
60
|
-
> Watch: Catching a breaking API change before it hits production — compare specs, publish provider/consumer specs via BDCT, and gate deployments with `can-i-deploy`.
|
|
61
|
-
|
|
62
|
-
**CLI preview:**
|
|
63
|
-
|
|
64
|
-

|
|
65
|
-
|
|
66
|
-
> `specshield compare payment-api-v1.yaml payment-api-v2.yaml --fail-on-breaking`
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
61
|
## See It in Action
|
|
71
62
|
|
|
63
|
+
**Catch a breaking spec change in CI:**
|
|
64
|
+
|
|
72
65
|
```bash
|
|
73
66
|
$ specshield compare base.yaml target.yaml --fail-on-breaking
|
|
74
67
|
|
|
@@ -85,37 +78,43 @@ $ specshield compare base.yaml target.yaml --fail-on-breaking
|
|
|
85
78
|
CI Result: FAILED · Exit code: 1
|
|
86
79
|
```
|
|
87
80
|
|
|
88
|
-
**
|
|
89
|
-
|
|
90
|
-
And when everything is safe:
|
|
81
|
+
**Catch the running provider drifting from its own spec:**
|
|
91
82
|
|
|
92
83
|
```bash
|
|
93
|
-
$ specshield
|
|
84
|
+
$ specshield bdct verify-provider --spec api/openapi.yaml --base-url https://staging.payments.acme.com
|
|
94
85
|
|
|
95
|
-
|
|
86
|
+
Provider conformance — spec vs https://staging.payments.acme.com
|
|
87
|
+
────────────────────────────────────────────────────────────
|
|
88
|
+
PASS GET /health (200)
|
|
89
|
+
FAIL GET /payments/{paymentId} (200)
|
|
90
|
+
/amount: must be number
|
|
91
|
+
PASS GET /orders (200)
|
|
92
|
+
────────────────────────────────────────────────────────────
|
|
93
|
+
2 pass · 1 fail · 0 error · 0 skip (3 probes)
|
|
94
|
+
```
|
|
96
95
|
|
|
97
|
-
|
|
98
|
-
Modifications : 0
|
|
99
|
-
Additions : 3
|
|
96
|
+
**Turn recorded test traffic into an accurate consumer contract — no Pact DSL:**
|
|
100
97
|
|
|
101
|
-
|
|
98
|
+
```bash
|
|
99
|
+
$ specshield bdct capture from-har --in checkout-tests.har --base-url https://api.acme.com --out consumer.yaml
|
|
100
|
+
|
|
101
|
+
✔ Wrote consumer.yaml (2 endpoints, 3 ops from 17/24 entries)
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
**That output just saved you a production incident.**
|
|
105
|
+
|
|
104
106
|
---
|
|
105
107
|
|
|
106
108
|
## Quick Start
|
|
107
109
|
|
|
108
|
-
No account
|
|
110
|
+
No account, no login, no config file for `compare`. Just run it.
|
|
109
111
|
|
|
110
112
|
```bash
|
|
111
113
|
npm install -g specshield
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
```bash
|
|
115
114
|
specshield compare base.yaml target.yaml --fail-on-breaking
|
|
116
115
|
```
|
|
117
116
|
|
|
118
|
-
|
|
117
|
+
Works with any OpenAPI 3.x YAML or JSON.
|
|
119
118
|
|
|
120
119
|
**For BDCT**, run the wizard once and never re-type the same flags again:
|
|
121
120
|
|
|
@@ -123,71 +122,24 @@ That's it. Works with any OpenAPI 3.x YAML or JSON spec.
|
|
|
123
122
|
specshield init
|
|
124
123
|
```
|
|
125
124
|
|
|
126
|
-
It
|
|
127
|
-
`pyproject.toml` / `pom.xml` / `go.mod`), your git branch, and your
|
|
128
|
-
default environment, asks you a few questions, and writes a
|
|
129
|
-
**`.specshield.yml`** at the project root. Every subsequent
|
|
130
|
-
`specshield bdct ...` invocation reads this file, so your CI commands
|
|
131
|
-
collapse to:
|
|
125
|
+
It auto-detects your spec, service name (from `package.json` / `pyproject.toml` / `pom.xml` / `go.mod`), git branch, and environment; writes **`.specshield.yml`**; and (optionally) seeds a GitHub Actions workflow. Every subsequent `specshield bdct …` invocation reads this file, so your CI commands collapse to:
|
|
132
126
|
|
|
133
127
|
```bash
|
|
134
128
|
specshield bdct publish-provider --version $GITHUB_SHA
|
|
135
|
-
specshield bdct can-i-deploy
|
|
129
|
+
specshield bdct can-i-deploy --version $GITHUB_SHA
|
|
136
130
|
```
|
|
137
131
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
> **Quiet install for CI / Docker images:**
|
|
141
|
-
> The post-install welcome banner auto-detects CI environments (`CI`,
|
|
142
|
-
> `GITHUB_ACTIONS`, `BUILDKITE`, `CIRCLECI`, `GITLAB_CI`, `JENKINS_URL`,
|
|
143
|
-
> `TRAVIS`, `TF_BUILD`) and skips itself there — so your CI logs stay clean.
|
|
144
|
-
> To silence it on a workstation too:
|
|
145
|
-
> ```bash
|
|
146
|
-
> export SPECSHIELD_NO_BANNER=1
|
|
147
|
-
> ```
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
## 🚀 Create Your Free Account
|
|
152
|
-
|
|
153
|
-
**Unlock history, dashboards, contract testing, and team features.**
|
|
154
|
-
|
|
155
|
-
👉 **[Create free account at specshield.io](https://specshield.io)**
|
|
156
|
-
|
|
157
|
-
- ✅ No credit card required
|
|
158
|
-
- ✅ Takes less than 30 seconds
|
|
159
|
-
- ✅ GitHub and Google sign-in supported
|
|
160
|
-
- ✅ Local compare always free, forever
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## Local vs Cloud
|
|
165
|
-
|
|
166
|
-
| Feature | Local (Free) | Cloud Free | Cloud Pro |
|
|
167
|
-
|---|---|---|---|
|
|
168
|
-
| Compare two spec files | ✅ | ✅ | ✅ |
|
|
169
|
-
| Breaking change detection | ✅ | ✅ | ✅ |
|
|
170
|
-
| JSON / human output | ✅ | ✅ | ✅ |
|
|
171
|
-
| Fail CI on breaking change | ✅ | ✅ | ✅ |
|
|
172
|
-
| **`specshield history` — compare timeline** | ❌ | ✅ | ✅ |
|
|
173
|
-
| **`specshield share` — public report URLs** | ❌ | ✅ | ✅ |
|
|
174
|
-
| **Dashboard** | ❌ | ✅ | ✅ |
|
|
175
|
-
| **GitHub App PR checks** | ❌ | ✅ | ✅ |
|
|
176
|
-
| **BDCT bi-directional contracts** | ❌ | ❌ | ✅ |
|
|
177
|
-
| **BDCT can-i-deploy gating** | ❌ | ❌ | ✅ |
|
|
178
|
-
| **BDCT compatibility matrix** | ❌ | ❌ | ✅ |
|
|
179
|
-
| **Team collaboration** | ❌ | ❌ | ✅ |
|
|
180
|
-
| **API drift trends** | ❌ | ✅ | ✅ |
|
|
132
|
+
> **Quiet install for CI / Docker:** the post-install welcome banner auto-skips in CI (`CI`, `GITHUB_ACTIONS`, `BUILDKITE`, `CIRCLECI`, `GITLAB_CI`, `JENKINS_URL`, `TRAVIS`, `TF_BUILD`). To silence it on a workstation too: `export SPECSHIELD_NO_BANNER=1`.
|
|
181
133
|
|
|
182
134
|
---
|
|
183
135
|
|
|
184
136
|
## A Real-World Story
|
|
185
137
|
|
|
186
|
-
> The `payment-service` team merged a change that renamed `status` to
|
|
187
|
-
>
|
|
138
|
+
> The `payment-service` team merged a change that renamed `status` to
|
|
139
|
+
> `paymentStatus`. The `checkout-ui` team wasn't notified.
|
|
188
140
|
>
|
|
189
|
-
> Without SpecShield, this would have reached staging, broken checkout for
|
|
190
|
-
> and triggered an incident at 2am.
|
|
141
|
+
> Without SpecShield, this would have reached staging, broken checkout for
|
|
142
|
+
> every user, and triggered an incident at 2am.
|
|
191
143
|
>
|
|
192
144
|
> With SpecShield, the provider's CI published the new spec via
|
|
193
145
|
> `specshield bdct publish-provider`. The compatibility engine ran against
|
|
@@ -205,92 +157,40 @@ See [§ specshield init](#specshield-init--first-run-setup-wizard) below.
|
|
|
205
157
|
|
|
206
158
|
## Use Cases
|
|
207
159
|
|
|
208
|
-
**Pull
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
**
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
**Microservices Contract Safety**
|
|
215
|
-
Consumer teams publish what they expect. Provider teams verify they deliver it. No cross-team surprises.
|
|
216
|
-
|
|
217
|
-
**API Governance**
|
|
218
|
-
Track API drift over time across your entire platform. Know what changed, when, and which team changed it.
|
|
160
|
+
- **Pull-request validation** — catch breaking changes before merge with `specshield compare`.
|
|
161
|
+
- **CI/CD gating** — exit code `1` stops the pipeline automatically.
|
|
162
|
+
- **Microservices contract safety** — consumers publish what they expect, providers verify they deliver it, no cross-team surprises.
|
|
163
|
+
- **API governance** — track API drift over time across your platform; know what changed, when, by whom.
|
|
164
|
+
- **Provider conformance** *(new)* — make sure your *running* service actually matches its published OpenAPI spec, not just on paper.
|
|
165
|
+
- **Pact-free consumer contracts** *(new)* — record real traffic with `capture from-har` and get an OpenAPI consumer contract without writing a single line of Pact DSL.
|
|
219
166
|
|
|
220
167
|
---
|
|
221
168
|
|
|
222
|
-
## vs
|
|
169
|
+
## Local vs Cloud
|
|
223
170
|
|
|
224
|
-
| Feature |
|
|
171
|
+
| Feature | Local (Free) | Team | Enterprise |
|
|
225
172
|
|---|---|---|---|
|
|
226
|
-
|
|
|
227
|
-
|
|
|
228
|
-
|
|
|
229
|
-
|
|
|
230
|
-
|
|
|
231
|
-
|
|
|
232
|
-
|
|
|
233
|
-
|
|
|
234
|
-
|
|
|
235
|
-
|
|
|
236
|
-
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|---|---|---|
|
|
244
|
-
| **Free** | $0 forever | Local compare (unlimited) · Compare history & dashboard · GitHub App PR checks |
|
|
245
|
-
| **Pro** | Coming soon | Everything in Free + BDCT bi-directional contracts · BDCT can-i-deploy & matrix · Team collaboration · Advanced reporting · Priority support |
|
|
246
|
-
|
|
247
|
-
No credit card ever required for the free plan.
|
|
248
|
-
**[Get started free →](https://specshield.io)**
|
|
173
|
+
| Compare two spec files | ✅ | ✅ | ✅ |
|
|
174
|
+
| Breaking change detection | ✅ | ✅ | ✅ |
|
|
175
|
+
| JSON / human output | ✅ | ✅ | ✅ |
|
|
176
|
+
| Fail CI on breaking change | ✅ | ✅ | ✅ |
|
|
177
|
+
| **`bdct capture from-har`** | ✅ | ✅ | ✅ |
|
|
178
|
+
| **`bdct verify-provider`** | ✅ | ✅ | ✅ |
|
|
179
|
+
| `specshield history` — compare timeline | ❌ | ✅ | ✅ |
|
|
180
|
+
| `specshield share` — public report URLs | ❌ | ✅ | ✅ |
|
|
181
|
+
| Hosted dashboard | ❌ | ✅ | ✅ |
|
|
182
|
+
| GitHub App PR checks | ❌ | ✅ | ✅ |
|
|
183
|
+
| BDCT consumer registry + can-i-deploy gate | ❌ | ✅ | ✅ |
|
|
184
|
+
| BDCT compatibility matrix | ❌ | ✅ | ✅ |
|
|
185
|
+
| Team workspace + audit log + RBAC | ❌ | ✅ | ✅ |
|
|
186
|
+
| Slack notifications | ❌ | ✅ | ✅ |
|
|
187
|
+
| SAML SSO, SCIM, on-prem | ❌ | ❌ | ✅ |
|
|
188
|
+
|
|
189
|
+
> **The local-only commands are first-class.** `compare`, `bdct capture from-har`, and `bdct verify-provider` all run entirely in your CI — your spec text never leaves your infrastructure.
|
|
249
190
|
|
|
250
191
|
---
|
|
251
192
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
**Step 1 — Create your account**
|
|
255
|
-
|
|
256
|
-
Go to [https://specshield.io](https://specshield.io) · Sign in with GitHub or Google (30 seconds)
|
|
257
|
-
|
|
258
|
-
**Step 2 — Generate an API key**
|
|
259
|
-
|
|
260
|
-
Dashboard → **API Keys** → **Generate Key** · Copy the `ss_` token
|
|
261
|
-
|
|
262
|
-
**Step 3 — Authenticate the CLI**
|
|
263
|
-
|
|
264
|
-
```bash
|
|
265
|
-
specshield login --api-key ss_your_token_here
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
```
|
|
269
|
-
✔ Logged in successfully.
|
|
270
|
-
Customer : Your Name
|
|
271
|
-
Plan : FREE
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Done. Your token is stored in `~/.specshield/config.json` — no need to pass it on every command.
|
|
275
|
-
|
|
276
|
-
**Or use an environment variable (recommended for CI):**
|
|
277
|
-
|
|
278
|
-
```bash
|
|
279
|
-
export SPECSHIELD_API_KEY=ss_your_token_here
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
This single env var works for every command — `compare`, `login`, and every
|
|
283
|
-
`bdct` subcommand all read it.
|
|
284
|
-
|
|
285
|
-
Token resolution order:
|
|
286
|
-
- `compare` / `login`: `--api-key` flag → `SPECSHIELD_API_KEY` env var → stored config → `.specshield.yml`
|
|
287
|
-
- `bdct ...` subcommands: `--api-token` flag → `SPECSHIELD_API_KEY` env var → stored config
|
|
288
|
-
|
|
289
|
-
> **Why two flag names?** `compare` and `login` were built first and used
|
|
290
|
-
> `--api-key`. The newer `bdct` commands use `--api-token` to keep the word
|
|
291
|
-
> "key" reserved for the stored config concept. The env var unifies both.
|
|
292
|
-
|
|
293
|
-
---
|
|
193
|
+
# Commands
|
|
294
194
|
|
|
295
195
|
## Local Compare
|
|
296
196
|
|
|
@@ -313,36 +213,24 @@ specshield compare base.yaml target.yaml --output result.json
|
|
|
313
213
|
specshield compare base.yaml target.yaml --ignore "DELETE /admin removed" --fail-on-breaking
|
|
314
214
|
```
|
|
315
215
|
|
|
316
|
-
---
|
|
317
|
-
|
|
318
216
|
## Remote Compare
|
|
319
217
|
|
|
320
|
-
Sends your specs to SpecShield and stores results in your dashboard.
|
|
321
|
-
Requires a free account and API key.
|
|
218
|
+
Sends your specs to SpecShield and stores results in your dashboard. Requires a free account.
|
|
322
219
|
|
|
323
220
|
```bash
|
|
324
|
-
# Remote compare
|
|
325
221
|
specshield compare base.yaml target.yaml --remote
|
|
326
|
-
|
|
327
|
-
# Remote + fail on breaking
|
|
328
222
|
specshield compare base.yaml target.yaml --remote --fail-on-breaking
|
|
329
|
-
|
|
330
|
-
# Remote + JSON output saved to file
|
|
331
223
|
specshield compare base.yaml target.yaml --remote --json --output result.json
|
|
332
224
|
```
|
|
333
225
|
|
|
334
|
-
---
|
|
335
|
-
|
|
336
226
|
## Comparison History
|
|
337
227
|
|
|
338
|
-
Every `specshield compare --remote` is saved to your
|
|
339
|
-
List the recent comparisons your account has run from any machine — useful
|
|
340
|
-
for tracking API drift over time across CI pipelines + local runs.
|
|
228
|
+
Every `specshield compare --remote` is saved to your account. List recent comparisons from any machine — useful for tracking API drift over time across CI pipelines + local runs.
|
|
341
229
|
|
|
342
230
|
```bash
|
|
343
231
|
specshield history # last 20 comparisons
|
|
344
|
-
specshield history --limit 50
|
|
345
|
-
specshield history --json
|
|
232
|
+
specshield history --limit 50
|
|
233
|
+
specshield history --json
|
|
346
234
|
```
|
|
347
235
|
|
|
348
236
|
```
|
|
@@ -353,15 +241,9 @@ specshield history --json # machine-readable for scripts
|
|
|
353
241
|
480 7 breaking 2026-05-16 18:55 billing-v3.yaml → billing-v4.yaml
|
|
354
242
|
```
|
|
355
243
|
|
|
356
|
-
Account required — run `specshield login` to set up (free, no credit card).
|
|
357
|
-
|
|
358
|
-
---
|
|
359
|
-
|
|
360
244
|
## Share a Comparison
|
|
361
245
|
|
|
362
|
-
Generate a public, tokenized URL for any comparison report.
|
|
363
|
-
the link can view the diff — no SpecShield account needed. Great for
|
|
364
|
-
pasting into Slack threads, PR comments, or Jira tickets.
|
|
246
|
+
Generate a public, tokenized URL for any comparison report. Great for Slack threads, PR comments, Jira tickets.
|
|
365
247
|
|
|
366
248
|
```bash
|
|
367
249
|
# Share an existing report by ID (from `specshield history`)
|
|
@@ -376,190 +258,45 @@ specshield share 482 --expires 30
|
|
|
376
258
|
|
|
377
259
|
```
|
|
378
260
|
✔ Share link ready
|
|
379
|
-
─────────────────────────────────────────────────────
|
|
380
261
|
https://specshield.io/r/_Ru8OVubxY3r9zHOsylESaULphCqBYH5jTPYldSMU88
|
|
381
262
|
Expires: 2026-06-16T12:34:56Z
|
|
382
|
-
|
|
383
|
-
Anyone with this link can view the diff — no SpecShield account required.
|
|
384
263
|
```
|
|
385
264
|
|
|
386
|
-
Links use a 256-bit random token
|
|
387
|
-
Revoke any time from your dashboard at [specshield.io](https://specshield.io).
|
|
265
|
+
Links use a 256-bit random token (unguessable by enumeration). Revoke any time from the dashboard.
|
|
388
266
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
---
|
|
392
|
-
|
|
393
|
-
## GitHub Integration
|
|
267
|
+
## GitHub App — PR Checks
|
|
394
268
|
|
|
395
269
|
**Automatic API contract checks on every pull request — no workflow YAML required.**
|
|
396
270
|
|
|
397
|
-
Install
|
|
398
|
-
- A GitHub check run (pass/fail) visible directly on the PR
|
|
399
|
-
- A PR comment with the full diff table — breaking changes highlighted in red
|
|
400
|
-
- Configurable `fail-on-breaking` per repository
|
|
401
|
-
|
|
402
|
-
### Install the GitHub App
|
|
403
|
-
|
|
404
|
-
1. Go to **Dashboard → GitHub Integration** at [specshield.io](https://specshield.io)
|
|
405
|
-
2. Click **Install GitHub App**
|
|
406
|
-
3. Choose the repositories to enable (or select all)
|
|
407
|
-
4. Done — no secrets, no workflow changes needed
|
|
408
|
-
|
|
409
|
-
### How It Works
|
|
410
|
-
|
|
411
|
-
When a PR is opened or updated, SpecShield:
|
|
412
|
-
|
|
413
|
-
1. Fetches the OpenAPI spec from the base branch and the PR branch
|
|
414
|
-
2. Runs the same diff engine as `specshield compare`
|
|
415
|
-
3. Posts a GitHub check run — **Passed** if no breaking changes, **Failed** if breaking changes found
|
|
416
|
-
4. Adds a PR comment with the full breakdown:
|
|
417
|
-
|
|
418
|
-
```
|
|
419
|
-
## SpecShield API Contract Check
|
|
420
|
-
|
|
421
|
-
| Change | Type | Severity |
|
|
422
|
-
|--------|------|----------|
|
|
423
|
-
| POST /payments — "amount" required field added | Request schema | BREAKING |
|
|
424
|
-
| GET /orders/{id} — "status" type changed | Response schema | BREAKING |
|
|
425
|
-
| GET /users — new query param "filter" | Addition | NON-BREAKING |
|
|
426
|
-
|
|
427
|
-
Breaking changes: 2 · Non-breaking: 1
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
### Configure Per Repository
|
|
431
|
-
|
|
432
|
-
Add a `.specshield.yml` to your repo root:
|
|
433
|
-
|
|
434
|
-
```yaml
|
|
435
|
-
github:
|
|
436
|
-
specPath: api/openapi.yaml # path to your spec (default: openapi.yaml)
|
|
437
|
-
failOnBreaking: true # block PR merge on breaking changes (default: true)
|
|
438
|
-
commentOnPr: true # post breakdown comment (default: true)
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
### Requirements
|
|
442
|
-
|
|
443
|
-
- The spec file must exist on both the base branch and the PR branch
|
|
444
|
-
- Supported formats: OpenAPI 3.x YAML or JSON
|
|
445
|
-
- The GitHub App needs `pull_requests: write` and `checks: write` permissions (granted during install)
|
|
271
|
+
Install once at **Dashboard → GitHub Integration**, choose your repos, done. Every PR that touches the OpenAPI spec gets:
|
|
446
272
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
273
|
+
- A GitHub check run (pass/fail) visible on the PR
|
|
274
|
+
- A sticky PR comment with the full diff (breaking changes highlighted)
|
|
275
|
+
- Configurable `failOnBreaking` per repository
|
|
450
276
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
1. Detects your OpenAPI spec (looks under `api/`, `spec/`, `docs/`, repo root).
|
|
454
|
-
2. Detects your service name (`package.json`, `pyproject.toml`, `pom.xml`, `go.mod`, `Cargo.toml`, or directory name).
|
|
455
|
-
3. Detects your git branch and suggests `production` for `main`/`master`, `staging` otherwise.
|
|
456
|
-
4. Asks whether this project is a provider, a consumer, or both.
|
|
457
|
-
5. Asks for your org key (autocompletes from your account if you're already signed in).
|
|
458
|
-
6. Validates / stores your API key.
|
|
459
|
-
7. Writes **`.specshield.yml`** and, optionally, a starter **`.github/workflows/specshield-bdct.yml`** that uses [`specshield26/bdct-action@v1`](https://github.com/marketplace/actions/specshield-bdct).
|
|
460
|
-
|
|
461
|
-
```bash
|
|
462
|
-
specshield init
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
### Example `.specshield.yml`
|
|
277
|
+
Configure per-repo via `.specshield.yml`:
|
|
466
278
|
|
|
467
279
|
```yaml
|
|
468
|
-
schemaVersion: 1
|
|
469
|
-
|
|
470
|
-
failOnBreaking: true
|
|
471
|
-
severity: error
|
|
472
|
-
|
|
473
|
-
bdct:
|
|
474
|
-
org: acme-pay
|
|
475
|
-
environment: staging
|
|
476
|
-
|
|
477
|
-
provider:
|
|
478
|
-
name: payment-service
|
|
479
|
-
spec: api/openapi.yaml
|
|
480
|
-
|
|
481
|
-
# consumer (optional — present when --kind=consumer or --kind=both):
|
|
482
|
-
# consumer:
|
|
483
|
-
# name: checkout-ui
|
|
484
|
-
# provider: payment-service
|
|
485
|
-
# contract: contracts/payment-service.yaml
|
|
486
|
-
# format: OPENAPI
|
|
487
|
-
|
|
488
280
|
github:
|
|
489
281
|
specPath: api/openapi.yaml
|
|
490
282
|
failOnBreaking: true
|
|
491
283
|
commentOnPr: true
|
|
492
284
|
```
|
|
493
285
|
|
|
494
|
-
CLI flags **always** override this file. Paths in the file are resolved
|
|
495
|
-
relative to the file's own directory, so you can run `specshield bdct ...`
|
|
496
|
-
from any subdirectory of your project.
|
|
497
|
-
|
|
498
|
-
### Non-interactive (scriptable) mode
|
|
499
|
-
|
|
500
|
-
```bash
|
|
501
|
-
# Provider-only project
|
|
502
|
-
specshield init --no-interactive \
|
|
503
|
-
--kind provider \
|
|
504
|
-
--org acme-pay \
|
|
505
|
-
--provider payment-service \
|
|
506
|
-
--spec api/openapi.yaml \
|
|
507
|
-
--env staging \
|
|
508
|
-
--write-workflow
|
|
509
|
-
|
|
510
|
-
# Consumer-only project
|
|
511
|
-
specshield init --no-interactive \
|
|
512
|
-
--kind consumer \
|
|
513
|
-
--org acme-pay \
|
|
514
|
-
--consumer checkout-ui \
|
|
515
|
-
--consumer-provider payment-service \
|
|
516
|
-
--contract contracts/payment-service.yaml \
|
|
517
|
-
--format OPENAPI \
|
|
518
|
-
--env staging
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
### All `init` flags
|
|
522
|
-
|
|
523
|
-
| Flag | Purpose |
|
|
524
|
-
| --- | --- |
|
|
525
|
-
| `--no-interactive` | Run without prompts; all required fields must come from flags or `package.json`/git autodetection. |
|
|
526
|
-
| `--print` | Detect everything, print the proposed YAML to stdout, write nothing. Good for `--dry-run` review in CI. |
|
|
527
|
-
| `--force` | Skip the overwrite-confirmation if `.specshield.yml` already exists. |
|
|
528
|
-
| `--server <url>` | Use a non-default SpecShield endpoint (self-hosted / staging). Default: `https://specshield.io`. |
|
|
529
|
-
| `--kind <kind>` | `provider`, `consumer`, `both`, or `skip`. Required in `--no-interactive`. |
|
|
530
|
-
| `--org <key>` | Organization key. |
|
|
531
|
-
| `--provider <name>` | Provider service name (used when `--kind=provider|both`). |
|
|
532
|
-
| `--spec <path>` | Path to the provider OpenAPI spec. |
|
|
533
|
-
| `--consumer <name>` | Consumer service name (used when `--kind=consumer|both`). |
|
|
534
|
-
| `--consumer-provider <name>` | The provider this consumer talks to (used when `--kind=consumer|both`). |
|
|
535
|
-
| `--contract <path>` | Path to the consumer contract (OpenAPI or Pact JSON). |
|
|
536
|
-
| `--format <fmt>` | Consumer contract format: `OPENAPI` (default) or `PACT`. |
|
|
537
|
-
| `--env <environment>` | Default environment for BDCT operations. |
|
|
538
|
-
| `--write-workflow` | Also write a starter GitHub Actions workflow under `.github/workflows/specshield-bdct.yml`. |
|
|
539
|
-
|
|
540
|
-
> **What is _not_ written into `.specshield.yml`:** your API key. It is
|
|
541
|
-
> stored in `~/.specshield/config.json` (set by `specshield login`) or
|
|
542
|
-
> read from `SPECSHIELD_API_KEY` in CI. The project file is meant to be
|
|
543
|
-
> committed; never commit a secret into it.
|
|
544
|
-
|
|
545
286
|
---
|
|
546
287
|
|
|
547
|
-
|
|
288
|
+
# Bi-Directional Contract Testing (BDCT)
|
|
548
289
|
|
|
549
|
-
**
|
|
290
|
+
**Compatibility without Pact's broker overhead or DSL.**
|
|
550
291
|
|
|
551
|
-
Both sides publish
|
|
552
|
-
mismatches immediately — ideal for teams that don't run services locally or in
|
|
553
|
-
CI. Pact JSON consumer contracts are also accepted and auto-converted.
|
|
554
|
-
|
|
555
|
-
> BDCT requires a **Pro plan**. [Upgrade at specshield.io/upgrade](https://specshield.io/upgrade)
|
|
292
|
+
Both sides publish what they have — provider publishes its OpenAPI spec, consumer publishes either an OpenAPI subset *or* a Pact JSON file — and SpecShield's engine verifies that every endpoint/field the consumer relies on is satisfied by the provider. `can-i-deploy` then gates the deploy.
|
|
556
293
|
|
|
557
294
|
### How BDCT Works
|
|
558
295
|
|
|
559
|
-
1. Consumer
|
|
560
|
-
2. Provider
|
|
561
|
-
3. SpecShield compares
|
|
562
|
-
4. `can-i-deploy`
|
|
296
|
+
1. Consumer publishes a contract (OpenAPI subset *or* Pact JSON).
|
|
297
|
+
2. Provider publishes its full OpenAPI spec.
|
|
298
|
+
3. SpecShield compares: endpoint presence, request schemas, response fields, status codes, types.
|
|
299
|
+
4. `can-i-deploy` returns `0` only when all consumers are compatible.
|
|
563
300
|
|
|
564
301
|
### Publish a Provider Spec
|
|
565
302
|
|
|
@@ -573,31 +310,16 @@ specshield bdct publish-provider \
|
|
|
573
310
|
--branch main
|
|
574
311
|
```
|
|
575
312
|
|
|
576
|
-
|
|
577
|
-
✔ Provider Spec Published
|
|
578
|
-
─────────────────────────────────────────────────────
|
|
579
|
-
ID : 1842
|
|
580
|
-
Provider : payment-service
|
|
581
|
-
Version : v2.1.0
|
|
582
|
-
Environment : production
|
|
583
|
-
Published At: 2026-05-13 14:30:12
|
|
584
|
-
Verifications triggered: 3
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
`--branch` is optional — when present it's stamped on the published spec so you
|
|
588
|
-
can correlate a spec version with the git branch it came from in
|
|
589
|
-
`bdct list-providers`.
|
|
313
|
+
`--branch` is optional — stamped on the published spec so you can correlate a spec version with the git branch it came from in `bdct list-providers`.
|
|
590
314
|
|
|
591
|
-
### Publish a Consumer Contract
|
|
315
|
+
### Publish a Consumer Contract (OpenAPI subset or Pact JSON)
|
|
592
316
|
|
|
593
|
-
The consumer contract is an OpenAPI
|
|
317
|
+
The consumer contract is an OpenAPI subset describing only the endpoints the consumer uses:
|
|
594
318
|
|
|
595
319
|
```yaml
|
|
596
320
|
# consumer-contract.yaml — only the subset checkout-ui uses
|
|
597
321
|
openapi: "3.0.0"
|
|
598
|
-
info:
|
|
599
|
-
title: checkout-ui → payment-service contract
|
|
600
|
-
version: "1.0.0"
|
|
322
|
+
info: { title: checkout-ui → payment-service contract, version: "1.0.0" }
|
|
601
323
|
paths:
|
|
602
324
|
/payments:
|
|
603
325
|
post:
|
|
@@ -608,8 +330,8 @@ paths:
|
|
|
608
330
|
type: object
|
|
609
331
|
required: [orderId, amount, currency]
|
|
610
332
|
properties:
|
|
611
|
-
orderId:
|
|
612
|
-
amount:
|
|
333
|
+
orderId: { type: string }
|
|
334
|
+
amount: { type: number }
|
|
613
335
|
currency: { type: string }
|
|
614
336
|
responses:
|
|
615
337
|
"201":
|
|
@@ -632,26 +354,7 @@ specshield bdct publish-consumer \
|
|
|
632
354
|
--format OPENAPI
|
|
633
355
|
```
|
|
634
356
|
|
|
635
|
-
|
|
636
|
-
✔ Consumer Contract Published
|
|
637
|
-
─────────────────────────────────────────────────────
|
|
638
|
-
ID : 942
|
|
639
|
-
Consumer : checkout-ui
|
|
640
|
-
Provider : payment-service
|
|
641
|
-
Version : 2.0.0
|
|
642
|
-
Format : OPENAPI
|
|
643
|
-
Published At: 2026-05-13 14:31:05
|
|
644
|
-
Verifications triggered: 1
|
|
645
|
-
|
|
646
|
-
➜ Run: specshield bdct verify --consumer checkout-ui --provider payment-service
|
|
647
|
-
```
|
|
648
|
-
|
|
649
|
-
If the provider spec is already published, compatibility is verified
|
|
650
|
-
automatically — the "Verifications triggered" count reflects that.
|
|
651
|
-
|
|
652
|
-
**Pact JSON contracts are also supported** — pass `--format PACT` and point
|
|
653
|
-
`--contract` at a Pact file. The backend stores the format and runs the same
|
|
654
|
-
compatibility engine against your provider's OpenAPI spec:
|
|
357
|
+
**Pact JSON contracts are also supported** — pass `--format PACT` and point `--contract` at a Pact file. The same compatibility engine runs against your provider's OpenAPI spec:
|
|
655
358
|
|
|
656
359
|
```bash
|
|
657
360
|
specshield bdct publish-consumer \
|
|
@@ -667,28 +370,14 @@ specshield bdct publish-consumer \
|
|
|
667
370
|
|
|
668
371
|
### Verify Compatibility
|
|
669
372
|
|
|
670
|
-
Manually trigger a verification between a specific consumer/provider pair:
|
|
671
|
-
|
|
672
373
|
```bash
|
|
673
374
|
specshield bdct verify \
|
|
674
375
|
--org acme-store \
|
|
675
|
-
--consumer checkout-ui \
|
|
676
|
-
--
|
|
677
|
-
--provider payment-service \
|
|
678
|
-
--provider-version v2.1.0 \
|
|
376
|
+
--consumer checkout-ui --consumer-version 2.0.0 \
|
|
377
|
+
--provider payment-service --provider-version v2.1.0 \
|
|
679
378
|
--env production
|
|
680
379
|
```
|
|
681
380
|
|
|
682
|
-
Compatible output:
|
|
683
|
-
```
|
|
684
|
-
✔ COMPATIBLE
|
|
685
|
-
|
|
686
|
-
Endpoints checked: 2
|
|
687
|
-
Compatible : 2
|
|
688
|
-
Incompatible : 0
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
Incompatible output:
|
|
692
381
|
```
|
|
693
382
|
✖ INCOMPATIBLE
|
|
694
383
|
|
|
@@ -706,24 +395,18 @@ Incompatible output:
|
|
|
706
395
|
consumer: integer → provider: string
|
|
707
396
|
```
|
|
708
397
|
|
|
709
|
-
### Can I Deploy?
|
|
398
|
+
### Can I Deploy?
|
|
710
399
|
|
|
711
400
|
```bash
|
|
712
401
|
specshield bdct can-i-deploy \
|
|
713
|
-
--org acme-store \
|
|
714
|
-
--
|
|
715
|
-
--version v2.1.0 \
|
|
716
|
-
--env production
|
|
402
|
+
--org acme-store --service payment-service \
|
|
403
|
+
--version v2.1.0 --env production
|
|
717
404
|
```
|
|
718
405
|
|
|
719
|
-
Deployable output:
|
|
720
|
-
|
|
721
406
|
```
|
|
722
407
|
✔ PASS: payment-service v2.1.0 is deployable in production
|
|
723
408
|
─────────────────────────────────────────────────────
|
|
724
409
|
|
|
725
|
-
Consumer Verifications
|
|
726
|
-
|
|
727
410
|
Consumer Version Status Verified At
|
|
728
411
|
─────────── ─────── ────────── ───────────────
|
|
729
412
|
checkout-ui 2.0.0 COMPATIBLE 2026-05-13 14:32
|
|
@@ -731,100 +414,52 @@ Deployable output:
|
|
|
731
414
|
partner-sdk 3.2.1 COMPATIBLE 2026-05-13 14:32
|
|
732
415
|
```
|
|
733
416
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
```
|
|
737
|
-
✖ FAIL: payment-service v2.1.0 is NOT deployable in production
|
|
738
|
-
─────────────────────────────────────────────────────
|
|
739
|
-
|
|
740
|
-
Consumer Verifications
|
|
741
|
-
|
|
742
|
-
Consumer Version Status Verified At
|
|
743
|
-
─────────── ─────── ──────────── ───────────────
|
|
744
|
-
checkout-ui 2.0.0 INCOMPATIBLE 2026-05-13 14:32
|
|
745
|
-
mobile-app 1.5.0 INCOMPATIBLE 2026-05-13 14:32
|
|
746
|
-
|
|
747
|
-
➜ Run: specshield bdct verify --consumer <NAME> --provider payment-service
|
|
748
|
-
➜ to identify and resolve incompatibilities
|
|
749
|
-
```
|
|
750
|
-
|
|
751
|
-
Exit codes: `0` = deployable · `1` = blocked · `2` = error
|
|
417
|
+
Exit codes: `0` = deployable · `1` = blocked · `2` = error.
|
|
752
418
|
|
|
753
419
|
### Compatibility Matrix
|
|
754
420
|
|
|
755
|
-
View the compatibility status across all consumer/provider pairs in your org:
|
|
756
|
-
|
|
757
421
|
```bash
|
|
758
422
|
specshield bdct matrix --org acme-store --env production
|
|
759
423
|
```
|
|
760
424
|
|
|
761
425
|
```
|
|
762
|
-
BDCT Compatibility Matrix
|
|
763
|
-
Environment: production
|
|
764
|
-
─────────────────────────────────────────────────────
|
|
765
|
-
|
|
766
426
|
Consumer \ Provider payment-service order-service
|
|
767
427
|
─────────────────── ─────────────── ─────────────
|
|
768
428
|
checkout-ui COMPATIBLE COMPATIBLE
|
|
769
429
|
mobile-app INCOMPATIBLE COMPATIBLE
|
|
770
430
|
partner-sdk COMPATIBLE UNKNOWN
|
|
771
|
-
|
|
772
|
-
■ COMPATIBLE ■ INCOMPATIBLE ■ UNKNOWN
|
|
773
431
|
```
|
|
774
432
|
|
|
775
|
-
### List Provider Specs
|
|
433
|
+
### List Provider Specs / Consumer Contracts / Verifications
|
|
776
434
|
|
|
777
435
|
```bash
|
|
778
|
-
# All providers for the org
|
|
779
436
|
specshield bdct list-providers --org acme-store
|
|
780
|
-
|
|
781
|
-
# Filter by provider name
|
|
782
437
|
specshield bdct list-providers --org acme-store --provider payment-service
|
|
783
|
-
```
|
|
784
|
-
|
|
785
|
-
```
|
|
786
|
-
Published Provider Specs
|
|
787
|
-
─────────────────────────────────────────────────────
|
|
788
|
-
Showing 3 of 3 specs
|
|
789
|
-
|
|
790
|
-
ID Provider Version Environment Branch Published At
|
|
791
|
-
──── ─────────────── ─────── ─────────── ────── ───────────────
|
|
792
|
-
1842 payment-service v2.1.0 production main 2026-05-13 14:30
|
|
793
|
-
1799 payment-service v2.0.0 staging main 2026-04-20 09:11
|
|
794
|
-
1772 order-service v1.3.0 production main 2026-04-28 11:02
|
|
795
|
-
```
|
|
796
|
-
|
|
797
|
-
### List Consumer Contracts
|
|
798
438
|
|
|
799
|
-
```bash
|
|
800
|
-
# All consumers for the org
|
|
801
439
|
specshield bdct list-consumers --org acme-store
|
|
802
|
-
|
|
803
|
-
# Filter by consumer or provider
|
|
804
440
|
specshield bdct list-consumers --org acme-store --consumer checkout-ui
|
|
805
|
-
|
|
441
|
+
|
|
442
|
+
specshield bdct list --org acme-store --provider payment-service --env production
|
|
806
443
|
```
|
|
807
444
|
|
|
808
|
-
###
|
|
445
|
+
### Full BDCT Workflow
|
|
809
446
|
|
|
810
447
|
```bash
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
--provider payment-service \
|
|
814
|
-
--
|
|
815
|
-
--page 0 \
|
|
816
|
-
--size 20
|
|
817
|
-
```
|
|
448
|
+
# 1. Provider publishes spec on every release
|
|
449
|
+
specshield bdct publish-provider \
|
|
450
|
+
--org acme-store --provider payment-service \
|
|
451
|
+
--version v2.1.0 --spec ./api/openapi.yaml
|
|
818
452
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
453
|
+
# 2. Each consumer publishes their contract (update on contract change)
|
|
454
|
+
specshield bdct publish-consumer \
|
|
455
|
+
--org acme-store --consumer checkout-ui \
|
|
456
|
+
--provider payment-service --version 2.0.0 \
|
|
457
|
+
--contract ./contracts/checkout-ui.yaml
|
|
823
458
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
459
|
+
# 3. Gate the provider deployment
|
|
460
|
+
specshield bdct can-i-deploy \
|
|
461
|
+
--org acme-store --service payment-service \
|
|
462
|
+
--version v2.1.0 --env production
|
|
828
463
|
```
|
|
829
464
|
|
|
830
465
|
### BDCT JSON Output
|
|
@@ -841,48 +476,174 @@ specshield bdct can-i-deploy --org acme-store --service payment-service --versio
|
|
|
841
476
|
"service": "payment-service",
|
|
842
477
|
"version": "v2.1.0",
|
|
843
478
|
"environment": "production",
|
|
844
|
-
"reason": "payment-service v2.1.0 is INCOMPATIBLE with: checkout-ui@2.0.0
|
|
479
|
+
"reason": "payment-service v2.1.0 is INCOMPATIBLE with: checkout-ui@2.0.0",
|
|
845
480
|
"verifications": [
|
|
846
|
-
{
|
|
847
|
-
"
|
|
848
|
-
"consumerVersion": "2.0.0",
|
|
849
|
-
"status": "INCOMPATIBLE",
|
|
850
|
-
"compatibleCount": 1,
|
|
851
|
-
"incompatibleCount": 1
|
|
852
|
-
}
|
|
481
|
+
{ "consumerName": "checkout-ui", "consumerVersion": "2.0.0", "status": "INCOMPATIBLE",
|
|
482
|
+
"compatibleCount": 1, "incompatibleCount": 1 }
|
|
853
483
|
]
|
|
854
484
|
}
|
|
855
485
|
```
|
|
856
486
|
|
|
857
|
-
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
# `bdct capture from-har` — record real traffic, get a consumer contract
|
|
490
|
+
|
|
491
|
+
**The Pact alternative for teams that don't want to adopt a DSL.**
|
|
492
|
+
|
|
493
|
+
`from-har` reads a [HAR file](https://en.wikipedia.org/wiki/HAR_(file_format)) (HTTP Archive — any browser, Cypress, Playwright, k6, Insomnia, or Charles Proxy can export one), filters to your provider's host, infers an OpenAPI 3.0 consumer-contract subset from what your tests actually called, and writes it to a file you can publish with `bdct publish-consumer`.
|
|
494
|
+
|
|
495
|
+
Why this matters: a hand-written consumer subset can be wrong (you forget the `currency` field your code reads, and the provider can remove it without anyone noticing). A HAR recording **captures what your code actually does** — without the Pact DSL, language-agnostic, runs anywhere.
|
|
496
|
+
|
|
497
|
+
### Generate a contract from a recorded test run
|
|
858
498
|
|
|
859
499
|
```bash
|
|
860
|
-
#
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
500
|
+
# Record a HAR (one of many ways)
|
|
501
|
+
# - Chrome DevTools → Network → right-click → "Save all as HAR"
|
|
502
|
+
# - Playwright: page.on('request')... or use BROWSER_TOOLS_HAR
|
|
503
|
+
# - Cypress: cy.intercept(...) + plugins like cypress-har-generator
|
|
504
|
+
# - k6: k6 run --out har=run.har script.js
|
|
864
505
|
|
|
865
|
-
|
|
506
|
+
specshield bdct capture from-har \
|
|
507
|
+
--in tests/checkout-run.har \
|
|
508
|
+
--base-url https://api.acme.com \
|
|
509
|
+
--out contracts/checkout-ui-payment.yaml
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
```
|
|
513
|
+
✔ Wrote contracts/checkout-ui-payment.yaml (2 endpoints, 3 ops from 17/24 entries)
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Options
|
|
517
|
+
|
|
518
|
+
| Flag | Purpose |
|
|
519
|
+
|---|---|
|
|
520
|
+
| `--in <path>` | **Required.** Input HAR file (HTTP Archive 1.2). |
|
|
521
|
+
| `--out <path>` | Output file (default: stdout). |
|
|
522
|
+
| `--base-url <url>` | Keep only entries matching this URL prefix (e.g. `https://api.acme.com` or `https://api.acme.com/v1`). |
|
|
523
|
+
| `--method <verbs>` | Comma-separated methods to include (e.g. `GET,POST`). Default: all. |
|
|
524
|
+
| `--title <title>` | OpenAPI `info.title`. Default: `Captured consumer contract`. |
|
|
525
|
+
| `--version <ver>` | OpenAPI `info.version`. Default: `0.1.0`. |
|
|
526
|
+
| `--format <fmt>` | Output format: `yaml` (default) or `json`. |
|
|
527
|
+
| `--include-non-json` | Keep entries with non-JSON bodies (default: drop them — schemas can't be inferred). |
|
|
528
|
+
|
|
529
|
+
### What you get
|
|
530
|
+
|
|
531
|
+
- **Path templating:** concrete paths like `/users/123/orders/abc-2026` are turned into `/users/{userId}/orders/{orderId}` (the param is named from the preceding noun, not a generic `{id}`).
|
|
532
|
+
- **Per-status schema merging:** if two recorded GETs return slightly different shapes, the emitted schema is the merger — fields seen in EVERY sample stay `required`, fields seen in only SOME become optional, integer + number widens to number.
|
|
533
|
+
- **Format detection:** UUIDs, RFC 3339 date-times, and emails get `format: uuid|date-time|email`.
|
|
534
|
+
- **JSON-only by default:** non-JSON bodies are dropped (schemas can't be inferred from binary/HTML); override with `--include-non-json` for debugging.
|
|
535
|
+
|
|
536
|
+
### Use the captured contract in BDCT
|
|
537
|
+
|
|
538
|
+
```bash
|
|
866
539
|
specshield bdct publish-consumer \
|
|
867
540
|
--org acme-store --consumer checkout-ui \
|
|
868
541
|
--provider payment-service --version 2.0.0 \
|
|
869
|
-
--contract
|
|
542
|
+
--contract contracts/checkout-ui-payment.yaml \
|
|
543
|
+
--format OPENAPI
|
|
544
|
+
```
|
|
870
545
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
# `bdct verify-provider` — does your live provider actually match its spec?
|
|
549
|
+
|
|
550
|
+
**Active spec-vs-production conformance — Dredd-style, in CI.**
|
|
551
|
+
|
|
552
|
+
Most teams trust the provider's OpenAPI as the source of truth and never check whether the running service actually matches it. SpecShield's compatibility engine for BDCT is only as accurate as that trust — so `verify-provider` closes the loop by **firing probes derived from the spec at a running endpoint** (staging, usually) and validating every response body against the spec's schema for its status code.
|
|
553
|
+
|
|
554
|
+
Catches things like: the spec says `status ∈ {paid, pending, refunded}` but the live API sometimes returns `partially_refunded`. Or a field documented as `required` is sometimes missing. Or a `format: uuid` field actually contains a numeric ID.
|
|
555
|
+
|
|
556
|
+
### Safe by default
|
|
557
|
+
|
|
558
|
+
By default `verify-provider` only probes **safe** methods (GET, HEAD, OPTIONS) — it must never side-effect your staging data. Mutating methods are opt-in with `--include-mutating`.
|
|
559
|
+
|
|
560
|
+
### Run it
|
|
561
|
+
|
|
562
|
+
```bash
|
|
563
|
+
specshield bdct verify-provider \
|
|
564
|
+
--spec api/openapi.yaml \
|
|
565
|
+
--base-url https://staging.payments.acme.com
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
```
|
|
569
|
+
Provider conformance — spec vs https://staging.payments.acme.com
|
|
570
|
+
────────────────────────────────────────────────────────────
|
|
571
|
+
PASS GET /health (200)
|
|
572
|
+
FAIL GET /payments/{paymentId} (200)
|
|
573
|
+
/amount: must be number
|
|
574
|
+
PASS GET /orders (200)
|
|
575
|
+
SKIP GET /unconfigured/{thingId}
|
|
576
|
+
unresolved path params (no --path-params or spec example): thingId
|
|
577
|
+
────────────────────────────────────────────────────────────
|
|
578
|
+
2 pass · 1 fail · 0 error · 1 skip (4 probes)
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
Exit codes: `0` = all pass · `1` = at least one fail/error · `2` = config/spec error.
|
|
582
|
+
|
|
583
|
+
### Options
|
|
584
|
+
|
|
585
|
+
| Flag | Purpose |
|
|
586
|
+
|---|---|
|
|
587
|
+
| `--spec <path>` | **Required.** Provider OpenAPI spec (YAML or JSON; `$ref`s are resolved). |
|
|
588
|
+
| `--base-url <url>` | **Required.** Base URL of the running provider (e.g. `https://staging.payments.acme.com`). |
|
|
589
|
+
| `--include-mutating` | Also probe POST/PUT/PATCH/DELETE. **Off by default** — never side-effects staging. |
|
|
590
|
+
| `--path-params <kvList>` | Resolve path params: `paymentId=pay-123,userId=u-7`. Overrides spec examples. Repeatable. |
|
|
591
|
+
| `--header <header>` | Extra request header to send, e.g. `--header "Authorization: Bearer $TOKEN"`. Repeatable. |
|
|
592
|
+
| `--timeout-ms <ms>` | Per-request timeout (default: `8000`). |
|
|
593
|
+
| `--json` | Machine-readable JSON output (for CI parsing). |
|
|
594
|
+
|
|
595
|
+
### Path-parameter resolution
|
|
596
|
+
|
|
597
|
+
For path templates like `/payments/{paymentId}`, the resolution priority is:
|
|
598
|
+
|
|
599
|
+
1. `--path-params paymentId=pay-123` on the CLI (always wins)
|
|
600
|
+
2. The spec's `parameters[].example` for that param
|
|
601
|
+
3. **SKIPPED** with a reason if neither resolves
|
|
602
|
+
|
|
603
|
+
So you can declare examples in the spec once and never repeat them on the CLI:
|
|
604
|
+
|
|
605
|
+
```yaml
|
|
606
|
+
paths:
|
|
607
|
+
/payments/{paymentId}:
|
|
608
|
+
get:
|
|
609
|
+
parameters:
|
|
610
|
+
- name: paymentId
|
|
611
|
+
in: path
|
|
612
|
+
required: true
|
|
613
|
+
schema: { type: string }
|
|
614
|
+
example: pay-123 # ← verify-provider uses this automatically
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### What the validator checks (per response)
|
|
618
|
+
|
|
619
|
+
- **Type / format** — `string`/`integer`/`number`/`boolean`/`array`/`object`, plus `format: uuid|date-time|email|...` (via `ajv-formats`).
|
|
620
|
+
- **Required fields** — flags any `required` field that's missing.
|
|
621
|
+
- **Enums** — flags values outside the documented enum set.
|
|
622
|
+
- **`nullable: true`** — properly allows `null` values (OAS-3.0-isms handled).
|
|
623
|
+
- **Status code coverage** — actual status must match an exact code, a wildcard (`4XX`), or the `default` response. An undocumented status is a FAIL.
|
|
624
|
+
|
|
625
|
+
### Run it from CI
|
|
626
|
+
|
|
627
|
+
```yaml
|
|
628
|
+
- name: Verify production matches spec
|
|
629
|
+
env:
|
|
630
|
+
STAGING_TOKEN: ${{ secrets.STAGING_TOKEN }}
|
|
631
|
+
run: |
|
|
632
|
+
specshield bdct verify-provider \
|
|
633
|
+
--spec api/openapi.yaml \
|
|
634
|
+
--base-url https://staging.payments.acme.com \
|
|
635
|
+
--header "Authorization: Bearer $STAGING_TOKEN" \
|
|
636
|
+
--json > conformance.json
|
|
875
637
|
```
|
|
876
638
|
|
|
877
639
|
---
|
|
878
640
|
|
|
879
|
-
|
|
641
|
+
# CI/CD — GitHub Actions
|
|
880
642
|
|
|
881
|
-
### On Pull Request — Catch breaking changes before merge
|
|
643
|
+
### On Pull Request — Catch breaking spec changes before merge
|
|
882
644
|
|
|
883
645
|
```yaml
|
|
884
646
|
name: API Contract Check
|
|
885
|
-
|
|
886
647
|
on:
|
|
887
648
|
pull_request:
|
|
888
649
|
branches: [main]
|
|
@@ -892,28 +653,22 @@ jobs:
|
|
|
892
653
|
runs-on: ubuntu-latest
|
|
893
654
|
steps:
|
|
894
655
|
- uses: actions/checkout@v4
|
|
895
|
-
with:
|
|
896
|
-
fetch-depth: 0
|
|
656
|
+
with: { fetch-depth: 0 }
|
|
897
657
|
- uses: actions/setup-node@v4
|
|
898
|
-
with:
|
|
899
|
-
node-version: '20'
|
|
658
|
+
with: { node-version: '20' }
|
|
900
659
|
- run: npm install -g specshield
|
|
901
|
-
-
|
|
902
|
-
|
|
903
|
-
- name: Compare specs
|
|
904
|
-
run: specshield compare /tmp/base.yaml api/openapi.yaml --fail-on-breaking
|
|
660
|
+
- run: git show origin/main:api/openapi.yaml > /tmp/base.yaml
|
|
661
|
+
- run: specshield compare /tmp/base.yaml api/openapi.yaml --fail-on-breaking
|
|
905
662
|
```
|
|
906
663
|
|
|
907
|
-
### On Push — Publish provider spec
|
|
664
|
+
### On Push — Publish provider spec + gate the deploy
|
|
908
665
|
|
|
909
666
|
```yaml
|
|
910
|
-
name: BDCT Publish
|
|
911
|
-
|
|
667
|
+
name: BDCT Publish & Deploy Gate
|
|
912
668
|
on:
|
|
913
669
|
push:
|
|
914
670
|
branches: [main]
|
|
915
|
-
paths:
|
|
916
|
-
- 'api/openapi.yaml'
|
|
671
|
+
paths: ['api/openapi.yaml']
|
|
917
672
|
|
|
918
673
|
jobs:
|
|
919
674
|
publish-bdct:
|
|
@@ -921,12 +676,10 @@ jobs:
|
|
|
921
676
|
steps:
|
|
922
677
|
- uses: actions/checkout@v4
|
|
923
678
|
- uses: actions/setup-node@v4
|
|
924
|
-
with:
|
|
925
|
-
node-version: '20'
|
|
679
|
+
with: { node-version: '20' }
|
|
926
680
|
- run: npm install -g specshield
|
|
927
681
|
- name: Publish provider spec
|
|
928
|
-
env:
|
|
929
|
-
SPECSHIELD_API_KEY: ${{ secrets.SPECSHIELD_API_KEY }}
|
|
682
|
+
env: { SPECSHIELD_API_KEY: ${{ secrets.SPECSHIELD_API_KEY }} }
|
|
930
683
|
run: |
|
|
931
684
|
specshield bdct publish-provider \
|
|
932
685
|
--org ${{ vars.SPECSHIELD_ORG }} \
|
|
@@ -934,9 +687,8 @@ jobs:
|
|
|
934
687
|
--version ${{ github.sha }} \
|
|
935
688
|
--spec ./api/openapi.yaml \
|
|
936
689
|
--env production
|
|
937
|
-
- name: Gate
|
|
938
|
-
env:
|
|
939
|
-
SPECSHIELD_API_KEY: ${{ secrets.SPECSHIELD_API_KEY }}
|
|
690
|
+
- name: Gate the deploy
|
|
691
|
+
env: { SPECSHIELD_API_KEY: ${{ secrets.SPECSHIELD_API_KEY }} }
|
|
940
692
|
run: |
|
|
941
693
|
specshield bdct can-i-deploy \
|
|
942
694
|
--org ${{ vars.SPECSHIELD_ORG }} \
|
|
@@ -945,53 +697,201 @@ jobs:
|
|
|
945
697
|
--env production
|
|
946
698
|
```
|
|
947
699
|
|
|
948
|
-
###
|
|
700
|
+
### Nightly — Spec-vs-production conformance
|
|
949
701
|
|
|
950
702
|
```yaml
|
|
951
|
-
name:
|
|
952
|
-
|
|
703
|
+
name: Provider Conformance
|
|
953
704
|
on:
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
paths:
|
|
957
|
-
- 'contracts/bdct/**'
|
|
705
|
+
schedule: [{ cron: '0 7 * * *' }] # daily 07:00 UTC
|
|
706
|
+
workflow_dispatch:
|
|
958
707
|
|
|
959
708
|
jobs:
|
|
960
|
-
|
|
709
|
+
conformance:
|
|
961
710
|
runs-on: ubuntu-latest
|
|
962
711
|
steps:
|
|
963
712
|
- uses: actions/checkout@v4
|
|
964
713
|
- uses: actions/setup-node@v4
|
|
965
|
-
with:
|
|
966
|
-
node-version: '20'
|
|
714
|
+
with: { node-version: '20' }
|
|
967
715
|
- run: npm install -g specshield
|
|
968
|
-
- name:
|
|
969
|
-
env:
|
|
970
|
-
SPECSHIELD_API_KEY: ${{ secrets.SPECSHIELD_API_KEY }}
|
|
716
|
+
- name: Verify production matches its spec
|
|
717
|
+
env: { STAGING_TOKEN: ${{ secrets.STAGING_TOKEN }} }
|
|
971
718
|
run: |
|
|
972
|
-
specshield bdct
|
|
973
|
-
--
|
|
974
|
-
--
|
|
975
|
-
--
|
|
976
|
-
--version ${{ github.ref_name }} \
|
|
977
|
-
--contract ./contracts/bdct/checkout-ui-payment.yaml
|
|
719
|
+
specshield bdct verify-provider \
|
|
720
|
+
--spec api/openapi.yaml \
|
|
721
|
+
--base-url https://staging.payments.acme.com \
|
|
722
|
+
--header "Authorization: Bearer $STAGING_TOKEN"
|
|
978
723
|
```
|
|
979
724
|
|
|
980
725
|
---
|
|
981
726
|
|
|
982
|
-
##
|
|
727
|
+
## vs. Alternatives
|
|
728
|
+
|
|
729
|
+
| | **SpecShield** | **Pact / PactFlow** (SmartBear) | **oasdiff** | **Specmatic** / **Microcks** (OSS) |
|
|
730
|
+
|---|---|---|---|---|
|
|
731
|
+
| OpenAPI-native | ✅ | partial (Pact DSL) | ✅ | ✅ |
|
|
732
|
+
| No broker required | ✅ | ❌ (Pact Broker) | ✅ | ✅ |
|
|
733
|
+
| Bi-directional contract testing | ✅ | ✅ (Pactflow paid) | ❌ | partial |
|
|
734
|
+
| Breaking-change detection | ✅ | ❌ | ✅ | ❌ |
|
|
735
|
+
| `can-i-deploy` gating | ✅ | ✅ (broker) | ❌ | ❌ |
|
|
736
|
+
| **Pact JSON ingest** | ✅ | native | ❌ | ❌ |
|
|
737
|
+
| **HAR → consumer contract capture** | ✅ | ❌ (requires Pact DSL in tests) | ❌ | ❌ |
|
|
738
|
+
| **Spec-vs-production conformance** | ✅ | partial (ReadyAPI / Dredd) | ❌ | ✅ |
|
|
739
|
+
| GitHub App PR checks | ✅ | ❌ | ❌ | ❌ |
|
|
740
|
+
| Hosted dashboard | ✅ | ✅ (paid) | partial | ❌ |
|
|
741
|
+
| CLI-first | ✅ | ❌ | ✅ | partial |
|
|
742
|
+
| Free tier | ✅ | ❌ | ✅ (OSS) | ✅ (OSS) |
|
|
743
|
+
|
|
744
|
+
---
|
|
745
|
+
|
|
746
|
+
## Pricing
|
|
747
|
+
|
|
748
|
+
| Plan | Price | What's included |
|
|
749
|
+
|---|---|---|
|
|
750
|
+
| **Free** | $0 forever | Local compare · `bdct capture from-har` · `bdct verify-provider` · public web diff · 7-day compare history · 1 GitHub App PR check |
|
|
751
|
+
| **Team** | $89/mo ($75 annual) | Everything in Free + consumer registry · enforced `can-i-deploy` gate · audit trail · BDCT compatibility matrix · Slack alerts · team workspace + RBAC · priority email support |
|
|
752
|
+
| **Enterprise** | Talk to us | Everything in Team + SAML SSO · SCIM · on-prem / private-cloud · advanced RBAC + audit-log export · dedicated onboarding + SLA |
|
|
753
|
+
|
|
754
|
+
No credit card for the free plan. **[Get started free →](https://specshield.io)** · For Enterprise: [sales@specshield.io](mailto:sales@specshield.io).
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
|
|
758
|
+
## `specshield init` — first-run setup wizard
|
|
759
|
+
|
|
760
|
+
Run once at the root of your project. The wizard:
|
|
761
|
+
|
|
762
|
+
1. Detects your OpenAPI spec (looks under `api/`, `spec/`, `docs/`, repo root).
|
|
763
|
+
2. Detects your service name (`package.json`, `pyproject.toml`, `pom.xml`, `go.mod`, `Cargo.toml`, or directory name).
|
|
764
|
+
3. Detects your git branch and suggests `production` for `main`/`master`, `staging` otherwise.
|
|
765
|
+
4. Asks whether this project is a provider, a consumer, or both.
|
|
766
|
+
5. Asks for your org key (autocompletes from your account if signed in).
|
|
767
|
+
6. Validates / stores your API key.
|
|
768
|
+
7. Writes **`.specshield.yml`** and (optionally) a starter **`.github/workflows/specshield-bdct.yml`** using [`specshield26/bdct-action@v1`](https://github.com/marketplace/actions/specshield-bdct).
|
|
769
|
+
|
|
770
|
+
```bash
|
|
771
|
+
specshield init
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
### Example `.specshield.yml`
|
|
775
|
+
|
|
776
|
+
```yaml
|
|
777
|
+
schemaVersion: 1
|
|
778
|
+
|
|
779
|
+
failOnBreaking: true
|
|
780
|
+
severity: error
|
|
781
|
+
|
|
782
|
+
bdct:
|
|
783
|
+
org: acme-pay
|
|
784
|
+
environment: staging
|
|
785
|
+
|
|
786
|
+
provider:
|
|
787
|
+
name: payment-service
|
|
788
|
+
spec: api/openapi.yaml
|
|
789
|
+
|
|
790
|
+
# consumer (optional — present when --kind=consumer or --kind=both):
|
|
791
|
+
# consumer:
|
|
792
|
+
# name: checkout-ui
|
|
793
|
+
# provider: payment-service
|
|
794
|
+
# contract: contracts/payment-service.yaml
|
|
795
|
+
# format: OPENAPI
|
|
796
|
+
|
|
797
|
+
github:
|
|
798
|
+
specPath: api/openapi.yaml
|
|
799
|
+
failOnBreaking: true
|
|
800
|
+
commentOnPr: true
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
CLI flags **always** override this file. Paths in the file are resolved relative to the file's own directory, so you can run `specshield bdct …` from any subdirectory.
|
|
804
|
+
|
|
805
|
+
### Non-interactive (scriptable) mode
|
|
806
|
+
|
|
807
|
+
```bash
|
|
808
|
+
# Provider-only project
|
|
809
|
+
specshield init --no-interactive \
|
|
810
|
+
--kind provider --org acme-pay \
|
|
811
|
+
--provider payment-service --spec api/openapi.yaml \
|
|
812
|
+
--env staging --write-workflow
|
|
983
813
|
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
814
|
+
# Consumer-only project
|
|
815
|
+
specshield init --no-interactive \
|
|
816
|
+
--kind consumer --org acme-pay \
|
|
817
|
+
--consumer checkout-ui --consumer-provider payment-service \
|
|
818
|
+
--contract contracts/payment-service.yaml --format OPENAPI \
|
|
819
|
+
--env staging
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
### All `init` flags
|
|
823
|
+
|
|
824
|
+
| Flag | Purpose |
|
|
825
|
+
|---|---|
|
|
826
|
+
| `--no-interactive` | Run without prompts; required fields must come from flags or auto-detection. |
|
|
827
|
+
| `--print` | Detect everything, print the proposed YAML to stdout, write nothing. |
|
|
828
|
+
| `--force` | Skip the overwrite-confirmation if `.specshield.yml` already exists. |
|
|
829
|
+
| `--server <url>` | Use a non-default SpecShield endpoint (self-hosted / staging). |
|
|
830
|
+
| `--kind <kind>` | `provider`, `consumer`, `both`, or `skip`. |
|
|
831
|
+
| `--org <key>` | Organization key. |
|
|
832
|
+
| `--provider <name>` | Provider service name. |
|
|
833
|
+
| `--spec <path>` | Path to the provider OpenAPI spec. |
|
|
834
|
+
| `--consumer <name>` | Consumer service name. |
|
|
835
|
+
| `--consumer-provider <name>` | The provider this consumer talks to. |
|
|
836
|
+
| `--contract <path>` | Path to the consumer contract (OpenAPI or Pact JSON). |
|
|
837
|
+
| `--format <fmt>` | Consumer contract format: `OPENAPI` (default) or `PACT`. |
|
|
838
|
+
| `--env <environment>` | Default environment for BDCT operations. |
|
|
839
|
+
| `--write-workflow` | Also write a starter GitHub Actions workflow. |
|
|
840
|
+
|
|
841
|
+
> **What is _not_ written into `.specshield.yml`:** your API key. It's stored in `~/.specshield/config.json` (set by `specshield login`) or read from `SPECSHIELD_API_KEY` in CI. The project file is committed; never commit a secret into it.
|
|
842
|
+
|
|
843
|
+
---
|
|
844
|
+
|
|
845
|
+
## Login & Authentication
|
|
846
|
+
|
|
847
|
+
**Step 1 — Create your account**
|
|
848
|
+
|
|
849
|
+
Go to [https://specshield.io](https://specshield.io) and sign in with GitHub or Google (30 seconds).
|
|
850
|
+
|
|
851
|
+
**Step 2 — Generate an API key**
|
|
852
|
+
|
|
853
|
+
Dashboard → **API Keys** → **Generate Key** → copy the `ss_` token.
|
|
854
|
+
|
|
855
|
+
**Step 3 — Authenticate the CLI**
|
|
988
856
|
|
|
989
|
-
|
|
857
|
+
```bash
|
|
858
|
+
specshield login --api-key ss_your_token_here
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
```
|
|
862
|
+
✔ Logged in successfully.
|
|
863
|
+
Customer : Your Name
|
|
864
|
+
Plan : FREE
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
The token is stored in `~/.specshield/config.json` — no need to pass it on every command.
|
|
868
|
+
|
|
869
|
+
**Or use an environment variable (recommended for CI):**
|
|
870
|
+
|
|
871
|
+
```bash
|
|
872
|
+
export SPECSHIELD_API_KEY=ss_your_token_here
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
This one env var works for every command — `compare`, `login`, and every `bdct` subcommand all read it.
|
|
876
|
+
|
|
877
|
+
**Token resolution order:**
|
|
878
|
+
- `compare` / `login`: `--api-key` flag → `SPECSHIELD_API_KEY` env var → stored config → `.specshield.yml`
|
|
879
|
+
- `bdct …` subcommands: `--api-token` flag → `SPECSHIELD_API_KEY` env var → stored config
|
|
880
|
+
|
|
881
|
+
> **Why two flag names?** `compare` and `login` were built first and used `--api-key`. The newer `bdct` commands use `--api-token` to keep "key" reserved for the stored-config concept. The env var unifies both.
|
|
882
|
+
|
|
883
|
+
> **`bdct capture from-har` and `bdct verify-provider` don't require auth** — they run entirely locally against files / your own staging URL, and nothing is uploaded.
|
|
884
|
+
|
|
885
|
+
---
|
|
886
|
+
|
|
887
|
+
## Config File
|
|
888
|
+
|
|
889
|
+
Run [`specshield init`](#specshield-init--first-run-setup-wizard) to generate `.specshield.yml`, or hand-write it. Every `specshield …` invocation reads it from the project root (or any parent directory) and uses its values as defaults — CLI flags always win.
|
|
990
890
|
|
|
991
891
|
```yaml
|
|
992
892
|
schemaVersion: 1
|
|
993
893
|
|
|
994
|
-
# Local-compare defaults
|
|
894
|
+
# Local-compare defaults.
|
|
995
895
|
failOnBreaking: true
|
|
996
896
|
severity: error # info | warning | error
|
|
997
897
|
ignore:
|
|
@@ -1002,14 +902,12 @@ remote:
|
|
|
1002
902
|
enabled: false
|
|
1003
903
|
url: https://specshield.io/compare
|
|
1004
904
|
timeout: 10000
|
|
1005
|
-
# apiKey is intentionally NOT set here. Use SPECSHIELD_API_KEY in CI
|
|
1006
|
-
# or `specshield login` locally. Never commit a key to a file.
|
|
1007
905
|
|
|
1008
|
-
# BDCT defaults (used by every `specshield bdct
|
|
906
|
+
# BDCT defaults (used by every `specshield bdct …` subcommand).
|
|
1009
907
|
bdct:
|
|
1010
908
|
org: acme-pay
|
|
1011
909
|
environment: staging
|
|
1012
|
-
# server: https://specshield.io # only
|
|
910
|
+
# server: https://specshield.io # only for self-hosted / staging
|
|
1013
911
|
|
|
1014
912
|
provider:
|
|
1015
913
|
name: payment-service
|
|
@@ -1029,7 +927,7 @@ github:
|
|
|
1029
927
|
commentOnPr: true
|
|
1030
928
|
```
|
|
1031
929
|
|
|
1032
|
-
|
|
930
|
+
With this file, BDCT commands collapse to `--version`:
|
|
1033
931
|
|
|
1034
932
|
```bash
|
|
1035
933
|
specshield bdct publish-provider --version $GITHUB_SHA
|
|
@@ -1090,6 +988,8 @@ specshield bdct <subcommand> [options]
|
|
|
1090
988
|
| `list-providers` | List published provider specs |
|
|
1091
989
|
| `list-consumers` | List published consumer contracts |
|
|
1092
990
|
| `list` | List verification history |
|
|
991
|
+
| **`capture from-har`** | **Turn a recorded HAR file into an OpenAPI consumer contract** |
|
|
992
|
+
| **`verify-provider`** | **Check that a running provider service matches its OpenAPI spec** |
|
|
1093
993
|
|
|
1094
994
|
Every `bdct` subcommand accepts these flags in common:
|
|
1095
995
|
|
|
@@ -1110,8 +1010,10 @@ Per-subcommand flags:
|
|
|
1110
1010
|
| `can-i-deploy` | `--service <name>`, `--version <ver>`, `--env <env>` |
|
|
1111
1011
|
| `matrix` | `--env <env>` |
|
|
1112
1012
|
| `list-providers` | `--provider <name>` (filter) |
|
|
1113
|
-
| `list-consumers` | `--consumer <name
|
|
1013
|
+
| `list-consumers` | `--consumer <name>`, `--provider <name>` (filters) |
|
|
1114
1014
|
| `list` | `--consumer <name>`, `--provider <name>`, `--env <env>`, `--page <n>`, `--size <n>` |
|
|
1015
|
+
| **`capture from-har`** | `--in <path>` *required*, `--out <path>`, `--base-url <url>`, `--method <verbs>`, `--title <s>`, `--version <s>`, `--format yaml\|json`, `--include-non-json` |
|
|
1016
|
+
| **`verify-provider`** | `--spec <path>` *required*, `--base-url <url>` *required*, `--include-mutating`, `--path-params <kv>` (repeatable), `--header <h>` (repeatable), `--timeout-ms <n>`, `--json` |
|
|
1115
1017
|
|
|
1116
1018
|
---
|
|
1117
1019
|
|
|
@@ -1119,8 +1021,8 @@ Per-subcommand flags:
|
|
|
1119
1021
|
|
|
1120
1022
|
| Code | Meaning |
|
|
1121
1023
|
|---|---|
|
|
1122
|
-
| `0` | Clean — no breaking changes / deployable |
|
|
1123
|
-
| `1` | Breaking changes found / not deployable |
|
|
1024
|
+
| `0` | Clean — no breaking changes / deployable / all probes pass |
|
|
1025
|
+
| `1` | Breaking changes found / not deployable / one or more probes failed |
|
|
1124
1026
|
| `2` | Config error, missing token, or runtime error |
|
|
1125
1027
|
|
|
1126
1028
|
---
|
|
@@ -1133,8 +1035,6 @@ MIT © Deepak Satyam
|
|
|
1133
1035
|
|
|
1134
1036
|
## Support
|
|
1135
1037
|
|
|
1136
|
-
Questions or issues?
|
|
1137
|
-
|
|
1138
1038
|
- 📧 [admin@specshield.io](mailto:admin@specshield.io)
|
|
1139
1039
|
- 🐛 [Open an issue on GitHub](https://github.com/specshield26/specshield-cli/issues)
|
|
1140
1040
|
- 🌐 [specshield.io](https://specshield.io)
|