@shipeasy/openapi 2.3.0 → 2.5.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/dist/{chunk-PRN4AEAM.js → chunk-DBTSD3W5.js} +1085 -261
- package/dist/chunk-DBTSD3W5.js.map +1 -0
- package/dist/{chunk-LYNWK55D.js → chunk-RDMD5XQT.js} +171 -1
- package/dist/chunk-RDMD5XQT.js.map +1 -0
- package/dist/{client-DO5HTb_L.d.ts → client-ObcuFHaV.d.ts} +5605 -2734
- package/dist/client.d.ts +1 -1
- package/dist/client.js +47 -1
- package/dist/custom.d.ts +9 -4
- package/dist/custom.js +57 -9
- package/dist/custom.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +48 -2
- package/dist/index.js.map +1 -1
- package/dist/schemas.d.ts +3171 -485
- package/dist/schemas.js +229 -1
- package/openapi.json +13264 -8071
- package/openapi.yaml +5108 -1550
- package/package.json +1 -1
- package/spec/components/errors.yaml +3 -0
- package/spec/components/schemas/alerts.yaml +138 -0
- package/spec/components/schemas/attributes.yaml +53 -3
- package/spec/components/schemas/common.yaml +10 -0
- package/spec/components/schemas/configs.yaml +91 -3
- package/spec/components/schemas/connectors.yaml +5 -1
- package/spec/components/schemas/errors-api.yaml +51 -4
- package/spec/components/schemas/experiments.yaml +347 -87
- package/spec/components/schemas/gates.yaml +350 -277
- package/spec/components/schemas/i18n.yaml +169 -40
- package/spec/components/schemas/killswitches.yaml +36 -0
- package/spec/components/schemas/metrics.yaml +199 -7
- package/spec/components/schemas/ops.yaml +961 -29
- package/spec/components/schemas/projects.yaml +129 -3
- package/spec/openapi.yaml +58 -0
- package/spec/paths/alerts.yaml +184 -0
- package/spec/paths/attributes.yaml +23 -5
- package/spec/paths/configs.yaml +98 -21
- package/spec/paths/errors.yaml +16 -0
- package/spec/paths/experiments.yaml +236 -16
- package/spec/paths/gates.yaml +137 -0
- package/spec/paths/i18n.yaml +290 -6
- package/spec/paths/killswitches.yaml +6 -0
- package/spec/paths/metrics.yaml +186 -0
- package/spec/paths/ops.yaml +382 -0
- package/spec/paths/projects.yaml +60 -0
- package/dist/chunk-LYNWK55D.js.map +0 -1
- package/dist/chunk-PRN4AEAM.js.map +0 -1
package/spec/paths/configs.yaml
CHANGED
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
- id: cfg_01j7wae5h6j7k8l9m0n1p2q3r4
|
|
26
26
|
name: pricing.tiers
|
|
27
27
|
description: Pricing tier definitions consumed by the checkout flow.
|
|
28
|
+
folder: pricing
|
|
29
|
+
creatorEmail: ana@example.com
|
|
30
|
+
createdAt: 2026-05-01T10:12:00.000Z
|
|
28
31
|
schema:
|
|
29
32
|
type: object
|
|
30
33
|
properties:
|
|
@@ -84,7 +87,7 @@
|
|
|
84
87
|
|
|
85
88
|
- **Minimal create** — `name` + `schema`. Initial value defaults to `{}`.
|
|
86
89
|
- **Seeded create** — supply a flat `value` to publish the same object on every env.
|
|
87
|
-
- **Per-env seed** — supply a `{ env: value }` map for
|
|
90
|
+
- **Per-env seed** — supply a `{ env: value }` map under `value`, or pass the env keys `dev`/`staging`/`prod` directly (each overrides `value` for that env and is published at version 1).
|
|
88
91
|
tags:
|
|
89
92
|
- Configs
|
|
90
93
|
parameters:
|
|
@@ -126,8 +129,8 @@
|
|
|
126
129
|
- name: free
|
|
127
130
|
- name: pro
|
|
128
131
|
perEnvSeed:
|
|
129
|
-
summary: Per-env seed
|
|
130
|
-
description: "Pass
|
|
132
|
+
summary: Per-env seed (env keys)
|
|
133
|
+
description: "Pass the env keys directly to seed different initial values per env. Each overrides `value` for that env and is published at version 1."
|
|
131
134
|
value:
|
|
132
135
|
name: pricing.tiers
|
|
133
136
|
schema:
|
|
@@ -137,20 +140,15 @@
|
|
|
137
140
|
type: array
|
|
138
141
|
required:
|
|
139
142
|
- tiers
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
- name: pro
|
|
150
|
-
prod:
|
|
151
|
-
tiers:
|
|
152
|
-
- name: free
|
|
153
|
-
- name: pro
|
|
143
|
+
dev:
|
|
144
|
+
tiers:
|
|
145
|
+
- name: free
|
|
146
|
+
- name: pro
|
|
147
|
+
- name: enterprise
|
|
148
|
+
prod:
|
|
149
|
+
tiers:
|
|
150
|
+
- name: free
|
|
151
|
+
- name: pro
|
|
154
152
|
responses:
|
|
155
153
|
"201":
|
|
156
154
|
description: Create a dynamic config
|
|
@@ -226,6 +224,7 @@
|
|
|
226
224
|
id: cfg_01j7wae5h6j7k8l9m0n1p2q3r4
|
|
227
225
|
name: pricing.tiers
|
|
228
226
|
description: Pricing tier definitions consumed by the checkout flow.
|
|
227
|
+
folder: pricing
|
|
229
228
|
schema:
|
|
230
229
|
type: object
|
|
231
230
|
properties:
|
|
@@ -298,15 +297,13 @@
|
|
|
298
297
|
operationId: updateConfig
|
|
299
298
|
summary: Update a dynamic config
|
|
300
299
|
description: |-
|
|
301
|
-
Partial update. When `value` is supplied it is **republished on every env** (new version per env). When `schema` is supplied it replaces the current schema; every existing value is re-validated.
|
|
302
|
-
|
|
303
|
-
For env-scoped edits, use the draft/publish flow (`PUT /{id}/drafts` then `POST /{id}/publish`) instead.
|
|
300
|
+
Partial update. When `value` is supplied it is **republished on every env** (new version per env). A per-env key (`dev`/`staging`/`prod`) publishes a new version to **only that env**, immediately, overriding `value` for it. When `schema` is supplied it replaces the current schema; every existing value is re-validated.
|
|
304
301
|
|
|
305
302
|
**Use cases**
|
|
306
303
|
|
|
307
304
|
- **Republish flat value** — `{ "value": {…} }` sets the same value on every env.
|
|
305
|
+
- **Publish one env** — `{ "prod": {…} }` publishes a new version to prod only, instantly.
|
|
308
306
|
- **Schema migration** — `{ "schema": {…} }` replaces the schema; existing values are re-validated.
|
|
309
|
-
- **Env-scoped edits** — use `PUT /{id}/drafts` + `POST /{id}/publish` instead of PATCH.
|
|
310
307
|
tags:
|
|
311
308
|
- Configs
|
|
312
309
|
parameters:
|
|
@@ -332,6 +329,15 @@
|
|
|
332
329
|
tiers:
|
|
333
330
|
- name: free
|
|
334
331
|
- name: pro
|
|
332
|
+
prodOnly:
|
|
333
|
+
summary: Per-env — publish prod only
|
|
334
|
+
description: Publishes a new version to prod only, immediately. dev/staging untouched.
|
|
335
|
+
value:
|
|
336
|
+
prod:
|
|
337
|
+
tiers:
|
|
338
|
+
- name: free
|
|
339
|
+
- name: pro
|
|
340
|
+
- name: enterprise
|
|
335
341
|
schemaOnly:
|
|
336
342
|
summary: Schema-only update
|
|
337
343
|
description: Replaces the schema. Existing values must still validate or the update fails.
|
|
@@ -492,6 +498,7 @@
|
|
|
492
498
|
- VALIDATION
|
|
493
499
|
x-cli:
|
|
494
500
|
name: draft
|
|
501
|
+
hidden: true
|
|
495
502
|
positional:
|
|
496
503
|
- id
|
|
497
504
|
delete:
|
|
@@ -551,6 +558,7 @@
|
|
|
551
558
|
- NOT_FOUND
|
|
552
559
|
x-cli:
|
|
553
560
|
name: discard-draft
|
|
561
|
+
hidden: true
|
|
554
562
|
positional:
|
|
555
563
|
- id
|
|
556
564
|
/api/admin/configs/{id}/publish:
|
|
@@ -622,6 +630,7 @@
|
|
|
622
630
|
- VALIDATION
|
|
623
631
|
x-cli:
|
|
624
632
|
name: publish
|
|
633
|
+
hidden: true
|
|
625
634
|
positional:
|
|
626
635
|
- id
|
|
627
636
|
/api/admin/configs/{id}/activity:
|
|
@@ -686,6 +695,74 @@
|
|
|
686
695
|
- NOT_FOUND
|
|
687
696
|
x-cli:
|
|
688
697
|
name: activity
|
|
698
|
+
hidden: true
|
|
699
|
+
positional:
|
|
700
|
+
- id
|
|
701
|
+
/api/admin/configs/{id}/versions:
|
|
702
|
+
get:
|
|
703
|
+
operationId: listConfigVersions
|
|
704
|
+
summary: List config version history
|
|
705
|
+
description: |-
|
|
706
|
+
Returns every published version of the config's value on one env, newest first. The `env` query parameter picks the environment (`dev`, `staging`, or `prod`) and defaults to `prod`; an unknown env returns `400`. The config's JSON Schema is config-level and not versioned — this is value history only.
|
|
707
|
+
|
|
708
|
+
**Use case:** Render the History timeline in the config detail pane (value diff + restore), or audit which value was live on prod at a given version.
|
|
709
|
+
tags:
|
|
710
|
+
- Configs
|
|
711
|
+
parameters:
|
|
712
|
+
- $ref: ../components/parameters.yaml#/ProjectId
|
|
713
|
+
- name: id
|
|
714
|
+
in: path
|
|
715
|
+
required: true
|
|
716
|
+
description: Stable opaque config id (`cfg_…`) or the config's `name`.
|
|
717
|
+
schema:
|
|
718
|
+
$ref: ../components/schemas/common.yaml#/ResourceId
|
|
719
|
+
- name: env
|
|
720
|
+
in: query
|
|
721
|
+
required: false
|
|
722
|
+
description: Environment to list history for (`dev`, `staging`, or `prod`). Defaults to `prod` when omitted.
|
|
723
|
+
schema:
|
|
724
|
+
$ref: ../components/schemas/common.yaml#/Env
|
|
725
|
+
responses:
|
|
726
|
+
"200":
|
|
727
|
+
description: List config version history
|
|
728
|
+
content:
|
|
729
|
+
application/json:
|
|
730
|
+
schema:
|
|
731
|
+
$ref: ../components/schemas/configs.yaml#/ListConfigVersionsResponse
|
|
732
|
+
example:
|
|
733
|
+
- version: 5
|
|
734
|
+
value:
|
|
735
|
+
tiers:
|
|
736
|
+
- name: free
|
|
737
|
+
- name: pro
|
|
738
|
+
publishedAt: 2026-05-09T18:22:11.000Z
|
|
739
|
+
publishedBy: ana@example.com
|
|
740
|
+
- version: 4
|
|
741
|
+
value:
|
|
742
|
+
tiers:
|
|
743
|
+
- name: free
|
|
744
|
+
publishedAt: 2026-05-08T11:05:22.000Z
|
|
745
|
+
publishedBy: bo@example.com
|
|
746
|
+
"400":
|
|
747
|
+
$ref: ../components/responses.yaml#/BadRequest
|
|
748
|
+
"401":
|
|
749
|
+
$ref: ../components/responses.yaml#/Unauthorized
|
|
750
|
+
"403":
|
|
751
|
+
$ref: ../components/responses.yaml#/Forbidden
|
|
752
|
+
"404":
|
|
753
|
+
$ref: ../components/responses.yaml#/NotFound
|
|
754
|
+
"409":
|
|
755
|
+
$ref: ../components/responses.yaml#/Conflict
|
|
756
|
+
"422":
|
|
757
|
+
$ref: ../components/responses.yaml#/UnprocessableEntity
|
|
758
|
+
x-error-codes:
|
|
759
|
+
- BAD_REQUEST
|
|
760
|
+
- UNAUTHORIZED
|
|
761
|
+
- FORBIDDEN
|
|
762
|
+
- NOT_FOUND
|
|
763
|
+
x-cli:
|
|
764
|
+
name: versions
|
|
765
|
+
hidden: true
|
|
689
766
|
positional:
|
|
690
767
|
- id
|
|
691
768
|
/api/admin/configs/{id}/schema:
|
package/spec/paths/errors.yaml
CHANGED
|
@@ -73,6 +73,9 @@
|
|
|
73
73
|
lastSeenAt: 2026-06-28T14:55:31.000Z
|
|
74
74
|
createdAt: 2026-06-20T08:11:02.000Z
|
|
75
75
|
updatedAt: 2026-06-28T14:55:31.000Z
|
|
76
|
+
assigneeId: null
|
|
77
|
+
assigneeConnectorId: null
|
|
78
|
+
assigneeAgent: null
|
|
76
79
|
"400":
|
|
77
80
|
$ref: ../components/responses.yaml#/BadRequest
|
|
78
81
|
"401":
|
|
@@ -142,8 +145,13 @@
|
|
|
142
145
|
lastSeenAt: 2026-06-28T14:55:31.000Z
|
|
143
146
|
createdAt: 2026-06-20T08:11:02.000Z
|
|
144
147
|
updatedAt: 2026-06-28T14:55:31.000Z
|
|
148
|
+
assigneeId: 6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c
|
|
149
|
+
assigneeConnectorId: null
|
|
150
|
+
assigneeAgent: null
|
|
145
151
|
occurrences:
|
|
146
152
|
- id: occ_01j7w7qq0v3k9d2m5rc8t1xh4n
|
|
153
|
+
projectId: e976b15e-2f0d-4c6e-9b1a-3a7c1f2d8e90
|
|
154
|
+
errorId: err_01j7w7m9q4hxbf6npe6s9zr3vc
|
|
147
155
|
message: Cannot read properties of undefined (reading 'id')
|
|
148
156
|
stack: |-
|
|
149
157
|
TypeError: Cannot read properties of undefined (reading 'id')
|
|
@@ -156,6 +164,8 @@
|
|
|
156
164
|
sampleRate: 100
|
|
157
165
|
seenAt: 2026-06-28T14:55:31.000Z
|
|
158
166
|
- id: occ_01j7w7pk8s6e3f9b0zad7y5w2q
|
|
167
|
+
projectId: e976b15e-2f0d-4c6e-9b1a-3a7c1f2d8e90
|
|
168
|
+
errorId: err_01j7w7m9q4hxbf6npe6s9zr3vc
|
|
159
169
|
message: Cannot read properties of undefined (reading 'id')
|
|
160
170
|
stack: |-
|
|
161
171
|
TypeError: Cannot read properties of undefined (reading 'id')
|
|
@@ -257,6 +267,9 @@
|
|
|
257
267
|
lastSeenAt: 2026-06-28T14:55:31.000Z
|
|
258
268
|
createdAt: 2026-06-20T08:11:02.000Z
|
|
259
269
|
updatedAt: 2026-06-28T15:02:10.000Z
|
|
270
|
+
assigneeId: null
|
|
271
|
+
assigneeConnectorId: null
|
|
272
|
+
assigneeAgent: null
|
|
260
273
|
"400":
|
|
261
274
|
$ref: ../components/responses.yaml#/BadRequest
|
|
262
275
|
"401":
|
|
@@ -377,6 +390,9 @@
|
|
|
377
390
|
lastSeenAt: 2026-06-28T14:55:31.000Z
|
|
378
391
|
createdAt: 2026-06-20T08:11:02.000Z
|
|
379
392
|
updatedAt: 2026-06-28T15:02:10.000Z
|
|
393
|
+
assigneeId: null
|
|
394
|
+
assigneeConnectorId: null
|
|
395
|
+
assigneeAgent: null
|
|
380
396
|
"400":
|
|
381
397
|
$ref: ../components/responses.yaml#/BadRequest
|
|
382
398
|
"401":
|
|
@@ -648,21 +648,51 @@
|
|
|
648
648
|
status: running
|
|
649
649
|
results:
|
|
650
650
|
- metric: checkout_completed
|
|
651
|
-
|
|
651
|
+
groupName: control
|
|
652
652
|
ds: 2026-05-09
|
|
653
653
|
n: 12421
|
|
654
654
|
mean: 0.1834
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
655
|
+
variance: 0.1498
|
|
656
|
+
delta: null
|
|
657
|
+
deltaPct: null
|
|
658
|
+
ci95Low: null
|
|
659
|
+
ci95High: null
|
|
660
|
+
ci99Low: null
|
|
661
|
+
ci99High: null
|
|
662
|
+
ciLow: null
|
|
663
|
+
ciHigh: null
|
|
664
|
+
pValue: null
|
|
665
|
+
expectedN: 15000
|
|
666
|
+
realizedMde: null
|
|
667
|
+
srmPValue: 0.82
|
|
668
|
+
srmDetected: 0
|
|
669
|
+
msprtSignificant: null
|
|
670
|
+
msprtLambda: null
|
|
671
|
+
isFinal: 0
|
|
672
|
+
peekWarning: 0
|
|
658
673
|
- metric: checkout_completed
|
|
659
|
-
|
|
674
|
+
groupName: treatment
|
|
660
675
|
ds: 2026-05-09
|
|
661
676
|
n: 12519
|
|
662
677
|
mean: 0.1922
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
678
|
+
variance: 0.1553
|
|
679
|
+
delta: 0.0088
|
|
680
|
+
deltaPct: 4.8
|
|
681
|
+
ci95Low: 0.0015
|
|
682
|
+
ci95High: 0.0161
|
|
683
|
+
ci99Low: -0.0008
|
|
684
|
+
ci99High: 0.0184
|
|
685
|
+
ciLow: 0.0015
|
|
686
|
+
ciHigh: 0.0161
|
|
687
|
+
pValue: 0.018
|
|
688
|
+
expectedN: 15000
|
|
689
|
+
realizedMde: 0.0079
|
|
690
|
+
srmPValue: 0.82
|
|
691
|
+
srmDetected: 0
|
|
692
|
+
msprtSignificant: null
|
|
693
|
+
msprtLambda: null
|
|
694
|
+
isFinal: 0
|
|
695
|
+
peekWarning: 0
|
|
666
696
|
verdict: ship
|
|
667
697
|
"400":
|
|
668
698
|
$ref: ../components/responses.yaml#/BadRequest
|
|
@@ -723,21 +753,51 @@
|
|
|
723
753
|
status: running
|
|
724
754
|
series:
|
|
725
755
|
- metric: checkout_completed
|
|
726
|
-
|
|
756
|
+
groupName: treatment
|
|
727
757
|
ds: 2026-05-08
|
|
728
758
|
n: 11200
|
|
729
759
|
mean: 0.1903
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
760
|
+
variance: 0.1541
|
|
761
|
+
delta: 0.0071
|
|
762
|
+
deltaPct: 3.9
|
|
763
|
+
ci95Low: -0.0004
|
|
764
|
+
ci95High: 0.0146
|
|
765
|
+
ci99Low: -0.0028
|
|
766
|
+
ci99High: 0.017
|
|
767
|
+
ciLow: -0.0004
|
|
768
|
+
ciHigh: 0.0146
|
|
769
|
+
pValue: 0.034
|
|
770
|
+
expectedN: 15000
|
|
771
|
+
realizedMde: 0.0083
|
|
772
|
+
srmPValue: 0.79
|
|
773
|
+
srmDetected: 0
|
|
774
|
+
msprtSignificant: null
|
|
775
|
+
msprtLambda: null
|
|
776
|
+
isFinal: 0
|
|
777
|
+
peekWarning: 0
|
|
733
778
|
- metric: checkout_completed
|
|
734
|
-
|
|
779
|
+
groupName: treatment
|
|
735
780
|
ds: 2026-05-09
|
|
736
781
|
n: 12519
|
|
737
782
|
mean: 0.1922
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
783
|
+
variance: 0.1553
|
|
784
|
+
delta: 0.0088
|
|
785
|
+
deltaPct: 4.8
|
|
786
|
+
ci95Low: 0.0015
|
|
787
|
+
ci95High: 0.0161
|
|
788
|
+
ci99Low: -0.0008
|
|
789
|
+
ci99High: 0.0184
|
|
790
|
+
ciLow: 0.0015
|
|
791
|
+
ciHigh: 0.0161
|
|
792
|
+
pValue: 0.018
|
|
793
|
+
expectedN: 15000
|
|
794
|
+
realizedMde: 0.0079
|
|
795
|
+
srmPValue: 0.82
|
|
796
|
+
srmDetected: 0
|
|
797
|
+
msprtSignificant: null
|
|
798
|
+
msprtLambda: null
|
|
799
|
+
isFinal: 0
|
|
800
|
+
peekWarning: 0
|
|
741
801
|
"400":
|
|
742
802
|
$ref: ../components/responses.yaml#/BadRequest
|
|
743
803
|
"401":
|
|
@@ -759,6 +819,166 @@
|
|
|
759
819
|
name: timeseries
|
|
760
820
|
positional:
|
|
761
821
|
- id
|
|
822
|
+
/api/admin/experiments/{id}/readouts:
|
|
823
|
+
post:
|
|
824
|
+
operationId: createExperimentReadout
|
|
825
|
+
summary: Mint a readout snapshot
|
|
826
|
+
description: |-
|
|
827
|
+
Freezes the current results view into an immutable, dated readout snapshot — verdict, headline, per-metric numbers, the caveat list with its acknowledgment state, enrollment, and a hash of the assignment-relevant config. Ship/stop flows mint one automatically; "Share readout" mints one on demand. Snapshots are never updated after insert.
|
|
828
|
+
|
|
829
|
+
Pass `requireAllAcknowledged: true` to enforce ship gating server-side — returns `422` while any open caveat is not listed in `acknowledgedCaveatIds`.
|
|
830
|
+
|
|
831
|
+
**Use case:** Capture "what the data said when we decided" before shipping or stopping, so the decision stays auditable even after results move.
|
|
832
|
+
tags:
|
|
833
|
+
- Experiments
|
|
834
|
+
parameters:
|
|
835
|
+
- $ref: ../components/parameters.yaml#/ProjectId
|
|
836
|
+
- name: id
|
|
837
|
+
in: path
|
|
838
|
+
required: true
|
|
839
|
+
description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
|
|
840
|
+
schema:
|
|
841
|
+
$ref: ../components/schemas/common.yaml#/ResourceId
|
|
842
|
+
requestBody:
|
|
843
|
+
required: true
|
|
844
|
+
content:
|
|
845
|
+
application/json:
|
|
846
|
+
schema:
|
|
847
|
+
$ref: ../components/schemas/experiments.yaml#/CreateExperimentReadoutRequest
|
|
848
|
+
examples:
|
|
849
|
+
manual:
|
|
850
|
+
summary: Manual — "Share readout"
|
|
851
|
+
description: Snapshot the current results view on demand.
|
|
852
|
+
value:
|
|
853
|
+
kind: manual
|
|
854
|
+
shipGated:
|
|
855
|
+
summary: Ship — with caveat gating
|
|
856
|
+
description: Mint a ship readout, acknowledging the open caveats; fails with `422` if any open caveat is missing from the list.
|
|
857
|
+
value:
|
|
858
|
+
kind: ship
|
|
859
|
+
acknowledgedCaveatIds:
|
|
860
|
+
- srm
|
|
861
|
+
- min_runtime
|
|
862
|
+
requireAllAcknowledged: true
|
|
863
|
+
responses:
|
|
864
|
+
"200":
|
|
865
|
+
description: Mint a readout snapshot
|
|
866
|
+
content:
|
|
867
|
+
application/json:
|
|
868
|
+
schema:
|
|
869
|
+
$ref: ../components/schemas/experiments.yaml#/CreateExperimentReadoutResponse
|
|
870
|
+
example:
|
|
871
|
+
id: 5f0c1f2d-8e90-4c6e-9b1a-3a7c1f2d8e90
|
|
872
|
+
links:
|
|
873
|
+
GetExperimentReadout:
|
|
874
|
+
operationId: getExperimentReadout
|
|
875
|
+
parameters: { readoutId: $response.body#/id }
|
|
876
|
+
"400":
|
|
877
|
+
$ref: ../components/responses.yaml#/BadRequest
|
|
878
|
+
"401":
|
|
879
|
+
$ref: ../components/responses.yaml#/Unauthorized
|
|
880
|
+
"403":
|
|
881
|
+
$ref: ../components/responses.yaml#/Forbidden
|
|
882
|
+
"404":
|
|
883
|
+
$ref: ../components/responses.yaml#/NotFound
|
|
884
|
+
"409":
|
|
885
|
+
$ref: ../components/responses.yaml#/Conflict
|
|
886
|
+
"422":
|
|
887
|
+
$ref: ../components/responses.yaml#/UnprocessableEntity
|
|
888
|
+
x-error-codes:
|
|
889
|
+
- BAD_REQUEST
|
|
890
|
+
- UNAUTHORIZED
|
|
891
|
+
- FORBIDDEN
|
|
892
|
+
- NOT_FOUND
|
|
893
|
+
- VALIDATION
|
|
894
|
+
x-cli:
|
|
895
|
+
name: readout-create
|
|
896
|
+
positional:
|
|
897
|
+
- id
|
|
898
|
+
/api/admin/experiments/{id}/readouts/{readoutId}:
|
|
899
|
+
get:
|
|
900
|
+
operationId: getExperimentReadout
|
|
901
|
+
summary: Get a readout snapshot
|
|
902
|
+
description: |-
|
|
903
|
+
Returns one immutable readout snapshot — the frozen results view (verdict, headline, per-metric numbers, caveats, enrollment) captured when it was minted, plus the `configHash` that tells you whether it is still comparable to the live view.
|
|
904
|
+
|
|
905
|
+
**Use case:** Render a shared, dated readout exactly as it looked at decision time.
|
|
906
|
+
tags:
|
|
907
|
+
- Experiments
|
|
908
|
+
parameters:
|
|
909
|
+
- $ref: ../components/parameters.yaml#/ProjectId
|
|
910
|
+
- name: id
|
|
911
|
+
in: path
|
|
912
|
+
required: true
|
|
913
|
+
description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
|
|
914
|
+
schema:
|
|
915
|
+
$ref: ../components/schemas/common.yaml#/ResourceId
|
|
916
|
+
- name: readoutId
|
|
917
|
+
in: path
|
|
918
|
+
required: true
|
|
919
|
+
description: Readout snapshot id, as returned by `createExperimentReadout`.
|
|
920
|
+
schema:
|
|
921
|
+
$ref: ../components/schemas/common.yaml#/ResourceId
|
|
922
|
+
responses:
|
|
923
|
+
"200":
|
|
924
|
+
description: Get a readout snapshot
|
|
925
|
+
content:
|
|
926
|
+
application/json:
|
|
927
|
+
schema:
|
|
928
|
+
$ref: ../components/schemas/experiments.yaml#/GetExperimentReadoutResponse
|
|
929
|
+
example:
|
|
930
|
+
id: 5f0c1f2d-8e90-4c6e-9b1a-3a7c1f2d8e90
|
|
931
|
+
experimentId: exp_01j7wb12c3d4e5f6g7h8j9k0l1
|
|
932
|
+
experimentName: checkout_button_color
|
|
933
|
+
kind: ship
|
|
934
|
+
createdBy: pm@example.com
|
|
935
|
+
createdAt: 2026-05-09T18:22:11.000Z
|
|
936
|
+
verdict: ship
|
|
937
|
+
title: Treatment wins on checkout conversion
|
|
938
|
+
why: Goal metric significant with guardrails flat after 8 days.
|
|
939
|
+
configHash: 9c1f4f1f2c0c4a5fa1c2b6d3e7c8e3a19c1f4f1f2c0c4a5fa1c2b6d3e7c8e3a1
|
|
940
|
+
metricsJson:
|
|
941
|
+
- name: checkout_completed
|
|
942
|
+
role: goal
|
|
943
|
+
delta: 0.0088
|
|
944
|
+
deltaPct: 4.8
|
|
945
|
+
ci: [0.0015, 0.0161]
|
|
946
|
+
p: 0.018
|
|
947
|
+
sig: true
|
|
948
|
+
caveatsJson:
|
|
949
|
+
- id: min_runtime
|
|
950
|
+
severity: warn
|
|
951
|
+
text: Below the 14-day minimum runtime.
|
|
952
|
+
acknowledged: true
|
|
953
|
+
usersJson:
|
|
954
|
+
groups:
|
|
955
|
+
- name: control
|
|
956
|
+
n: 12421
|
|
957
|
+
- name: treatment
|
|
958
|
+
n: 12519
|
|
959
|
+
days: 8
|
|
960
|
+
"400":
|
|
961
|
+
$ref: ../components/responses.yaml#/BadRequest
|
|
962
|
+
"401":
|
|
963
|
+
$ref: ../components/responses.yaml#/Unauthorized
|
|
964
|
+
"403":
|
|
965
|
+
$ref: ../components/responses.yaml#/Forbidden
|
|
966
|
+
"404":
|
|
967
|
+
$ref: ../components/responses.yaml#/NotFound
|
|
968
|
+
"409":
|
|
969
|
+
$ref: ../components/responses.yaml#/Conflict
|
|
970
|
+
"422":
|
|
971
|
+
$ref: ../components/responses.yaml#/UnprocessableEntity
|
|
972
|
+
x-error-codes:
|
|
973
|
+
- BAD_REQUEST
|
|
974
|
+
- UNAUTHORIZED
|
|
975
|
+
- FORBIDDEN
|
|
976
|
+
- NOT_FOUND
|
|
977
|
+
x-cli:
|
|
978
|
+
name: readout-get
|
|
979
|
+
positional:
|
|
980
|
+
- id
|
|
981
|
+
- readoutId
|
|
762
982
|
/api/admin/experiments/{id}/reanalyze:
|
|
763
983
|
post:
|
|
764
984
|
operationId: reanalyzeExperiment
|
package/spec/paths/gates.yaml
CHANGED
|
@@ -43,6 +43,10 @@
|
|
|
43
43
|
groupName: growth
|
|
44
44
|
ownerEmail: ana@example.com
|
|
45
45
|
stack: null
|
|
46
|
+
creatorEmail: ana@example.com
|
|
47
|
+
updaterEmail: bo@example.com
|
|
48
|
+
version: 4
|
|
49
|
+
createdAt: 2026-05-01T10:12:00.000Z
|
|
46
50
|
updatedAt: 2026-05-09T16:01:22.000Z
|
|
47
51
|
next_cursor: null
|
|
48
52
|
"400":
|
|
@@ -201,6 +205,76 @@
|
|
|
201
205
|
positional:
|
|
202
206
|
- name
|
|
203
207
|
/api/admin/gates/{id}:
|
|
208
|
+
get:
|
|
209
|
+
operationId: getGate
|
|
210
|
+
summary: Get one gate
|
|
211
|
+
description: |-
|
|
212
|
+
Returns the full gate row — including the gatekeeper `stack`, resolved creator/last-editor emails, and the edit `version` — for one gate, addressed by id or `name`.
|
|
213
|
+
|
|
214
|
+
**Use case:** Inspect a single gate's current rollout, rules, and stack before editing it, without paging through the whole list.
|
|
215
|
+
tags:
|
|
216
|
+
- Flags
|
|
217
|
+
parameters:
|
|
218
|
+
- $ref: ../components/parameters.yaml#/ProjectId
|
|
219
|
+
- name: id
|
|
220
|
+
in: path
|
|
221
|
+
required: true
|
|
222
|
+
description: Stable opaque gate id (`gat_…`) or the gate's `name`.
|
|
223
|
+
schema:
|
|
224
|
+
$ref: ../components/schemas/common.yaml#/ResourceId
|
|
225
|
+
responses:
|
|
226
|
+
"200":
|
|
227
|
+
description: Get one gate
|
|
228
|
+
content:
|
|
229
|
+
application/json:
|
|
230
|
+
schema:
|
|
231
|
+
$ref: ../components/schemas/gates.yaml#/GetGateResponse
|
|
232
|
+
example:
|
|
233
|
+
id: gat_01j7w7m9q4hxbf6npe6s9zr3vc
|
|
234
|
+
name: checkout_v2
|
|
235
|
+
enabled: 1
|
|
236
|
+
type: targeting
|
|
237
|
+
rolloutPct: 5000
|
|
238
|
+
rules:
|
|
239
|
+
- attr: country
|
|
240
|
+
op: in
|
|
241
|
+
value:
|
|
242
|
+
- US
|
|
243
|
+
- CA
|
|
244
|
+
- GB
|
|
245
|
+
salt: 9c1f4f1f2c0c4a5fa1c2b6d3e7c8e3a1
|
|
246
|
+
title: Checkout v2
|
|
247
|
+
description: New checkout flow. Pro users in US/CA/GB only.
|
|
248
|
+
folder: checkout
|
|
249
|
+
groupName: growth
|
|
250
|
+
ownerEmail: ana@example.com
|
|
251
|
+
stack: null
|
|
252
|
+
creatorEmail: ana@example.com
|
|
253
|
+
updaterEmail: bo@example.com
|
|
254
|
+
version: 4
|
|
255
|
+
createdAt: 2026-05-01T10:12:00.000Z
|
|
256
|
+
updatedAt: 2026-05-09T16:01:22.000Z
|
|
257
|
+
"400":
|
|
258
|
+
$ref: ../components/responses.yaml#/BadRequest
|
|
259
|
+
"401":
|
|
260
|
+
$ref: ../components/responses.yaml#/Unauthorized
|
|
261
|
+
"403":
|
|
262
|
+
$ref: ../components/responses.yaml#/Forbidden
|
|
263
|
+
"404":
|
|
264
|
+
$ref: ../components/responses.yaml#/NotFound
|
|
265
|
+
"409":
|
|
266
|
+
$ref: ../components/responses.yaml#/Conflict
|
|
267
|
+
"422":
|
|
268
|
+
$ref: ../components/responses.yaml#/UnprocessableEntity
|
|
269
|
+
x-error-codes:
|
|
270
|
+
- BAD_REQUEST
|
|
271
|
+
- UNAUTHORIZED
|
|
272
|
+
- FORBIDDEN
|
|
273
|
+
- NOT_FOUND
|
|
274
|
+
x-cli:
|
|
275
|
+
name: get
|
|
276
|
+
positional:
|
|
277
|
+
- id
|
|
204
278
|
patch:
|
|
205
279
|
operationId: updateGate
|
|
206
280
|
summary: Update a feature gate
|
|
@@ -464,3 +538,66 @@
|
|
|
464
538
|
name: disable
|
|
465
539
|
positional:
|
|
466
540
|
- id
|
|
541
|
+
/api/admin/gates/{id}/activity:
|
|
542
|
+
get:
|
|
543
|
+
operationId: listGateActivity
|
|
544
|
+
summary: List gate activity
|
|
545
|
+
description: |-
|
|
546
|
+
Returns recent audit rows for one gate (create, update, enable, disable, delete) ordered newest first. Use the `limit` query parameter to cap the result (1–100, default 20).
|
|
547
|
+
|
|
548
|
+
**Use case:** Render the activity feed in the gate detail panel or answer "who ramped this gate, and when?" during an incident review.
|
|
549
|
+
tags:
|
|
550
|
+
- Flags
|
|
551
|
+
parameters:
|
|
552
|
+
- $ref: ../components/parameters.yaml#/ProjectId
|
|
553
|
+
- name: id
|
|
554
|
+
in: path
|
|
555
|
+
required: true
|
|
556
|
+
description: Stable opaque gate id (`gat_…`) or the gate's `name`.
|
|
557
|
+
schema:
|
|
558
|
+
$ref: ../components/schemas/common.yaml#/ResourceId
|
|
559
|
+
- name: limit
|
|
560
|
+
in: query
|
|
561
|
+
required: false
|
|
562
|
+
description: Max rows to return (1–100). Defaults to 20.
|
|
563
|
+
schema:
|
|
564
|
+
default: 20
|
|
565
|
+
type: integer
|
|
566
|
+
minimum: 1
|
|
567
|
+
maximum: 100
|
|
568
|
+
responses:
|
|
569
|
+
"200":
|
|
570
|
+
description: List gate activity
|
|
571
|
+
content:
|
|
572
|
+
application/json:
|
|
573
|
+
schema:
|
|
574
|
+
$ref: ../components/schemas/gates.yaml#/ListGateActivityResponse
|
|
575
|
+
example:
|
|
576
|
+
- id: act_01j7waf01a2b3c4d5e6f7g8h9i
|
|
577
|
+
action: gate.update
|
|
578
|
+
actorEmail: ana@example.com
|
|
579
|
+
actorType: user
|
|
580
|
+
payload:
|
|
581
|
+
rollout_pct: 5000
|
|
582
|
+
createdAt: 2026-05-09T16:01:22.000Z
|
|
583
|
+
"400":
|
|
584
|
+
$ref: ../components/responses.yaml#/BadRequest
|
|
585
|
+
"401":
|
|
586
|
+
$ref: ../components/responses.yaml#/Unauthorized
|
|
587
|
+
"403":
|
|
588
|
+
$ref: ../components/responses.yaml#/Forbidden
|
|
589
|
+
"404":
|
|
590
|
+
$ref: ../components/responses.yaml#/NotFound
|
|
591
|
+
"409":
|
|
592
|
+
$ref: ../components/responses.yaml#/Conflict
|
|
593
|
+
"422":
|
|
594
|
+
$ref: ../components/responses.yaml#/UnprocessableEntity
|
|
595
|
+
x-error-codes:
|
|
596
|
+
- BAD_REQUEST
|
|
597
|
+
- UNAUTHORIZED
|
|
598
|
+
- FORBIDDEN
|
|
599
|
+
- NOT_FOUND
|
|
600
|
+
x-cli:
|
|
601
|
+
name: activity
|
|
602
|
+
positional:
|
|
603
|
+
- id
|