@shipeasy/openapi 3.1.0 → 3.3.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/README.md +1 -1
- package/dist/{chunk-V4ZESAIF.js → chunk-75Z4SQOM.js} +141 -1
- package/dist/chunk-75Z4SQOM.js.map +1 -0
- package/dist/{chunk-UV333BIK.js → chunk-ZYK74ZIW.js} +569 -119
- package/dist/chunk-ZYK74ZIW.js.map +1 -0
- package/dist/{client-yqGYju-M.d.ts → client-DAGqRpF1.d.ts} +2209 -401
- package/dist/client.d.ts +1 -1
- package/dist/client.js +33 -1
- package/dist/custom.d.ts +5 -5
- package/dist/custom.js +128 -84
- package/dist/custom.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +34 -2
- package/dist/index.js.map +1 -1
- package/dist/schemas.d.ts +2007 -891
- package/dist/schemas.js +179 -1
- package/openapi-sdk.json +1769 -0
- package/openapi.json +5861 -2597
- package/openapi.yaml +2739 -452
- package/package.json +6 -4
- package/spec/components/responses.yaml +39 -0
- package/spec/components/schemas/alert-rules.yaml +405 -7
- package/spec/components/schemas/alerts.yaml +9 -7
- package/spec/components/schemas/common.yaml +2 -2
- package/spec/components/schemas/connectors.yaml +69 -6
- package/spec/components/schemas/events.yaml +20 -9
- package/spec/components/schemas/gates.yaml +87 -0
- package/spec/components/schemas/keys.yaml +32 -2
- package/spec/components/schemas/killswitches.yaml +64 -0
- package/spec/components/schemas/metrics.yaml +131 -251
- package/spec/components/schemas/ops.yaml +555 -22
- package/spec/components/schemas/projects.yaml +18 -0
- package/spec/components/schemas/tags.yaml +91 -0
- package/spec/openapi-sdk.yaml +86 -0
- package/spec/openapi.yaml +61 -0
- package/spec/paths/alerts.yaml +5 -3
- package/spec/paths/gates.yaml +282 -0
- package/spec/paths/i18n.yaml +2 -1
- package/spec/paths/keys.yaml +79 -0
- package/spec/paths/killswitches.yaml +96 -0
- package/spec/paths/metrics.yaml +26 -17
- package/spec/paths/ops.yaml +566 -10
- package/spec/paths/tags.yaml +270 -0
- package/dist/chunk-UV333BIK.js.map +0 -1
- package/dist/chunk-V4ZESAIF.js.map +0 -1
package/openapi.yaml
CHANGED
|
@@ -216,6 +216,24 @@ tags:
|
|
|
216
216
|
the AI-write seam the cockpit's detail panel renders: `list` reads what a
|
|
217
217
|
previous run found, `create` appends a new record, and `update` fills in the
|
|
218
218
|
`working` run record you were handed (findings, PR, confidence) as you work.
|
|
219
|
+
- name: Questions
|
|
220
|
+
parent: Ops
|
|
221
|
+
description: |-
|
|
222
|
+
Structured questions an agent asks the team about a queue item — the
|
|
223
|
+
`AskUserQuestion` shape: a short `header`, the `question`, 2–4 `options`
|
|
224
|
+
(label + description), and `multiSelect` for checkboxes instead of radios.
|
|
225
|
+
Every question also accepts a free-text "Other" answer. Open questions sit
|
|
226
|
+
at the very top of the item's detail panel and mark the row in the queue.
|
|
227
|
+
|
|
228
|
+
**Asking.** `ask` posts 1–4 questions at once. Several agents (or several
|
|
229
|
+
runs) may have questions open on the same item at the same time.
|
|
230
|
+
|
|
231
|
+
**Getting the answer back.** `delivery: resume` (the default for a run
|
|
232
|
+
launched through a trigger connector) re-fires that same agent on the
|
|
233
|
+
item once every question its run asked is answered, continuing the same
|
|
234
|
+
run record with the answers in the prompt. `delivery: poll` (the default
|
|
235
|
+
for a live, connector-less session such as Claude Code in a terminal)
|
|
236
|
+
fires nothing — call `list` until the status reads `completed`.
|
|
219
237
|
- name: Projects
|
|
220
238
|
description: |-
|
|
221
239
|
Projects: the account-level container every other resource is scoped to.
|
|
@@ -258,6 +276,19 @@ tags:
|
|
|
258
276
|
Continue) schedule on their own surface — typically a GitHub Actions
|
|
259
277
|
`schedule:` cron running the platform's headless CLI with the shared
|
|
260
278
|
trigger prompt.
|
|
279
|
+
- name: Tags
|
|
280
|
+
description: |-
|
|
281
|
+
Tags: free-form, project-scoped labels any item can carry — queue items
|
|
282
|
+
(bugs, feature requests, error/alert tickets), flags, configs, kill
|
|
283
|
+
switches, metrics, tracked errors, alert rules, and experiments all share
|
|
284
|
+
one tag roster.
|
|
285
|
+
|
|
286
|
+
**Identity.** A tag is its name, unique case-insensitively per project. A
|
|
287
|
+
tag is born the first time it's attached — there is no separate create.
|
|
288
|
+
|
|
289
|
+
**Addressing.** An item is named by `entityType` + its handle (an ops
|
|
290
|
+
item's number, a resource's name, or any id). `set` replaces the full tag
|
|
291
|
+
set; `update` adds/removes names incrementally.
|
|
261
292
|
- name: Connectors
|
|
262
293
|
description: |-
|
|
263
294
|
Outbound integrations: the per-project destinations feedback + trigger
|
|
@@ -877,6 +908,288 @@ paths:
|
|
|
877
908
|
name: activity
|
|
878
909
|
positional:
|
|
879
910
|
- id
|
|
911
|
+
/api/admin/gates/{id}/whitelist:
|
|
912
|
+
get:
|
|
913
|
+
operationId: getGateWhitelist
|
|
914
|
+
summary: Read a gate's whitelist
|
|
915
|
+
description: |-
|
|
916
|
+
Returns the gate's whitelist — the always-first allowlist that admits the listed identities before any targeting rule or percentage rollout is evaluated.
|
|
917
|
+
|
|
918
|
+
A gate with no whitelist returns `entries: []` (and the default `attr`), never a 404 — so a caller can read-then-write without special-casing the empty gate.
|
|
919
|
+
|
|
920
|
+
**Use case:** Check whether an account is already let through before adding it.
|
|
921
|
+
tags:
|
|
922
|
+
- Flags
|
|
923
|
+
parameters:
|
|
924
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
925
|
+
- name: id
|
|
926
|
+
in: path
|
|
927
|
+
required: true
|
|
928
|
+
description: Stable opaque gate id (`gate_…`) or the gate's `name`.
|
|
929
|
+
schema:
|
|
930
|
+
$ref: '#/components/schemas/ResourceId'
|
|
931
|
+
responses:
|
|
932
|
+
'200':
|
|
933
|
+
description: Read a gate's whitelist
|
|
934
|
+
content:
|
|
935
|
+
application/json:
|
|
936
|
+
schema:
|
|
937
|
+
$ref: '#/components/schemas/GateWhitelist'
|
|
938
|
+
example:
|
|
939
|
+
id: gate_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
940
|
+
name: new_checkout
|
|
941
|
+
attr: email
|
|
942
|
+
entries:
|
|
943
|
+
- alice@acme.dev
|
|
944
|
+
- bob@acme.dev
|
|
945
|
+
'400':
|
|
946
|
+
$ref: '#/components/responses/BadRequest'
|
|
947
|
+
'401':
|
|
948
|
+
$ref: '#/components/responses/Unauthorized'
|
|
949
|
+
'403':
|
|
950
|
+
$ref: '#/components/responses/Forbidden'
|
|
951
|
+
'404':
|
|
952
|
+
$ref: '#/components/responses/NotFound'
|
|
953
|
+
'409':
|
|
954
|
+
$ref: '#/components/responses/Conflict'
|
|
955
|
+
'422':
|
|
956
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
957
|
+
x-error-codes:
|
|
958
|
+
- BAD_REQUEST
|
|
959
|
+
- UNAUTHORIZED
|
|
960
|
+
- FORBIDDEN
|
|
961
|
+
- NOT_FOUND
|
|
962
|
+
x-cli:
|
|
963
|
+
name: whitelist
|
|
964
|
+
positional:
|
|
965
|
+
- id
|
|
966
|
+
put:
|
|
967
|
+
operationId: setGateWhitelist
|
|
968
|
+
summary: Replace a gate's whitelist
|
|
969
|
+
description: |-
|
|
970
|
+
Replaces the gate's whole whitelist with `entries`, creating the block if the gate didn't have one. Idempotent — the same call twice leaves the same list.
|
|
971
|
+
|
|
972
|
+
This is the only whitelist call that can switch `attr` (`email` ⇄ `user_id`) or clear the block: `entries: []` removes the whitelist from the gate entirely.
|
|
973
|
+
|
|
974
|
+
**Use cases**
|
|
975
|
+
|
|
976
|
+
- **Pin an exact list** — `{ "entries": ["alice@acme.dev", "bob@acme.dev"] }`.
|
|
977
|
+
- **Switch to user ids** — `{ "attr": "user_id", "entries": ["usr_123"] }`.
|
|
978
|
+
- **Drop the whitelist** — `{ "entries": [] }`.
|
|
979
|
+
tags:
|
|
980
|
+
- Flags
|
|
981
|
+
parameters:
|
|
982
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
983
|
+
- name: id
|
|
984
|
+
in: path
|
|
985
|
+
required: true
|
|
986
|
+
description: Stable opaque gate id (`gate_…`) or the gate's `name`.
|
|
987
|
+
schema:
|
|
988
|
+
$ref: '#/components/schemas/ResourceId'
|
|
989
|
+
requestBody:
|
|
990
|
+
required: true
|
|
991
|
+
content:
|
|
992
|
+
application/json:
|
|
993
|
+
schema:
|
|
994
|
+
$ref: '#/components/schemas/SetGateWhitelistRequest'
|
|
995
|
+
examples:
|
|
996
|
+
pinList:
|
|
997
|
+
summary: Pin an exact list of emails
|
|
998
|
+
value:
|
|
999
|
+
entries:
|
|
1000
|
+
- alice@acme.dev
|
|
1001
|
+
- bob@acme.dev
|
|
1002
|
+
switchToUserIds:
|
|
1003
|
+
summary: Re-key the whitelist onto user ids
|
|
1004
|
+
description: Switching `attr` replaces the entries wholesale — the old emails are not translated.
|
|
1005
|
+
value:
|
|
1006
|
+
attr: user_id
|
|
1007
|
+
entries:
|
|
1008
|
+
- usr_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
1009
|
+
clear:
|
|
1010
|
+
summary: Remove the whitelist
|
|
1011
|
+
description: An empty list drops the pinned block from the gate's stack.
|
|
1012
|
+
value:
|
|
1013
|
+
entries: []
|
|
1014
|
+
responses:
|
|
1015
|
+
'200':
|
|
1016
|
+
description: Replace a gate's whitelist
|
|
1017
|
+
content:
|
|
1018
|
+
application/json:
|
|
1019
|
+
schema:
|
|
1020
|
+
$ref: '#/components/schemas/GateWhitelist'
|
|
1021
|
+
example:
|
|
1022
|
+
id: gate_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
1023
|
+
name: new_checkout
|
|
1024
|
+
attr: email
|
|
1025
|
+
entries:
|
|
1026
|
+
- alice@acme.dev
|
|
1027
|
+
- bob@acme.dev
|
|
1028
|
+
'400':
|
|
1029
|
+
$ref: '#/components/responses/BadRequest'
|
|
1030
|
+
'401':
|
|
1031
|
+
$ref: '#/components/responses/Unauthorized'
|
|
1032
|
+
'403':
|
|
1033
|
+
$ref: '#/components/responses/Forbidden'
|
|
1034
|
+
'404':
|
|
1035
|
+
$ref: '#/components/responses/NotFound'
|
|
1036
|
+
'409':
|
|
1037
|
+
$ref: '#/components/responses/Conflict'
|
|
1038
|
+
'422':
|
|
1039
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
1040
|
+
x-error-codes:
|
|
1041
|
+
- BAD_REQUEST
|
|
1042
|
+
- UNAUTHORIZED
|
|
1043
|
+
- FORBIDDEN
|
|
1044
|
+
- NOT_FOUND
|
|
1045
|
+
- VALIDATION
|
|
1046
|
+
x-cli:
|
|
1047
|
+
name: whitelist-set
|
|
1048
|
+
positional:
|
|
1049
|
+
- id
|
|
1050
|
+
post:
|
|
1051
|
+
operationId: addToGateWhitelist
|
|
1052
|
+
summary: Add entries to a gate's whitelist
|
|
1053
|
+
description: |-
|
|
1054
|
+
Adds identities to the gate's whitelist, creating the block if the gate doesn't have one yet. Entries already on the list are skipped, so the call is idempotent and safe to retry.
|
|
1055
|
+
|
|
1056
|
+
Adding to a gate that already has a whitelist keyed on the other attribute is rejected (409) rather than silently re-keying the entries already there — use `PUT` to switch `attr` deliberately.
|
|
1057
|
+
|
|
1058
|
+
**Use case:** Let one more customer into a private beta without reading the current list first.
|
|
1059
|
+
tags:
|
|
1060
|
+
- Flags
|
|
1061
|
+
parameters:
|
|
1062
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
1063
|
+
- name: id
|
|
1064
|
+
in: path
|
|
1065
|
+
required: true
|
|
1066
|
+
description: Stable opaque gate id (`gate_…`) or the gate's `name`.
|
|
1067
|
+
schema:
|
|
1068
|
+
$ref: '#/components/schemas/ResourceId'
|
|
1069
|
+
requestBody:
|
|
1070
|
+
required: true
|
|
1071
|
+
content:
|
|
1072
|
+
application/json:
|
|
1073
|
+
schema:
|
|
1074
|
+
$ref: '#/components/schemas/AddToGateWhitelistRequest'
|
|
1075
|
+
examples:
|
|
1076
|
+
addOne:
|
|
1077
|
+
summary: Admit one more email
|
|
1078
|
+
value:
|
|
1079
|
+
entries:
|
|
1080
|
+
- carol@acme.dev
|
|
1081
|
+
createOnUserIds:
|
|
1082
|
+
summary: Start a whitelist keyed on user ids
|
|
1083
|
+
description: '`attr` is honoured only because this gate has no whitelist yet.'
|
|
1084
|
+
value:
|
|
1085
|
+
attr: user_id
|
|
1086
|
+
entries:
|
|
1087
|
+
- usr_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
1088
|
+
responses:
|
|
1089
|
+
'200':
|
|
1090
|
+
description: Add entries to a gate's whitelist
|
|
1091
|
+
content:
|
|
1092
|
+
application/json:
|
|
1093
|
+
schema:
|
|
1094
|
+
$ref: '#/components/schemas/GateWhitelist'
|
|
1095
|
+
example:
|
|
1096
|
+
id: gate_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
1097
|
+
name: new_checkout
|
|
1098
|
+
attr: email
|
|
1099
|
+
entries:
|
|
1100
|
+
- alice@acme.dev
|
|
1101
|
+
- bob@acme.dev
|
|
1102
|
+
- carol@acme.dev
|
|
1103
|
+
'400':
|
|
1104
|
+
$ref: '#/components/responses/BadRequest'
|
|
1105
|
+
'401':
|
|
1106
|
+
$ref: '#/components/responses/Unauthorized'
|
|
1107
|
+
'403':
|
|
1108
|
+
$ref: '#/components/responses/Forbidden'
|
|
1109
|
+
'404':
|
|
1110
|
+
$ref: '#/components/responses/NotFound'
|
|
1111
|
+
'409':
|
|
1112
|
+
$ref: '#/components/responses/Conflict'
|
|
1113
|
+
'422':
|
|
1114
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
1115
|
+
x-error-codes:
|
|
1116
|
+
- BAD_REQUEST
|
|
1117
|
+
- UNAUTHORIZED
|
|
1118
|
+
- FORBIDDEN
|
|
1119
|
+
- NOT_FOUND
|
|
1120
|
+
- IMMUTABLE_FIELD
|
|
1121
|
+
- VALIDATION
|
|
1122
|
+
x-cli:
|
|
1123
|
+
name: whitelist-add
|
|
1124
|
+
positional:
|
|
1125
|
+
- id
|
|
1126
|
+
delete:
|
|
1127
|
+
operationId: removeFromGateWhitelist
|
|
1128
|
+
summary: Remove entries from a gate's whitelist
|
|
1129
|
+
description: |-
|
|
1130
|
+
Removes identities from the gate's whitelist. Entries that aren't on the list are skipped, so the call is idempotent.
|
|
1131
|
+
|
|
1132
|
+
Removing the last entry leaves an empty whitelist block in place; to drop the block itself use `PUT` with `entries: []`.
|
|
1133
|
+
|
|
1134
|
+
**Use case:** Revoke one beta tester's access without touching anyone else's.
|
|
1135
|
+
tags:
|
|
1136
|
+
- Flags
|
|
1137
|
+
parameters:
|
|
1138
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
1139
|
+
- name: id
|
|
1140
|
+
in: path
|
|
1141
|
+
required: true
|
|
1142
|
+
description: Stable opaque gate id (`gate_…`) or the gate's `name`.
|
|
1143
|
+
schema:
|
|
1144
|
+
$ref: '#/components/schemas/ResourceId'
|
|
1145
|
+
requestBody:
|
|
1146
|
+
required: true
|
|
1147
|
+
content:
|
|
1148
|
+
application/json:
|
|
1149
|
+
schema:
|
|
1150
|
+
$ref: '#/components/schemas/RemoveFromGateWhitelistRequest'
|
|
1151
|
+
examples:
|
|
1152
|
+
removeOne:
|
|
1153
|
+
summary: Revoke one email
|
|
1154
|
+
value:
|
|
1155
|
+
entries:
|
|
1156
|
+
- carol@acme.dev
|
|
1157
|
+
responses:
|
|
1158
|
+
'200':
|
|
1159
|
+
description: Remove entries from a gate's whitelist
|
|
1160
|
+
content:
|
|
1161
|
+
application/json:
|
|
1162
|
+
schema:
|
|
1163
|
+
$ref: '#/components/schemas/GateWhitelist'
|
|
1164
|
+
example:
|
|
1165
|
+
id: gate_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
1166
|
+
name: new_checkout
|
|
1167
|
+
attr: email
|
|
1168
|
+
entries:
|
|
1169
|
+
- alice@acme.dev
|
|
1170
|
+
- bob@acme.dev
|
|
1171
|
+
'400':
|
|
1172
|
+
$ref: '#/components/responses/BadRequest'
|
|
1173
|
+
'401':
|
|
1174
|
+
$ref: '#/components/responses/Unauthorized'
|
|
1175
|
+
'403':
|
|
1176
|
+
$ref: '#/components/responses/Forbidden'
|
|
1177
|
+
'404':
|
|
1178
|
+
$ref: '#/components/responses/NotFound'
|
|
1179
|
+
'409':
|
|
1180
|
+
$ref: '#/components/responses/Conflict'
|
|
1181
|
+
'422':
|
|
1182
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
1183
|
+
x-error-codes:
|
|
1184
|
+
- BAD_REQUEST
|
|
1185
|
+
- UNAUTHORIZED
|
|
1186
|
+
- FORBIDDEN
|
|
1187
|
+
- NOT_FOUND
|
|
1188
|
+
- VALIDATION
|
|
1189
|
+
x-cli:
|
|
1190
|
+
name: whitelist-remove
|
|
1191
|
+
positional:
|
|
1192
|
+
- id
|
|
880
1193
|
/api/admin/experiments:
|
|
881
1194
|
get:
|
|
882
1195
|
operationId: listExperiments
|
|
@@ -3343,38 +3656,80 @@ paths:
|
|
|
3343
3656
|
name: set-value
|
|
3344
3657
|
positional:
|
|
3345
3658
|
- id
|
|
3346
|
-
/api/admin/
|
|
3347
|
-
|
|
3348
|
-
operationId:
|
|
3349
|
-
summary:
|
|
3659
|
+
/api/admin/killswitches/{id}/toggle:
|
|
3660
|
+
post:
|
|
3661
|
+
operationId: toggleKillswitch
|
|
3662
|
+
summary: Toggle a killswitch or one of its switches
|
|
3350
3663
|
description: |-
|
|
3351
|
-
|
|
3664
|
+
Flips a killswitch on one environment and publishes a new version there. This is the one-call incident verb: it reads the current value, flips it, and publishes, so you don't have to fetch the killswitch first.
|
|
3352
3665
|
|
|
3353
|
-
|
|
3666
|
+
Every body field is optional, which is what makes the call widen cleanly:
|
|
3667
|
+
|
|
3668
|
+
- **Flip the killswitch** — `{}`. Flips the flat `value` on `prod`.
|
|
3669
|
+
- **Flip one sub-switch** — `{ "switchKey": "eu_region" }`. Flips that entry on `prod`, creating it (from `false`) if it isn't in the map yet.
|
|
3670
|
+
- **Set it idempotently** — `{ "switchKey": "eu_region", "value": true }`. Publishes exactly that value, so a retried call can't undo the first one. A `null` `value` means "flip", not "set to null".
|
|
3671
|
+
- **Choose the environment** — add `"env": "staging"`. Omitted, `env` is `prod`.
|
|
3672
|
+
|
|
3673
|
+
The response reports both `previous` and `value`, so a caller that asked for a flip can see what it actually changed.
|
|
3674
|
+
|
|
3675
|
+
Prefer this over `PUT /{id}/value` and `PUT /{id}/switch` unless you specifically need those endpoints' unconditional set semantics.
|
|
3354
3676
|
tags:
|
|
3355
|
-
-
|
|
3677
|
+
- Killswitch
|
|
3356
3678
|
parameters:
|
|
3357
3679
|
- $ref: '#/components/parameters/ProjectId'
|
|
3358
|
-
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3680
|
+
- name: id
|
|
3681
|
+
in: path
|
|
3682
|
+
required: true
|
|
3683
|
+
description: Stable opaque killswitch id (`ksw_…`) or the killswitch's `name`.
|
|
3684
|
+
schema:
|
|
3685
|
+
$ref: '#/components/schemas/ResourceId'
|
|
3686
|
+
requestBody:
|
|
3687
|
+
required: false
|
|
3688
|
+
content:
|
|
3689
|
+
application/json:
|
|
3690
|
+
schema:
|
|
3691
|
+
$ref: '#/components/schemas/ToggleKillswitchRequest'
|
|
3692
|
+
examples:
|
|
3693
|
+
flipOnProd:
|
|
3694
|
+
summary: Flip the killswitch on prod
|
|
3695
|
+
description: No body fields — reads the flat `value` on prod and publishes its opposite.
|
|
3696
|
+
value: {}
|
|
3697
|
+
flipOneSwitch:
|
|
3698
|
+
summary: Flip one sub-switch on prod
|
|
3699
|
+
description: Flips `switches.eu_region` on prod, leaving the flat `value` and every other key alone.
|
|
3700
|
+
value:
|
|
3701
|
+
switchKey: eu_region
|
|
3702
|
+
setOneSwitch:
|
|
3703
|
+
summary: Trip one sub-switch idempotently
|
|
3704
|
+
description: Publishes `switches.eu_region = true` on prod whatever it was before — safe to retry.
|
|
3705
|
+
value:
|
|
3706
|
+
switchKey: eu_region
|
|
3707
|
+
value: true
|
|
3708
|
+
setOneSwitchOnStaging:
|
|
3709
|
+
summary: Trip one sub-switch on a chosen env
|
|
3710
|
+
description: The same idempotent set, published on staging instead of prod.
|
|
3711
|
+
value:
|
|
3712
|
+
switchKey: eu_region
|
|
3713
|
+
value: true
|
|
3714
|
+
env: staging
|
|
3361
3715
|
responses:
|
|
3362
3716
|
'200':
|
|
3363
|
-
description:
|
|
3717
|
+
description: Toggle a killswitch or one of its switches
|
|
3364
3718
|
content:
|
|
3365
3719
|
application/json:
|
|
3366
3720
|
schema:
|
|
3367
|
-
$ref: '#/components/schemas/
|
|
3721
|
+
$ref: '#/components/schemas/ToggleKillswitchResponse'
|
|
3368
3722
|
example:
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3723
|
+
id: ksw_01j7w9d8h2k4m6n8p0q2r4s6t8
|
|
3724
|
+
env: prod
|
|
3725
|
+
switchKey: eu_region
|
|
3726
|
+
previous: false
|
|
3727
|
+
value: true
|
|
3728
|
+
version: 7
|
|
3729
|
+
published:
|
|
3730
|
+
value: false
|
|
3731
|
+
switches:
|
|
3732
|
+
eu_region: true
|
|
3378
3733
|
'400':
|
|
3379
3734
|
$ref: '#/components/responses/BadRequest'
|
|
3380
3735
|
'401':
|
|
@@ -3391,14 +3746,68 @@ paths:
|
|
|
3391
3746
|
- BAD_REQUEST
|
|
3392
3747
|
- UNAUTHORIZED
|
|
3393
3748
|
- FORBIDDEN
|
|
3749
|
+
- NOT_FOUND
|
|
3750
|
+
- VALIDATION
|
|
3394
3751
|
x-cli:
|
|
3395
|
-
name:
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3752
|
+
name: toggle
|
|
3753
|
+
positional:
|
|
3754
|
+
- id
|
|
3755
|
+
/api/admin/universes:
|
|
3756
|
+
get:
|
|
3757
|
+
operationId: listUniverses
|
|
3758
|
+
summary: List universes
|
|
3759
|
+
description: |-
|
|
3760
|
+
Returns a single page of universes ordered by `created_at desc, id desc`. The universes table has no `updated_at`, so this list is keyed on creation time.
|
|
3761
|
+
|
|
3762
|
+
**Use case:** Snapshot every universe in the project — for example to audit which `unit_type` and `holdout_range` are in use before launching a new experiment.
|
|
3763
|
+
tags:
|
|
3764
|
+
- Universes
|
|
3765
|
+
parameters:
|
|
3766
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
3767
|
+
- $ref: '#/components/parameters/PaginationLimit'
|
|
3768
|
+
- $ref: '#/components/parameters/PaginationCursor'
|
|
3769
|
+
- $ref: '#/components/parameters/Q'
|
|
3770
|
+
responses:
|
|
3771
|
+
'200':
|
|
3772
|
+
description: List universes
|
|
3773
|
+
content:
|
|
3774
|
+
application/json:
|
|
3775
|
+
schema:
|
|
3776
|
+
$ref: '#/components/schemas/ListUniversesResponse'
|
|
3777
|
+
example:
|
|
3778
|
+
data:
|
|
3779
|
+
- id: uni_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
3780
|
+
name: primary_users
|
|
3781
|
+
unitType: user_id
|
|
3782
|
+
holdoutRange:
|
|
3783
|
+
- 9500
|
|
3784
|
+
- 9999
|
|
3785
|
+
createdAt: '2026-04-12T10:14:08.000Z'
|
|
3786
|
+
next_cursor: null
|
|
3787
|
+
'400':
|
|
3788
|
+
$ref: '#/components/responses/BadRequest'
|
|
3789
|
+
'401':
|
|
3790
|
+
$ref: '#/components/responses/Unauthorized'
|
|
3791
|
+
'403':
|
|
3792
|
+
$ref: '#/components/responses/Forbidden'
|
|
3793
|
+
'404':
|
|
3794
|
+
$ref: '#/components/responses/NotFound'
|
|
3795
|
+
'409':
|
|
3796
|
+
$ref: '#/components/responses/Conflict'
|
|
3797
|
+
'422':
|
|
3798
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
3799
|
+
x-error-codes:
|
|
3800
|
+
- BAD_REQUEST
|
|
3801
|
+
- UNAUTHORIZED
|
|
3802
|
+
- FORBIDDEN
|
|
3803
|
+
x-cli:
|
|
3804
|
+
name: list
|
|
3805
|
+
post:
|
|
3806
|
+
operationId: createUniverse
|
|
3807
|
+
summary: Create a universe
|
|
3808
|
+
description: |-
|
|
3809
|
+
Creates a new universe. Only `name` is required — `unit_type` defaults to `user_id` and `holdout_range` defaults to `null` (no holdout).
|
|
3810
|
+
|
|
3402
3811
|
Returns `409` if `name` already exists in the project. Returns `403` if you supply `holdout_range` on a plan below Pro.
|
|
3403
3812
|
|
|
3404
3813
|
**Use cases**
|
|
@@ -4183,12 +4592,15 @@ paths:
|
|
|
4183
4592
|
name: checkouts
|
|
4184
4593
|
folder: null
|
|
4185
4594
|
eventName: checkout_completed
|
|
4186
|
-
query:
|
|
4595
|
+
query: count(checkout_completed)
|
|
4187
4596
|
queryIr:
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4597
|
+
v: 2
|
|
4598
|
+
expr:
|
|
4599
|
+
node: agg
|
|
4600
|
+
event: checkout_completed
|
|
4601
|
+
agg:
|
|
4602
|
+
kind: count
|
|
4603
|
+
filters: []
|
|
4192
4604
|
direction: higher_better
|
|
4193
4605
|
version: 1
|
|
4194
4606
|
'400':
|
|
@@ -4222,7 +4634,7 @@ paths:
|
|
|
4222
4634
|
|
|
4223
4635
|
**Use cases**
|
|
4224
4636
|
|
|
4225
|
-
- **Track an event** — `
|
|
4637
|
+
- **Track an event** — `count(<event>)` for event counts.
|
|
4226
4638
|
- **Sum a value** — `sum(<event>, <label>)` for revenue / quantity metrics.
|
|
4227
4639
|
- **Experiment success metric** — create the metric, then attach its id to an experiment.
|
|
4228
4640
|
tags:
|
|
@@ -4236,13 +4648,13 @@ paths:
|
|
|
4236
4648
|
schema:
|
|
4237
4649
|
$ref: '#/components/schemas/CreateMetricRequest'
|
|
4238
4650
|
examples:
|
|
4239
|
-
|
|
4240
|
-
summary: Count
|
|
4241
|
-
description:
|
|
4651
|
+
countEvents:
|
|
4652
|
+
summary: Count an event (DSL)
|
|
4653
|
+
description: Completed checkouts, expressed with the query DSL.
|
|
4242
4654
|
value:
|
|
4243
4655
|
name: checkouts
|
|
4244
4656
|
event_name: checkout_completed
|
|
4245
|
-
query:
|
|
4657
|
+
query: count(checkout_completed)
|
|
4246
4658
|
sumRevenue:
|
|
4247
4659
|
summary: Sum a value label (DSL)
|
|
4248
4660
|
description: Total revenue, summing the `amount` property of the `purchase` event.
|
|
@@ -4259,10 +4671,13 @@ paths:
|
|
|
4259
4671
|
name: checkouts
|
|
4260
4672
|
event_name: checkout_completed
|
|
4261
4673
|
query_ir:
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4674
|
+
v: 2
|
|
4675
|
+
expr:
|
|
4676
|
+
node: agg
|
|
4677
|
+
event: checkout_completed
|
|
4678
|
+
agg:
|
|
4679
|
+
kind: count
|
|
4680
|
+
filters: []
|
|
4266
4681
|
responses:
|
|
4267
4682
|
'201':
|
|
4268
4683
|
description: Create a metric
|
|
@@ -4343,11 +4758,14 @@ paths:
|
|
|
4343
4758
|
eventName: purchase
|
|
4344
4759
|
query: sum(purchase, amount)
|
|
4345
4760
|
queryIr:
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4761
|
+
v: 2
|
|
4762
|
+
expr:
|
|
4763
|
+
node: agg
|
|
4764
|
+
event: purchase
|
|
4765
|
+
agg:
|
|
4766
|
+
kind: sum
|
|
4767
|
+
valueLabel: amount
|
|
4768
|
+
filters: []
|
|
4351
4769
|
direction: higher_better
|
|
4352
4770
|
winsorizePct: 99
|
|
4353
4771
|
version: 1
|
|
@@ -5053,7 +5471,11 @@ paths:
|
|
|
5053
5471
|
operationId: listOpsItems
|
|
5054
5472
|
summary: List the operational queue
|
|
5055
5473
|
description: |-
|
|
5056
|
-
Returns the unified ops queue (bugs, feature requests, errors, alerts) in work order — highest priority first, oldest first within a priority — so consumers work it top-down.
|
|
5474
|
+
Returns the unified ops queue (bugs, feature requests, errors, alerts, measurement plans) in work order — highest priority first, oldest first within a priority — so consumers work it top-down. Every filter is applied in SQL before paging, and filters combine with AND. Human-gated holding states (items awaiting human sign-off in the dashboard) are never returned by `all`/default status.
|
|
5475
|
+
|
|
5476
|
+
**Filters:** `type` (one item type), `status` (one lifecycle status, or `unresolved` — everything not yet `resolved`/`wont_fix`), `priority` (one triage priority), `owner` (one person or agent), and `scope=ready` — the items ready to be picked up right now: `open`, with nobody working them (no open run), and either unowned or reopened (sent back to `open` after an earlier run finished).
|
|
5477
|
+
|
|
5478
|
+
**Paging:** `limit` is the page size and `offset` the number of items to skip. The order is stable, so walk the queue with `offset += limit`; a page shorter than `limit` is the last one.
|
|
5057
5479
|
|
|
5058
5480
|
**Use case:** Pull the open queue to triage — e.g. every `bug` still `open` — before working items down one by one.
|
|
5059
5481
|
tags:
|
|
@@ -5063,8 +5485,9 @@ paths:
|
|
|
5063
5485
|
- name: type
|
|
5064
5486
|
in: query
|
|
5065
5487
|
required: false
|
|
5066
|
-
description: Filter by item type
|
|
5488
|
+
description: Filter by item type, or `all` (the default). Every type a returned item can carry is filterable, including the auto-filed ones.
|
|
5067
5489
|
schema:
|
|
5490
|
+
default: all
|
|
5068
5491
|
anyOf:
|
|
5069
5492
|
- type: string
|
|
5070
5493
|
enum:
|
|
@@ -5072,30 +5495,70 @@ paths:
|
|
|
5072
5495
|
- feature_request
|
|
5073
5496
|
- error
|
|
5074
5497
|
- alert
|
|
5075
|
-
|
|
5498
|
+
- measure_plan
|
|
5499
|
+
description: Queue item type. `bug` and `feature_request` are user-fileable; `error`, `alert`, and `measure_plan` tickets are auto-filed by the platform.
|
|
5076
5500
|
- type: string
|
|
5077
5501
|
const: all
|
|
5078
5502
|
- name: status
|
|
5079
5503
|
in: query
|
|
5080
5504
|
required: false
|
|
5081
|
-
description: Filter by lifecycle status, or `all
|
|
5505
|
+
description: Filter by one lifecycle status, `unresolved` for every status that is not `resolved` or `wont_fix`, or `all` for every status. Defaults to `all` over HTTP; the CLI and MCP tool default to `unresolved`, so pass `all` there to include resolved and won't-fix items. The human-gated holding state (`pending_approval`) is excluded from `unresolved` and `all`, and returned only when requested as the exact status.
|
|
5082
5506
|
schema:
|
|
5507
|
+
default: all
|
|
5083
5508
|
anyOf:
|
|
5084
5509
|
- $ref: '#/components/schemas/OpsItemStatus'
|
|
5510
|
+
- type: string
|
|
5511
|
+
const: unresolved
|
|
5512
|
+
- type: string
|
|
5513
|
+
const: all
|
|
5514
|
+
x-cli:
|
|
5515
|
+
default: unresolved
|
|
5516
|
+
x-mcp:
|
|
5517
|
+
default: unresolved
|
|
5518
|
+
- name: priority
|
|
5519
|
+
in: query
|
|
5520
|
+
required: false
|
|
5521
|
+
description: Filter by triage priority, or `all` (the default). Items with no priority set are returned only under `all`.
|
|
5522
|
+
schema:
|
|
5523
|
+
default: all
|
|
5524
|
+
anyOf:
|
|
5525
|
+
- $ref: '#/components/schemas/OpsItemPriority'
|
|
5085
5526
|
- type: string
|
|
5086
5527
|
const: all
|
|
5528
|
+
- name: scope
|
|
5529
|
+
in: query
|
|
5530
|
+
required: false
|
|
5531
|
+
description: '`ready` narrows to the items ready to be picked up right now: status `open`, no open run (nobody has acked it and is still working), and either unowned (no person and no agent) or reopened (sent back to `open` after an earlier run finished). Leave `status` unset with it. `all` (the default) applies no such narrowing.'
|
|
5532
|
+
schema:
|
|
5533
|
+
type: string
|
|
5534
|
+
enum:
|
|
5535
|
+
- all
|
|
5536
|
+
- ready
|
|
5537
|
+
default: all
|
|
5087
5538
|
- name: limit
|
|
5088
5539
|
in: query
|
|
5089
5540
|
required: false
|
|
5090
|
-
description:
|
|
5541
|
+
description: Page size — max items to return (1–500). A page shorter than `limit` is the last one.
|
|
5091
5542
|
schema:
|
|
5092
5543
|
type: integer
|
|
5093
5544
|
minimum: 1
|
|
5094
5545
|
maximum: 500
|
|
5546
|
+
default: 200
|
|
5547
|
+
x-mcp:
|
|
5548
|
+
required: true
|
|
5549
|
+
- name: offset
|
|
5550
|
+
in: query
|
|
5551
|
+
required: false
|
|
5552
|
+
description: Number of items to skip before the page starts. Defaults to 0. The order is stable, so `offset += limit` walks the queue page by page.
|
|
5553
|
+
schema:
|
|
5554
|
+
type: integer
|
|
5555
|
+
minimum: 0
|
|
5556
|
+
maximum: 100000
|
|
5557
|
+
default: 0
|
|
5095
5558
|
- name: owner
|
|
5096
5559
|
in: query
|
|
5097
5560
|
required: false
|
|
5098
|
-
description: Narrow to items owned by one person OR one agent. Matches a person by `users.id`, email, or display name, and an agent by connector id, display name, or kebab-case handle — e.g. `owner=Claude` or `owner=alice@acme.dev`. Case-insensitive exact match
|
|
5561
|
+
description: Narrow to items owned by one person OR one agent. Matches a person by `users.id`, email, or display name, and an agent by connector id, display name, or kebab-case handle — e.g. `owner=Claude` or `owner=alice@acme.dev`. Case-insensitive exact match.
|
|
5099
5562
|
schema:
|
|
5100
5563
|
type: string
|
|
5101
5564
|
responses:
|
|
@@ -5141,6 +5604,8 @@ paths:
|
|
|
5141
5604
|
- FORBIDDEN
|
|
5142
5605
|
x-cli:
|
|
5143
5606
|
name: list
|
|
5607
|
+
x-mcp:
|
|
5608
|
+
description: 'List the operational queue (bugs, feature requests, errors, alerts, measurement plans) in work order — highest priority first, oldest first within a priority. PAGING: `limit` (page size, 1–500) is REQUIRED — the call fails without it. Start at `offset: 0` and add `limit` to `offset` for the next page; a page shorter than `limit` is the last one. FILTERS (all optional, combined with AND, applied before paging): `type` = bug | feature_request | error | alert | measure_plan; `status` = open | in_progress | investigating_by_ai | blocked | ready_for_qa | resolved | wont_fix | pending_approval | unresolved | all — DEFAULTS TO `unresolved` (omitted = items still being worked: open, in_progress, blocked, ready_for_qa…; no resolved or wont_fix ones). Pass `status: "all"` to include resolved and wont_fix too (pending_approval is only returned when asked for exactly); `priority` = critical | high | medium | nice_to_have; `owner` = a person (id, email or name) or an agent (connector id, name or handle, e.g. "Claude"); `scope: "ready"` = what to work on now — open items nobody is working (no open run) that are unowned or were reopened after an earlier run. Use `scope: "ready"` to pick the next item, then `ops_ack` it.'
|
|
5144
5609
|
post:
|
|
5145
5610
|
operationId: createOpsItem
|
|
5146
5611
|
summary: File a queue item
|
|
@@ -5222,6 +5687,173 @@ paths:
|
|
|
5222
5687
|
summary: File a feature request.
|
|
5223
5688
|
preset:
|
|
5224
5689
|
type: feature_request
|
|
5690
|
+
/ops/bug:
|
|
5691
|
+
post:
|
|
5692
|
+
operationId: createPublicBug
|
|
5693
|
+
summary: File a bug
|
|
5694
|
+
description: |-
|
|
5695
|
+
Files one bug onto a project's queue, awaiting human approval. This is the **public** intake: it authenticates with a *client* SDK key rather than an admin key, so it can be called from a CLI, an installer script, a devtools overlay, or any shipped code — the same places a client key already lives.
|
|
5696
|
+
|
|
5697
|
+
Three gates decide whether a ticket is filed, and nothing else the caller sends can widen them:
|
|
5698
|
+
|
|
5699
|
+
1. the key is a `client` key carrying the `tickets:public_create` scope,
|
|
5700
|
+
2. the key's project has public ticket creation enabled, and
|
|
5701
|
+
3. the item is filed as `pending_approval` — parked out of the work queue until a human promotes it in the dashboard.
|
|
5702
|
+
|
|
5703
|
+
The project is the key's own project; there is no `X-Project-Id` to pass and no way to file into someone else's queue. Repeat submissions of the same title dedupe against the open ticket already tracking it, which returns `200` with `deduped: true` instead of filing again.
|
|
5704
|
+
|
|
5705
|
+
Send a `dedupKey` to own that grain yourself — the same key from a monitor, a job, or a retried install re-triggers its open ticket: the ticket's fields are refreshed from the new payload and a "re-triggered" comment is appended (`200` with `deduped: true, updated: true`), so one recurring failure stays one ticket with its history intact.
|
|
5706
|
+
|
|
5707
|
+
This endpoint is served by the Shipeasy **edge worker** (`api.shipeasy.ai`), not the admin API — see `servers` below.
|
|
5708
|
+
|
|
5709
|
+
**Use case:** `shipeasy setup` fails on a customer's machine and self-reports the failure with the user's consent — `{ "title": "Setup failed at Feature installs", "stepsToReproduce": "…", "actualResult": "…" }`.
|
|
5710
|
+
tags:
|
|
5711
|
+
- Ops
|
|
5712
|
+
servers:
|
|
5713
|
+
- url: https://api.shipeasy.ai
|
|
5714
|
+
description: Shipeasy edge worker (production)
|
|
5715
|
+
- url: http://localhost:8787
|
|
5716
|
+
description: Local `wrangler dev`
|
|
5717
|
+
security:
|
|
5718
|
+
- clientSdkKey: []
|
|
5719
|
+
requestBody:
|
|
5720
|
+
required: true
|
|
5721
|
+
content:
|
|
5722
|
+
application/json:
|
|
5723
|
+
schema:
|
|
5724
|
+
$ref: '#/components/schemas/CreatePublicBugRequest'
|
|
5725
|
+
examples:
|
|
5726
|
+
minimal:
|
|
5727
|
+
summary: Just a title
|
|
5728
|
+
description: Every other field is optional — the queue triages from `open` at default priority.
|
|
5729
|
+
value:
|
|
5730
|
+
title: Checkout button misaligned on mobile
|
|
5731
|
+
full:
|
|
5732
|
+
summary: A full report
|
|
5733
|
+
value:
|
|
5734
|
+
title: Checkout button misaligned on mobile
|
|
5735
|
+
stepsToReproduce: Open the cart on iOS Safari and tap the price row.
|
|
5736
|
+
actualResult: The primary CTA overlaps the price.
|
|
5737
|
+
expectedResult: The CTA sits below the price with clear spacing.
|
|
5738
|
+
priority: high
|
|
5739
|
+
reporterEmail: alice@acme.dev
|
|
5740
|
+
pageUrl: https://acme.dev/cart
|
|
5741
|
+
responses:
|
|
5742
|
+
'200':
|
|
5743
|
+
description: An open ticket already tracks this report; nothing was filed
|
|
5744
|
+
content:
|
|
5745
|
+
application/json:
|
|
5746
|
+
schema:
|
|
5747
|
+
$ref: '#/components/schemas/CreatePublicTicketResponse'
|
|
5748
|
+
example:
|
|
5749
|
+
number: 7
|
|
5750
|
+
deduped: true
|
|
5751
|
+
'201':
|
|
5752
|
+
description: File a bug
|
|
5753
|
+
content:
|
|
5754
|
+
application/json:
|
|
5755
|
+
schema:
|
|
5756
|
+
$ref: '#/components/schemas/CreatePublicTicketResponse'
|
|
5757
|
+
example:
|
|
5758
|
+
id: fb_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
5759
|
+
number: 7
|
|
5760
|
+
'400':
|
|
5761
|
+
$ref: '#/components/responses/BadRequest'
|
|
5762
|
+
'401':
|
|
5763
|
+
$ref: '#/components/responses/Unauthorized'
|
|
5764
|
+
'403':
|
|
5765
|
+
$ref: '#/components/responses/Forbidden'
|
|
5766
|
+
'413':
|
|
5767
|
+
$ref: '#/components/responses/PayloadTooLarge'
|
|
5768
|
+
'429':
|
|
5769
|
+
$ref: '#/components/responses/TooManyRequests'
|
|
5770
|
+
'503':
|
|
5771
|
+
$ref: '#/components/responses/ServiceUnavailable'
|
|
5772
|
+
x-error-codes:
|
|
5773
|
+
- BAD_REQUEST
|
|
5774
|
+
- UNAUTHORIZED
|
|
5775
|
+
- FORBIDDEN
|
|
5776
|
+
- VALIDATION
|
|
5777
|
+
x-cli:
|
|
5778
|
+
hidden: true
|
|
5779
|
+
/ops/feature-request:
|
|
5780
|
+
post:
|
|
5781
|
+
operationId: createPublicFeatureRequest
|
|
5782
|
+
summary: File a feature request
|
|
5783
|
+
description: |-
|
|
5784
|
+
Files one feature request onto a project's queue, awaiting human approval. The feature-request counterpart to `POST /ops/bug`, with the same three gates: a `client` key carrying `tickets:public_create`, a project that has opted in, and a `pending_approval` state forced server-side.
|
|
5785
|
+
|
|
5786
|
+
The project is the key's own project; there is no `X-Project-Id` to pass. Repeat submissions of the same title dedupe against the open ticket already tracking it, which returns `200` with `deduped: true` instead of filing again. A `dedupKey` works exactly as on `POST /ops/bug`: a repeat carrying the same key refreshes the open ticket and comments that it was re-triggered.
|
|
5787
|
+
|
|
5788
|
+
This endpoint is served by the Shipeasy **edge worker** (`api.shipeasy.ai`), not the admin API — see `servers` below.
|
|
5789
|
+
|
|
5790
|
+
**Use case:** An in-product "request a feature" form posts what the user asked for — `{ "title": "Dark mode", "useCase": "Reduce eye strain at night" }`.
|
|
5791
|
+
tags:
|
|
5792
|
+
- Ops
|
|
5793
|
+
servers:
|
|
5794
|
+
- url: https://api.shipeasy.ai
|
|
5795
|
+
description: Shipeasy edge worker (production)
|
|
5796
|
+
- url: http://localhost:8787
|
|
5797
|
+
description: Local `wrangler dev`
|
|
5798
|
+
security:
|
|
5799
|
+
- clientSdkKey: []
|
|
5800
|
+
requestBody:
|
|
5801
|
+
required: true
|
|
5802
|
+
content:
|
|
5803
|
+
application/json:
|
|
5804
|
+
schema:
|
|
5805
|
+
$ref: '#/components/schemas/CreatePublicFeatureRequestRequest'
|
|
5806
|
+
examples:
|
|
5807
|
+
minimal:
|
|
5808
|
+
summary: Just a title
|
|
5809
|
+
value:
|
|
5810
|
+
title: Dark mode for the dashboard
|
|
5811
|
+
full:
|
|
5812
|
+
summary: A full request
|
|
5813
|
+
value:
|
|
5814
|
+
title: Dark mode for the dashboard
|
|
5815
|
+
description: Add a theme toggle that persists per user.
|
|
5816
|
+
useCase: Reduce eye strain for users working at night.
|
|
5817
|
+
priority: nice_to_have
|
|
5818
|
+
reporterEmail: alice@acme.dev
|
|
5819
|
+
responses:
|
|
5820
|
+
'200':
|
|
5821
|
+
description: An open ticket already tracks this report; nothing was filed
|
|
5822
|
+
content:
|
|
5823
|
+
application/json:
|
|
5824
|
+
schema:
|
|
5825
|
+
$ref: '#/components/schemas/CreatePublicTicketResponse'
|
|
5826
|
+
example:
|
|
5827
|
+
number: 7
|
|
5828
|
+
deduped: true
|
|
5829
|
+
'201':
|
|
5830
|
+
description: File a feature request
|
|
5831
|
+
content:
|
|
5832
|
+
application/json:
|
|
5833
|
+
schema:
|
|
5834
|
+
$ref: '#/components/schemas/CreatePublicTicketResponse'
|
|
5835
|
+
example:
|
|
5836
|
+
id: fb_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
5837
|
+
number: 8
|
|
5838
|
+
'400':
|
|
5839
|
+
$ref: '#/components/responses/BadRequest'
|
|
5840
|
+
'401':
|
|
5841
|
+
$ref: '#/components/responses/Unauthorized'
|
|
5842
|
+
'403':
|
|
5843
|
+
$ref: '#/components/responses/Forbidden'
|
|
5844
|
+
'413':
|
|
5845
|
+
$ref: '#/components/responses/PayloadTooLarge'
|
|
5846
|
+
'429':
|
|
5847
|
+
$ref: '#/components/responses/TooManyRequests'
|
|
5848
|
+
'503':
|
|
5849
|
+
$ref: '#/components/responses/ServiceUnavailable'
|
|
5850
|
+
x-error-codes:
|
|
5851
|
+
- BAD_REQUEST
|
|
5852
|
+
- UNAUTHORIZED
|
|
5853
|
+
- FORBIDDEN
|
|
5854
|
+
- VALIDATION
|
|
5855
|
+
x-cli:
|
|
5856
|
+
hidden: true
|
|
5225
5857
|
/api/admin/ops/{handle}:
|
|
5226
5858
|
get:
|
|
5227
5859
|
operationId: getOpsItem
|
|
@@ -5470,6 +6102,11 @@ paths:
|
|
|
5470
6102
|
list` and use one of those (or connect the agent under Settings →
|
|
5471
6103
|
Triggers).
|
|
5472
6104
|
|
|
6105
|
+
**Launching.** When the named agent has a connected trigger and you pass
|
|
6106
|
+
no `sessionId`, the ack also fires that trigger — a new provider run
|
|
6107
|
+
starts working the item. Pass `launch: false` to only claim the item and
|
|
6108
|
+
record the run (you are doing the work yourself), without starting one.
|
|
6109
|
+
|
|
5473
6110
|
**Completion.** The run closes automatically on the loop's final actions —
|
|
5474
6111
|
linking the fixing PR (`link-pr`), an ops-notify escalation, or a
|
|
5475
6112
|
completion status change (`ready_for_qa`/`resolved`) — and the dashboard
|
|
@@ -5591,7 +6228,9 @@ paths:
|
|
|
5591
6228
|
(`kind: investigated`), a blocking question for the team (`kind:
|
|
5592
6229
|
question`), or how to verify the fix (`kind: ready_for_qa` with
|
|
5593
6230
|
`qaNotes`). Append-only and create-only, so it is safe for restricted ops
|
|
5594
|
-
keys.
|
|
6231
|
+
keys. For a decision between options you can name, ask a structured
|
|
6232
|
+
question instead (`ops questions ask`) — it is answerable in one tap and
|
|
6233
|
+
the answer comes back to your run.
|
|
5595
6234
|
|
|
5596
6235
|
**Use case:** After working an item, leave a findings write-up (summary,
|
|
5597
6236
|
markdown findings, sources inspected, confidence) so the team — and the
|
|
@@ -5734,53 +6373,88 @@ paths:
|
|
|
5734
6373
|
positional:
|
|
5735
6374
|
- handle
|
|
5736
6375
|
- investigationId
|
|
5737
|
-
/api/admin/
|
|
6376
|
+
/api/admin/ops/{handle}/questions:
|
|
5738
6377
|
get:
|
|
5739
|
-
operationId:
|
|
5740
|
-
summary: List
|
|
6378
|
+
operationId: listOpsQuestions
|
|
6379
|
+
summary: List an item's questions
|
|
5741
6380
|
description: |-
|
|
5742
|
-
The
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
6381
|
+
The structured questions asked on a queue item, with their answers —
|
|
6382
|
+
newest first (max 100). Pull this to read the answers to questions you
|
|
6383
|
+
asked: an answered question reads `status: completed` and carries
|
|
6384
|
+
`answer.selected` (the option labels picked) and `answer.other` (the
|
|
6385
|
+
free-text "Other" reply, or `null`).
|
|
6386
|
+
|
|
6387
|
+
**Use case:** You asked with `delivery: poll` from a live session — poll
|
|
6388
|
+
this until your questions read `completed`, then continue with the answers.
|
|
5748
6389
|
tags:
|
|
5749
|
-
-
|
|
6390
|
+
- Questions
|
|
5750
6391
|
parameters:
|
|
5751
6392
|
- $ref: '#/components/parameters/ProjectId'
|
|
6393
|
+
- name: handle
|
|
6394
|
+
in: path
|
|
6395
|
+
required: true
|
|
6396
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6397
|
+
schema:
|
|
6398
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6399
|
+
- name: status
|
|
6400
|
+
in: query
|
|
6401
|
+
required: false
|
|
6402
|
+
description: Filter by question status, or `all` (the default).
|
|
6403
|
+
schema:
|
|
6404
|
+
default: all
|
|
6405
|
+
anyOf:
|
|
6406
|
+
- $ref: '#/components/schemas/OpsQuestionStatus'
|
|
6407
|
+
- type: string
|
|
6408
|
+
const: all
|
|
5752
6409
|
responses:
|
|
5753
6410
|
'200':
|
|
5754
|
-
description: List
|
|
6411
|
+
description: List an item's questions
|
|
5755
6412
|
content:
|
|
5756
6413
|
application/json:
|
|
5757
6414
|
schema:
|
|
5758
|
-
$ref: '#/components/schemas/
|
|
6415
|
+
$ref: '#/components/schemas/ListOpsQuestionsResponse'
|
|
5759
6416
|
'400':
|
|
5760
6417
|
$ref: '#/components/responses/BadRequest'
|
|
5761
6418
|
'401':
|
|
5762
6419
|
$ref: '#/components/responses/Unauthorized'
|
|
5763
6420
|
'403':
|
|
5764
6421
|
$ref: '#/components/responses/Forbidden'
|
|
6422
|
+
'404':
|
|
6423
|
+
$ref: '#/components/responses/NotFound'
|
|
6424
|
+
'422':
|
|
6425
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
5765
6426
|
x-error-codes:
|
|
5766
6427
|
- BAD_REQUEST
|
|
5767
6428
|
- UNAUTHORIZED
|
|
5768
6429
|
- FORBIDDEN
|
|
6430
|
+
- NOT_FOUND
|
|
5769
6431
|
x-cli:
|
|
5770
6432
|
name: list
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
6433
|
+
positional:
|
|
6434
|
+
- handle
|
|
6435
|
+
post:
|
|
6436
|
+
operationId: askOpsQuestions
|
|
6437
|
+
summary: Ask the team questions about an item
|
|
5775
6438
|
description: |-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
6439
|
+
Ask 1–4 structured questions about a queue item — the way to get a
|
|
6440
|
+
decision from a person when the implementation needs one. Each question
|
|
6441
|
+
is the `AskUserQuestion` shape: a short `header` chip, the full
|
|
6442
|
+
`question`, 2–4 `options` (`label` + `description`), and `multiSelect`
|
|
6443
|
+
(checkboxes instead of radios). The person can always answer "Other" in
|
|
6444
|
+
free text, so never add an "Other" option yourself. The questions render
|
|
6445
|
+
at the very top of the item's detail panel and mark the row in the queue.
|
|
6446
|
+
|
|
6447
|
+
**Delivery.** `resume` re-fires your trigger-connector run on the item
|
|
6448
|
+
once every question it asked is answered, continuing the same run record
|
|
6449
|
+
with the answers in the prompt — stop after asking. `poll` fires nothing;
|
|
6450
|
+
poll `GET .../questions` instead. Omitted, it is `resume` when `runId`
|
|
6451
|
+
names a run launched through a trigger connector, else `poll`.
|
|
6452
|
+
|
|
6453
|
+
**Use case:** Blocked on a product decision (which behaviour to keep,
|
|
6454
|
+
which of two fixes to ship) — ask instead of guessing, then wait for the
|
|
6455
|
+
answer.
|
|
5782
6456
|
tags:
|
|
5783
|
-
-
|
|
6457
|
+
- Questions
|
|
5784
6458
|
parameters:
|
|
5785
6459
|
- $ref: '#/components/parameters/ProjectId'
|
|
5786
6460
|
- name: handle
|
|
@@ -5789,13 +6463,33 @@ paths:
|
|
|
5789
6463
|
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
5790
6464
|
schema:
|
|
5791
6465
|
$ref: '#/components/schemas/ResourceId'
|
|
6466
|
+
requestBody:
|
|
6467
|
+
required: true
|
|
6468
|
+
content:
|
|
6469
|
+
application/json:
|
|
6470
|
+
schema:
|
|
6471
|
+
$ref: '#/components/schemas/AskOpsQuestionsRequest'
|
|
6472
|
+
examples:
|
|
6473
|
+
single:
|
|
6474
|
+
summary: Ask one radio question
|
|
6475
|
+
value:
|
|
6476
|
+
runId: 0d3f4c8e-7a51-4c2e-9b1f-1e2d3c4b5a69
|
|
6477
|
+
questions:
|
|
6478
|
+
- header: Legacy param
|
|
6479
|
+
question: Should the fix keep honouring the legacy `?v=1` query param?
|
|
6480
|
+
multiSelect: false
|
|
6481
|
+
options:
|
|
6482
|
+
- label: Keep it
|
|
6483
|
+
description: Old links keep working; the redirect stays
|
|
6484
|
+
- label: Drop it
|
|
6485
|
+
description: Simpler code; old links land on the default view
|
|
5792
6486
|
responses:
|
|
5793
6487
|
'200':
|
|
5794
|
-
description:
|
|
6488
|
+
description: The created questions, in the order asked
|
|
5795
6489
|
content:
|
|
5796
6490
|
application/json:
|
|
5797
6491
|
schema:
|
|
5798
|
-
$ref: '#/components/schemas/
|
|
6492
|
+
$ref: '#/components/schemas/AskOpsQuestionsResponse'
|
|
5799
6493
|
'400':
|
|
5800
6494
|
$ref: '#/components/responses/BadRequest'
|
|
5801
6495
|
'401':
|
|
@@ -5804,23 +6498,237 @@ paths:
|
|
|
5804
6498
|
$ref: '#/components/responses/Forbidden'
|
|
5805
6499
|
'404':
|
|
5806
6500
|
$ref: '#/components/responses/NotFound'
|
|
6501
|
+
'422':
|
|
6502
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
5807
6503
|
x-error-codes:
|
|
5808
6504
|
- BAD_REQUEST
|
|
5809
6505
|
- UNAUTHORIZED
|
|
5810
6506
|
- FORBIDDEN
|
|
5811
6507
|
- NOT_FOUND
|
|
6508
|
+
- VALIDATION
|
|
5812
6509
|
x-cli:
|
|
5813
|
-
name:
|
|
6510
|
+
name: ask
|
|
5814
6511
|
positional:
|
|
5815
6512
|
- handle
|
|
6513
|
+
/api/admin/ops/{handle}/questions/{questionId}/answer:
|
|
5816
6514
|
post:
|
|
5817
|
-
operationId:
|
|
5818
|
-
summary:
|
|
6515
|
+
operationId: answerOpsQuestion
|
|
6516
|
+
summary: Answer a question
|
|
5819
6517
|
description: |-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
6518
|
+
Answer one open question on a queue item — pick option labels in
|
|
6519
|
+
`selected` (exactly one unless the question is `multiSelect`) and/or
|
|
6520
|
+
write a free-text `other`. The question moves to `completed`. When it was
|
|
6521
|
+
the last open question of a `resume` run, that agent is re-fired on the
|
|
6522
|
+
item with every answer. A person's action: never allow-listed for
|
|
6523
|
+
restricted ops keys.
|
|
6524
|
+
|
|
6525
|
+
**Use case:** Unblock an agent from the CLI instead of the dashboard.
|
|
6526
|
+
tags:
|
|
6527
|
+
- Questions
|
|
6528
|
+
parameters:
|
|
6529
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
6530
|
+
- name: handle
|
|
6531
|
+
in: path
|
|
6532
|
+
required: true
|
|
6533
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6534
|
+
schema:
|
|
6535
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6536
|
+
- name: questionId
|
|
6537
|
+
in: path
|
|
6538
|
+
required: true
|
|
6539
|
+
description: The question id (from `ask` or `list`).
|
|
6540
|
+
schema:
|
|
6541
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6542
|
+
requestBody:
|
|
6543
|
+
required: true
|
|
6544
|
+
content:
|
|
6545
|
+
application/json:
|
|
6546
|
+
schema:
|
|
6547
|
+
$ref: '#/components/schemas/AnswerOpsQuestionRequest'
|
|
6548
|
+
examples:
|
|
6549
|
+
option:
|
|
6550
|
+
summary: Pick an option
|
|
6551
|
+
value:
|
|
6552
|
+
selected:
|
|
6553
|
+
- Keep it
|
|
6554
|
+
other:
|
|
6555
|
+
summary: Answer in free text
|
|
6556
|
+
value:
|
|
6557
|
+
other: Keep it for a release, then drop it
|
|
6558
|
+
responses:
|
|
6559
|
+
'200':
|
|
6560
|
+
description: The answered question
|
|
6561
|
+
content:
|
|
6562
|
+
application/json:
|
|
6563
|
+
schema:
|
|
6564
|
+
$ref: '#/components/schemas/OpsQuestion'
|
|
6565
|
+
'400':
|
|
6566
|
+
$ref: '#/components/responses/BadRequest'
|
|
6567
|
+
'401':
|
|
6568
|
+
$ref: '#/components/responses/Unauthorized'
|
|
6569
|
+
'403':
|
|
6570
|
+
$ref: '#/components/responses/Forbidden'
|
|
6571
|
+
'404':
|
|
6572
|
+
$ref: '#/components/responses/NotFound'
|
|
6573
|
+
'409':
|
|
6574
|
+
$ref: '#/components/responses/Conflict'
|
|
6575
|
+
'422':
|
|
6576
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
6577
|
+
x-error-codes:
|
|
6578
|
+
- BAD_REQUEST
|
|
6579
|
+
- UNAUTHORIZED
|
|
6580
|
+
- FORBIDDEN
|
|
6581
|
+
- NOT_FOUND
|
|
6582
|
+
- INVALID_TRANSITION
|
|
6583
|
+
- VALIDATION
|
|
6584
|
+
x-cli:
|
|
6585
|
+
name: answer
|
|
6586
|
+
positional:
|
|
6587
|
+
- handle
|
|
6588
|
+
- questionId
|
|
6589
|
+
/api/admin/ops/{handle}/questions/{questionId}/cancel:
|
|
6590
|
+
post:
|
|
6591
|
+
operationId: cancelOpsQuestion
|
|
6592
|
+
summary: Withdraw a question
|
|
6593
|
+
description: |-
|
|
6594
|
+
Withdraw one open question you asked — it no longer needs an answer
|
|
6595
|
+
(you found it out yourself, or the item moved on). The question moves to
|
|
6596
|
+
`cancelled` and leaves the detail panel. Withdrawing the last open
|
|
6597
|
+
question of a run delivers nothing.
|
|
6598
|
+
|
|
6599
|
+
**Use case:** You asked, then answered it yourself from the code — take
|
|
6600
|
+
it off the person's plate.
|
|
6601
|
+
tags:
|
|
6602
|
+
- Questions
|
|
6603
|
+
parameters:
|
|
6604
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
6605
|
+
- name: handle
|
|
6606
|
+
in: path
|
|
6607
|
+
required: true
|
|
6608
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6609
|
+
schema:
|
|
6610
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6611
|
+
- name: questionId
|
|
6612
|
+
in: path
|
|
6613
|
+
required: true
|
|
6614
|
+
description: The question id (from `ask` or `list`).
|
|
6615
|
+
schema:
|
|
6616
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6617
|
+
responses:
|
|
6618
|
+
'200':
|
|
6619
|
+
description: The withdrawn question
|
|
6620
|
+
content:
|
|
6621
|
+
application/json:
|
|
6622
|
+
schema:
|
|
6623
|
+
$ref: '#/components/schemas/OpsQuestion'
|
|
6624
|
+
'400':
|
|
6625
|
+
$ref: '#/components/responses/BadRequest'
|
|
6626
|
+
'401':
|
|
6627
|
+
$ref: '#/components/responses/Unauthorized'
|
|
6628
|
+
'403':
|
|
6629
|
+
$ref: '#/components/responses/Forbidden'
|
|
6630
|
+
'404':
|
|
6631
|
+
$ref: '#/components/responses/NotFound'
|
|
6632
|
+
'409':
|
|
6633
|
+
$ref: '#/components/responses/Conflict'
|
|
6634
|
+
x-error-codes:
|
|
6635
|
+
- BAD_REQUEST
|
|
6636
|
+
- UNAUTHORIZED
|
|
6637
|
+
- FORBIDDEN
|
|
6638
|
+
- NOT_FOUND
|
|
6639
|
+
- INVALID_TRANSITION
|
|
6640
|
+
x-cli:
|
|
6641
|
+
name: cancel
|
|
6642
|
+
positional:
|
|
6643
|
+
- handle
|
|
6644
|
+
- questionId
|
|
6645
|
+
/api/admin/agent-profiles:
|
|
6646
|
+
get:
|
|
6647
|
+
operationId: listOpsAgents
|
|
6648
|
+
summary: List connected AI agents
|
|
6649
|
+
description: |-
|
|
6650
|
+
The project's connected AI agents — one per authenticated trigger
|
|
6651
|
+
connector (Claude / Cursor / Copilot / Jules). These are the agent types
|
|
6652
|
+
`ops ack` accepts and the agents a queue item can be assigned to.
|
|
6653
|
+
|
|
6654
|
+
**Use case:** Discover which `agent` values an AI ack can use, e.g. after
|
|
6655
|
+
an `AGENT_NOT_CONNECTED` error.
|
|
6656
|
+
tags:
|
|
6657
|
+
- Agents
|
|
6658
|
+
parameters:
|
|
6659
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
6660
|
+
responses:
|
|
6661
|
+
'200':
|
|
6662
|
+
description: List connected AI agents
|
|
6663
|
+
content:
|
|
6664
|
+
application/json:
|
|
6665
|
+
schema:
|
|
6666
|
+
$ref: '#/components/schemas/ListOpsAgentsResponse'
|
|
6667
|
+
'400':
|
|
6668
|
+
$ref: '#/components/responses/BadRequest'
|
|
6669
|
+
'401':
|
|
6670
|
+
$ref: '#/components/responses/Unauthorized'
|
|
6671
|
+
'403':
|
|
6672
|
+
$ref: '#/components/responses/Forbidden'
|
|
6673
|
+
x-error-codes:
|
|
6674
|
+
- BAD_REQUEST
|
|
6675
|
+
- UNAUTHORIZED
|
|
6676
|
+
- FORBIDDEN
|
|
6677
|
+
x-cli:
|
|
6678
|
+
name: list
|
|
6679
|
+
/api/admin/ops/{handle}/comments:
|
|
6680
|
+
get:
|
|
6681
|
+
operationId: listOpsComments
|
|
6682
|
+
summary: List an item's comments
|
|
6683
|
+
description: |-
|
|
6684
|
+
List the comment thread on a queue item, oldest first. Each comment
|
|
6685
|
+
carries its author (a teammate email, or `system` for a comment authored by
|
|
6686
|
+
Jarvis — the AI agent), its markdown body, and `parentId` for the single
|
|
6687
|
+
level of threaded replies. Removed comments are omitted.
|
|
6688
|
+
|
|
6689
|
+
**Use case:** Read the discussion on an item before replying or acting on it.
|
|
6690
|
+
tags:
|
|
6691
|
+
- Comments
|
|
6692
|
+
parameters:
|
|
6693
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
6694
|
+
- name: handle
|
|
6695
|
+
in: path
|
|
6696
|
+
required: true
|
|
6697
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6698
|
+
schema:
|
|
6699
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6700
|
+
responses:
|
|
6701
|
+
'200':
|
|
6702
|
+
description: List an item's comments
|
|
6703
|
+
content:
|
|
6704
|
+
application/json:
|
|
6705
|
+
schema:
|
|
6706
|
+
$ref: '#/components/schemas/ListOpsCommentsResponse'
|
|
6707
|
+
'400':
|
|
6708
|
+
$ref: '#/components/responses/BadRequest'
|
|
6709
|
+
'401':
|
|
6710
|
+
$ref: '#/components/responses/Unauthorized'
|
|
6711
|
+
'403':
|
|
6712
|
+
$ref: '#/components/responses/Forbidden'
|
|
6713
|
+
'404':
|
|
6714
|
+
$ref: '#/components/responses/NotFound'
|
|
6715
|
+
x-error-codes:
|
|
6716
|
+
- BAD_REQUEST
|
|
6717
|
+
- UNAUTHORIZED
|
|
6718
|
+
- FORBIDDEN
|
|
6719
|
+
- NOT_FOUND
|
|
6720
|
+
x-cli:
|
|
6721
|
+
name: list
|
|
6722
|
+
positional:
|
|
6723
|
+
- handle
|
|
6724
|
+
post:
|
|
6725
|
+
operationId: createOpsComment
|
|
6726
|
+
summary: Comment on an item
|
|
6727
|
+
description: |-
|
|
6728
|
+
Append a comment to a queue item's thread. The body is markdown (mentions
|
|
6729
|
+
like `@teammate` notify that person; `@shipeasy` asks Jarvis, the AI agent,
|
|
6730
|
+
to reply). Pass `parentId` to reply under an existing top-level comment
|
|
6731
|
+
(one level of threading — a reply to a reply attaches to the same parent).
|
|
5824
6732
|
|
|
5825
6733
|
Create-only and append-only, so it is safe for restricted ops keys — the
|
|
5826
6734
|
same channel the ops loop and Jarvis use to leave a note on an item.
|
|
@@ -6247,7 +7155,9 @@ paths:
|
|
|
6247
7155
|
description: |-
|
|
6248
7156
|
Returns the project's FIRED alerts as a **bare JSON array** (no pagination envelope), ordered by `createdAt desc`. Defaults to the currently-firing ones (`status=active`); pass a `status` to widen to resolved/dismissed history or `all`.
|
|
6249
7157
|
|
|
6250
|
-
|
|
7158
|
+
A fired alert is an **instance** of an alert rule, and an instance IS its ops queue item — the same row `/api/admin/ops` returns with `type: "alert"`, viewed through the alert lens. One rule produces many instances over its life and at most one is open at a time: when the condition clears the instance closes, and the next firing is a NEW instance with its own id and history. That is why `severity` reads off the rule (the queue item carries it as `priority`) and why resolving the queue item and clearing the alert are one act, not two rows to keep in step.
|
|
7159
|
+
|
|
7160
|
+
Instances are opened only by the platform — the UI's killswitch handlers plus the worker's analysis consumer and alerts cron — never filed by hand, so this surface is list + triage (via PATCH), with no create. The rules that *define* metric-threshold alerts live at `/api/admin/alert-rules`.
|
|
6251
7161
|
|
|
6252
7162
|
**Use case:** Snapshot what is currently firing for an on-call view or the home Alerts block, or pull `status=all` to audit how a noisy rule has behaved over time.
|
|
6253
7163
|
tags:
|
|
@@ -6331,7 +7241,7 @@ paths:
|
|
|
6331
7241
|
description: |-
|
|
6332
7242
|
Triage writes on one fired alert — the only mutations this surface allows. All body fields are optional (at least one required); only the fields present are changed.
|
|
6333
7243
|
|
|
6334
|
-
- **`status`** — flip between `active` / `resolved` / `dismissed`. `resolved` and `dismissed` stamp `resolvedAt` / `dismissedAt`; `active` re-opens and clears both.
|
|
7244
|
+
- **`status`** — flip between `active` / `resolved` / `dismissed`. `resolved` and `dismissed` stamp `resolvedAt` / `dismissedAt`; `active` re-opens and clears both. These write the underlying queue item's own status (`resolved` / `wont_fix` / `open`), so clearing an alert here and resolving it in the ops queue are the same act. A cleared instance is never revived: if the condition fires again it opens a NEW instance with its own id.
|
|
6335
7245
|
- **`assigneeId`** — the PERSON owner (a `users.id`), or `null` to unassign.
|
|
6336
7246
|
- **`agent`** — the AGENT owner: a connected trigger connector's id, or the built-in `"jarvis"` (**Enterprise plan only** — `403` otherwise), or `null` to clear. Person and agent halves are independent.
|
|
6337
7247
|
|
|
@@ -6348,7 +7258,7 @@ paths:
|
|
|
6348
7258
|
- name: id
|
|
6349
7259
|
in: path
|
|
6350
7260
|
required: true
|
|
6351
|
-
description: Stable opaque
|
|
7261
|
+
description: Stable opaque instance id — the same id as the `alert` ops item this instance is.
|
|
6352
7262
|
schema:
|
|
6353
7263
|
$ref: '#/components/schemas/ResourceId'
|
|
6354
7264
|
requestBody:
|
|
@@ -6822,11 +7732,12 @@ paths:
|
|
|
6822
7732
|
- name: limit
|
|
6823
7733
|
in: query
|
|
6824
7734
|
required: false
|
|
6825
|
-
description: Max keys to return (1–500).
|
|
7735
|
+
description: Max keys to return (1–500). Defaults to 200.
|
|
6826
7736
|
schema:
|
|
6827
7737
|
type: integer
|
|
6828
7738
|
minimum: 1
|
|
6829
7739
|
maximum: 500
|
|
7740
|
+
default: 200
|
|
6830
7741
|
- name: offset
|
|
6831
7742
|
in: query
|
|
6832
7743
|
required: false
|
|
@@ -8863,6 +9774,7 @@ paths:
|
|
|
8863
9774
|
expires_at: null
|
|
8864
9775
|
created_by_email: ana@example.com
|
|
8865
9776
|
name: production back-end
|
|
9777
|
+
description: Held by the checkout service; rotate with the quarterly credential sweep
|
|
8866
9778
|
scopes:
|
|
8867
9779
|
- gates:evaluate
|
|
8868
9780
|
- events:write
|
|
@@ -8962,6 +9874,84 @@ paths:
|
|
|
8962
9874
|
- PLAN_LIMIT
|
|
8963
9875
|
x-cli:
|
|
8964
9876
|
name: create
|
|
9877
|
+
/api/admin/keys/{id}:
|
|
9878
|
+
patch:
|
|
9879
|
+
operationId: updateKey
|
|
9880
|
+
summary: Update an API key's label
|
|
9881
|
+
description: |-
|
|
9882
|
+
Renames a key or re-notes what it is for. **Only `name` and `description` are editable** — everything that gives the key its authority (`type`, `env`, `scopes`, `expires_at`) is fixed at mint, because the worker derives the read env and permissions from the key itself. To change any of those, rotate: mint a replacement and revoke this one.
|
|
9883
|
+
|
|
9884
|
+
Omitted fields are left untouched; send `null` to clear one. Returns the updated key row. Revoked keys can still be relabelled (the audit trail outlives the credential). Returns `404` if no such key exists in the project.
|
|
9885
|
+
|
|
9886
|
+
**Use case:** A key minted by `shipeasy setup` carries an auto-composed provenance label — rename it to the service that actually holds it and note the rotation owner.
|
|
9887
|
+
tags:
|
|
9888
|
+
- API Keys
|
|
9889
|
+
parameters:
|
|
9890
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
9891
|
+
- name: id
|
|
9892
|
+
in: path
|
|
9893
|
+
required: true
|
|
9894
|
+
description: Stable opaque key id (UUID) returned by `create` / `list`.
|
|
9895
|
+
schema:
|
|
9896
|
+
$ref: '#/components/schemas/ResourceId'
|
|
9897
|
+
requestBody:
|
|
9898
|
+
required: true
|
|
9899
|
+
content:
|
|
9900
|
+
application/json:
|
|
9901
|
+
schema:
|
|
9902
|
+
$ref: '#/components/schemas/UpdateKeyRequest'
|
|
9903
|
+
examples:
|
|
9904
|
+
rename:
|
|
9905
|
+
summary: Rename and note the key
|
|
9906
|
+
value:
|
|
9907
|
+
name: checkout-service · production
|
|
9908
|
+
description: Held by the checkout service; rotation owner is the payments team
|
|
9909
|
+
clearDescription:
|
|
9910
|
+
summary: Clear the note
|
|
9911
|
+
value:
|
|
9912
|
+
description: null
|
|
9913
|
+
responses:
|
|
9914
|
+
'200':
|
|
9915
|
+
description: Update an API key's label
|
|
9916
|
+
content:
|
|
9917
|
+
application/json:
|
|
9918
|
+
schema:
|
|
9919
|
+
$ref: '#/components/schemas/KeyRecord'
|
|
9920
|
+
example:
|
|
9921
|
+
id: 3f2a9b1c-7d4e-4a8f-9c2b-1e5d6f7a8b90
|
|
9922
|
+
type: server
|
|
9923
|
+
env: prod
|
|
9924
|
+
created_at: '2026-05-09T16:01:22.000Z'
|
|
9925
|
+
revoked_at: null
|
|
9926
|
+
expires_at: null
|
|
9927
|
+
created_by_email: ana@example.com
|
|
9928
|
+
name: checkout-service · production
|
|
9929
|
+
description: Held by the checkout service; rotation owner is the payments team
|
|
9930
|
+
scopes:
|
|
9931
|
+
- gates:evaluate
|
|
9932
|
+
- events:write
|
|
9933
|
+
last4: a1b2
|
|
9934
|
+
'400':
|
|
9935
|
+
$ref: '#/components/responses/BadRequest'
|
|
9936
|
+
'401':
|
|
9937
|
+
$ref: '#/components/responses/Unauthorized'
|
|
9938
|
+
'403':
|
|
9939
|
+
$ref: '#/components/responses/Forbidden'
|
|
9940
|
+
'404':
|
|
9941
|
+
$ref: '#/components/responses/NotFound'
|
|
9942
|
+
'409':
|
|
9943
|
+
$ref: '#/components/responses/Conflict'
|
|
9944
|
+
'422':
|
|
9945
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
9946
|
+
x-error-codes:
|
|
9947
|
+
- UNAUTHORIZED
|
|
9948
|
+
- FORBIDDEN
|
|
9949
|
+
- NOT_FOUND
|
|
9950
|
+
- VALIDATION
|
|
9951
|
+
x-cli:
|
|
9952
|
+
name: update
|
|
9953
|
+
positional:
|
|
9954
|
+
- id
|
|
8965
9955
|
/api/admin/keys/{id}/revoke:
|
|
8966
9956
|
post:
|
|
8967
9957
|
operationId: revokeKey
|
|
@@ -9074,30 +10064,310 @@ paths:
|
|
|
9074
10064
|
- FORBIDDEN
|
|
9075
10065
|
x-cli:
|
|
9076
10066
|
name: search
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
10067
|
+
/api/admin/tags:
|
|
10068
|
+
get:
|
|
10069
|
+
operationId: listTags
|
|
10070
|
+
summary: List the project's tags
|
|
10071
|
+
description: |-
|
|
10072
|
+
Returns every tag in the project — the shared roster any item (queue items, flags, configs, kill switches, metrics, tracked errors, alert rules, experiments) can carry. Sorted by name.
|
|
10073
|
+
|
|
10074
|
+
**Use case:** See which tags already exist before tagging an item, so you reuse `ios` instead of minting `iOS-app`.
|
|
10075
|
+
tags:
|
|
10076
|
+
- Tags
|
|
10077
|
+
parameters:
|
|
10078
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
10079
|
+
- name: q
|
|
10080
|
+
in: query
|
|
10081
|
+
required: false
|
|
10082
|
+
description: Case-insensitive substring filter on the tag name. Omit to return every tag.
|
|
10083
|
+
schema:
|
|
10084
|
+
type: string
|
|
10085
|
+
maxLength: 64
|
|
10086
|
+
responses:
|
|
10087
|
+
'200':
|
|
10088
|
+
description: List the project's tags
|
|
10089
|
+
content:
|
|
10090
|
+
application/json:
|
|
10091
|
+
schema:
|
|
10092
|
+
$ref: '#/components/schemas/ListTagsResponse'
|
|
10093
|
+
example:
|
|
10094
|
+
- id: tag_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
10095
|
+
name: checkout
|
|
10096
|
+
- id: tag_01j7w8a1b2c3d4e5f6g7h8i9j1
|
|
10097
|
+
name: ios
|
|
10098
|
+
'400':
|
|
10099
|
+
$ref: '#/components/responses/BadRequest'
|
|
10100
|
+
'401':
|
|
10101
|
+
$ref: '#/components/responses/Unauthorized'
|
|
10102
|
+
'403':
|
|
10103
|
+
$ref: '#/components/responses/Forbidden'
|
|
10104
|
+
'404':
|
|
10105
|
+
$ref: '#/components/responses/NotFound'
|
|
10106
|
+
'409':
|
|
10107
|
+
$ref: '#/components/responses/Conflict'
|
|
10108
|
+
'422':
|
|
10109
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
10110
|
+
x-error-codes:
|
|
10111
|
+
- BAD_REQUEST
|
|
10112
|
+
- UNAUTHORIZED
|
|
10113
|
+
- FORBIDDEN
|
|
10114
|
+
x-cli:
|
|
10115
|
+
name: list
|
|
10116
|
+
/api/admin/tags/{entityType}/{entityId}:
|
|
10117
|
+
get:
|
|
10118
|
+
operationId: getEntityTags
|
|
10119
|
+
summary: Read an item's tags
|
|
10120
|
+
description: |-
|
|
10121
|
+
Returns the tags attached to one item. The item is addressed by kind (`entityType`) plus its handle, so the same call reads tags off a queue item, a flag, a config, a kill switch, a metric, a tracked error, an alert rule, or an experiment.
|
|
10122
|
+
|
|
10123
|
+
**Use case:** Check an item's current tags before editing them.
|
|
10124
|
+
tags:
|
|
10125
|
+
- Tags
|
|
10126
|
+
parameters:
|
|
10127
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
10128
|
+
- name: entityType
|
|
10129
|
+
in: path
|
|
10130
|
+
required: true
|
|
10131
|
+
description: The kind of item — `ops`, `flag`, `config`, `killswitch`, `metric`, `error`, `alert_rule`, or `experiment`.
|
|
10132
|
+
schema:
|
|
10133
|
+
$ref: '#/components/schemas/TaggableEntityType'
|
|
10134
|
+
- name: entityId
|
|
10135
|
+
in: path
|
|
10136
|
+
required: true
|
|
10137
|
+
description: The item's handle — an ops item's number (e.g. `7`) or id; a flag/config/killswitch/metric/alert rule/experiment's name or id; a tracked error's id.
|
|
10138
|
+
schema:
|
|
10139
|
+
$ref: '#/components/schemas/ResourceId'
|
|
10140
|
+
responses:
|
|
10141
|
+
'200':
|
|
10142
|
+
description: Read an item's tags
|
|
10143
|
+
content:
|
|
10144
|
+
application/json:
|
|
10145
|
+
schema:
|
|
10146
|
+
$ref: '#/components/schemas/EntityTagsResponse'
|
|
10147
|
+
example:
|
|
10148
|
+
entityType: ops
|
|
10149
|
+
entityId: fb_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
10150
|
+
tags:
|
|
10151
|
+
- checkout
|
|
10152
|
+
- ios
|
|
10153
|
+
'400':
|
|
10154
|
+
$ref: '#/components/responses/BadRequest'
|
|
10155
|
+
'401':
|
|
10156
|
+
$ref: '#/components/responses/Unauthorized'
|
|
10157
|
+
'403':
|
|
10158
|
+
$ref: '#/components/responses/Forbidden'
|
|
10159
|
+
'404':
|
|
10160
|
+
$ref: '#/components/responses/NotFound'
|
|
10161
|
+
'409':
|
|
10162
|
+
$ref: '#/components/responses/Conflict'
|
|
10163
|
+
'422':
|
|
10164
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
10165
|
+
x-error-codes:
|
|
10166
|
+
- BAD_REQUEST
|
|
10167
|
+
- UNAUTHORIZED
|
|
10168
|
+
- FORBIDDEN
|
|
10169
|
+
- NOT_FOUND
|
|
10170
|
+
x-cli:
|
|
10171
|
+
name: get
|
|
10172
|
+
positional:
|
|
10173
|
+
- entityType
|
|
10174
|
+
- entityId
|
|
10175
|
+
put:
|
|
10176
|
+
operationId: setEntityTags
|
|
10177
|
+
summary: Replace an item's tags
|
|
10178
|
+
description: |-
|
|
10179
|
+
Replaces the item's whole tag set with `tags`: names not yet in the project are created, attached names not in the list are detached, and `[]` clears every tag. Names are deduped case-insensitively, reusing an existing tag's casing (sending `iOS` when `ios` exists attaches `ios`).
|
|
10180
|
+
|
|
10181
|
+
**Use cases**
|
|
10182
|
+
|
|
10183
|
+
- **Tag an item** — `{ "tags": ["checkout", "ios"] }`.
|
|
10184
|
+
- **Clear tags** — `{ "tags": [] }`.
|
|
10185
|
+
|
|
10186
|
+
To add or remove a few tags without restating the rest, use the incremental `PATCH` instead.
|
|
10187
|
+
tags:
|
|
10188
|
+
- Tags
|
|
10189
|
+
parameters:
|
|
10190
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
10191
|
+
- name: entityType
|
|
10192
|
+
in: path
|
|
10193
|
+
required: true
|
|
10194
|
+
description: The kind of item — `ops`, `flag`, `config`, `killswitch`, `metric`, `error`, `alert_rule`, or `experiment`.
|
|
10195
|
+
schema:
|
|
10196
|
+
$ref: '#/components/schemas/TaggableEntityType'
|
|
10197
|
+
- name: entityId
|
|
10198
|
+
in: path
|
|
10199
|
+
required: true
|
|
10200
|
+
description: The item's handle — an ops item's number (e.g. `7`) or id; a flag/config/killswitch/metric/alert rule/experiment's name or id; a tracked error's id.
|
|
10201
|
+
schema:
|
|
10202
|
+
$ref: '#/components/schemas/ResourceId'
|
|
10203
|
+
requestBody:
|
|
10204
|
+
required: true
|
|
10205
|
+
content:
|
|
10206
|
+
application/json:
|
|
10207
|
+
schema:
|
|
10208
|
+
$ref: '#/components/schemas/SetEntityTagsRequest'
|
|
10209
|
+
examples:
|
|
10210
|
+
tag:
|
|
10211
|
+
summary: Set the item's tags
|
|
10212
|
+
value:
|
|
10213
|
+
tags:
|
|
10214
|
+
- checkout
|
|
10215
|
+
- ios
|
|
10216
|
+
clear:
|
|
10217
|
+
summary: Remove every tag
|
|
10218
|
+
value:
|
|
10219
|
+
tags: []
|
|
10220
|
+
responses:
|
|
10221
|
+
'200':
|
|
10222
|
+
description: Replace an item's tags
|
|
10223
|
+
content:
|
|
10224
|
+
application/json:
|
|
10225
|
+
schema:
|
|
10226
|
+
$ref: '#/components/schemas/EntityTagsResponse'
|
|
10227
|
+
example:
|
|
10228
|
+
entityType: ops
|
|
10229
|
+
entityId: fb_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
10230
|
+
tags:
|
|
10231
|
+
- checkout
|
|
10232
|
+
- ios
|
|
10233
|
+
'400':
|
|
10234
|
+
$ref: '#/components/responses/BadRequest'
|
|
10235
|
+
'401':
|
|
10236
|
+
$ref: '#/components/responses/Unauthorized'
|
|
10237
|
+
'403':
|
|
10238
|
+
$ref: '#/components/responses/Forbidden'
|
|
10239
|
+
'404':
|
|
10240
|
+
$ref: '#/components/responses/NotFound'
|
|
10241
|
+
'409':
|
|
10242
|
+
$ref: '#/components/responses/Conflict'
|
|
10243
|
+
'422':
|
|
10244
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
10245
|
+
x-error-codes:
|
|
10246
|
+
- BAD_REQUEST
|
|
10247
|
+
- UNAUTHORIZED
|
|
10248
|
+
- FORBIDDEN
|
|
10249
|
+
- NOT_FOUND
|
|
10250
|
+
- VALIDATION
|
|
10251
|
+
x-cli:
|
|
10252
|
+
name: set
|
|
10253
|
+
positional:
|
|
10254
|
+
- entityType
|
|
10255
|
+
- entityId
|
|
10256
|
+
patch:
|
|
10257
|
+
operationId: updateEntityTags
|
|
10258
|
+
summary: Add or remove tags on an item
|
|
10259
|
+
description: |-
|
|
10260
|
+
Edits an item's tags incrementally: attaches every name in `add` (creating project tags as needed) and detaches every name in `remove`, leaving the item's other tags untouched. Matching is case-insensitive; a name in both lists ends up removed.
|
|
10261
|
+
|
|
10262
|
+
**Use cases**
|
|
10263
|
+
|
|
10264
|
+
- **Add a tag** — `{ "add": ["regression"] }`.
|
|
10265
|
+
- **Swap a tag** — `{ "add": ["p1"], "remove": ["p2"] }`.
|
|
10266
|
+
tags:
|
|
10267
|
+
- Tags
|
|
10268
|
+
parameters:
|
|
10269
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
10270
|
+
- name: entityType
|
|
10271
|
+
in: path
|
|
10272
|
+
required: true
|
|
10273
|
+
description: The kind of item — `ops`, `flag`, `config`, `killswitch`, `metric`, `error`, `alert_rule`, or `experiment`.
|
|
10274
|
+
schema:
|
|
10275
|
+
$ref: '#/components/schemas/TaggableEntityType'
|
|
10276
|
+
- name: entityId
|
|
10277
|
+
in: path
|
|
10278
|
+
required: true
|
|
10279
|
+
description: The item's handle — an ops item's number (e.g. `7`) or id; a flag/config/killswitch/metric/alert rule/experiment's name or id; a tracked error's id.
|
|
10280
|
+
schema:
|
|
10281
|
+
$ref: '#/components/schemas/ResourceId'
|
|
10282
|
+
requestBody:
|
|
10283
|
+
required: true
|
|
10284
|
+
content:
|
|
10285
|
+
application/json:
|
|
10286
|
+
schema:
|
|
10287
|
+
$ref: '#/components/schemas/UpdateEntityTagsRequest'
|
|
10288
|
+
examples:
|
|
10289
|
+
add:
|
|
10290
|
+
summary: Attach one tag
|
|
10291
|
+
value:
|
|
10292
|
+
add:
|
|
10293
|
+
- regression
|
|
10294
|
+
swap:
|
|
10295
|
+
summary: Replace one tag with another
|
|
10296
|
+
value:
|
|
10297
|
+
add:
|
|
10298
|
+
- p1
|
|
10299
|
+
remove:
|
|
10300
|
+
- p2
|
|
10301
|
+
responses:
|
|
10302
|
+
'200':
|
|
10303
|
+
description: Add or remove tags on an item
|
|
10304
|
+
content:
|
|
10305
|
+
application/json:
|
|
10306
|
+
schema:
|
|
10307
|
+
$ref: '#/components/schemas/EntityTagsResponse'
|
|
10308
|
+
example:
|
|
10309
|
+
entityType: ops
|
|
10310
|
+
entityId: fb_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
10311
|
+
tags:
|
|
10312
|
+
- checkout
|
|
10313
|
+
- ios
|
|
10314
|
+
'400':
|
|
10315
|
+
$ref: '#/components/responses/BadRequest'
|
|
10316
|
+
'401':
|
|
10317
|
+
$ref: '#/components/responses/Unauthorized'
|
|
10318
|
+
'403':
|
|
10319
|
+
$ref: '#/components/responses/Forbidden'
|
|
10320
|
+
'404':
|
|
10321
|
+
$ref: '#/components/responses/NotFound'
|
|
10322
|
+
'409':
|
|
10323
|
+
$ref: '#/components/responses/Conflict'
|
|
10324
|
+
'422':
|
|
10325
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
10326
|
+
x-error-codes:
|
|
10327
|
+
- BAD_REQUEST
|
|
10328
|
+
- UNAUTHORIZED
|
|
10329
|
+
- FORBIDDEN
|
|
10330
|
+
- NOT_FOUND
|
|
10331
|
+
- VALIDATION
|
|
10332
|
+
x-cli:
|
|
10333
|
+
name: update
|
|
10334
|
+
positional:
|
|
10335
|
+
- entityType
|
|
10336
|
+
- entityId
|
|
10337
|
+
components:
|
|
10338
|
+
securitySchemes:
|
|
10339
|
+
bearerSdkKey:
|
|
10340
|
+
type: http
|
|
10341
|
+
scheme: bearer
|
|
10342
|
+
bearerFormat: sdk_admin_*
|
|
10343
|
+
description: 'Pass an admin SDK key as `Authorization: Bearer sdk_admin_…`. Mint via `POST /api/admin/keys` with `type: "admin"`.'
|
|
10344
|
+
clientSdkKey:
|
|
10345
|
+
type: apiKey
|
|
10346
|
+
in: header
|
|
10347
|
+
name: X-SDK-Key
|
|
10348
|
+
description: |-
|
|
10349
|
+
Pass a **client** SDK key as `X-SDK-Key: sdk_client_…`. Used only by the public ticket intake (`POST /ops/bug`, `POST /ops/feature-request`), which is served by the edge worker rather than the admin API.
|
|
10350
|
+
|
|
10351
|
+
Client keys are designed to be embedded in shipped code — a CLI, an installer, a browser bundle — so presenting one here is safe by construction: it can do nothing but file a rate-limited ticket into its own project, in a state a human must approve. It carries no read access and cannot reach any other operation in this contract.
|
|
10352
|
+
|
|
10353
|
+
The key must additionally carry the `tickets:public_create` scope, and its project must have public ticket creation enabled.
|
|
10354
|
+
parameters:
|
|
10355
|
+
ProjectId:
|
|
10356
|
+
name: X-Project-Id
|
|
10357
|
+
in: header
|
|
10358
|
+
required: false
|
|
10359
|
+
description: Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
|
|
10360
|
+
schema:
|
|
10361
|
+
type: string
|
|
10362
|
+
PaginationLimit:
|
|
10363
|
+
name: limit
|
|
10364
|
+
in: query
|
|
10365
|
+
required: false
|
|
10366
|
+
description: Page size (1–500). Defaults to 100.
|
|
10367
|
+
schema:
|
|
10368
|
+
type: integer
|
|
10369
|
+
minimum: 1
|
|
10370
|
+
maximum: 500
|
|
9101
10371
|
default: 100
|
|
9102
10372
|
PaginationCursor:
|
|
9103
10373
|
name: cursor
|
|
@@ -10185,6 +11455,85 @@ components:
|
|
|
10185
11455
|
- createdAt
|
|
10186
11456
|
additionalProperties: false
|
|
10187
11457
|
description: Recent audit rows for one gate, newest first.
|
|
11458
|
+
GateWhitelistAttr:
|
|
11459
|
+
type: string
|
|
11460
|
+
enum:
|
|
11461
|
+
- email
|
|
11462
|
+
- user_id
|
|
11463
|
+
description: Which identity attribute the whitelist matches on. `email` compares the caller's `email`; `user_id` compares the caller's `userID`. A whitelist matches on exactly one of the two at a time.
|
|
11464
|
+
GateWhitelist:
|
|
11465
|
+
type: object
|
|
11466
|
+
properties:
|
|
11467
|
+
id:
|
|
11468
|
+
type: string
|
|
11469
|
+
description: Resolved gate id.
|
|
11470
|
+
name:
|
|
11471
|
+
type: string
|
|
11472
|
+
description: The gate's stable `name`.
|
|
11473
|
+
attr:
|
|
11474
|
+
$ref: '#/components/schemas/GateWhitelistAttr'
|
|
11475
|
+
entries:
|
|
11476
|
+
type: array
|
|
11477
|
+
items:
|
|
11478
|
+
type: string
|
|
11479
|
+
minLength: 1
|
|
11480
|
+
description: The whitelisted identities, in the order they are stored. Deduplicated case-sensitively; an empty array means the gate has no whitelist.
|
|
11481
|
+
required:
|
|
11482
|
+
- id
|
|
11483
|
+
- name
|
|
11484
|
+
- attr
|
|
11485
|
+
- entries
|
|
11486
|
+
additionalProperties: false
|
|
11487
|
+
description: A gate's whitelist — the always-first allowlist that admits the listed identities before any targeting rule or rollout runs. Backed by the pinned `whitelist` entry at the head of the gate's `stack`, so it is the same list the dashboard's Whitelist block edits.
|
|
11488
|
+
SetGateWhitelistRequest:
|
|
11489
|
+
type: object
|
|
11490
|
+
properties:
|
|
11491
|
+
attr:
|
|
11492
|
+
anyOf:
|
|
11493
|
+
- $ref: '#/components/schemas/GateWhitelistAttr'
|
|
11494
|
+
description: Identity attribute to match on. Defaults to the whitelist's current attribute, or `email` when the gate has no whitelist yet.
|
|
11495
|
+
entries:
|
|
11496
|
+
type: array
|
|
11497
|
+
items:
|
|
11498
|
+
type: string
|
|
11499
|
+
minLength: 1
|
|
11500
|
+
description: The complete whitelist after the call. Pass `[]` to remove the whitelist from the gate entirely.
|
|
11501
|
+
required:
|
|
11502
|
+
- entries
|
|
11503
|
+
additionalProperties: false
|
|
11504
|
+
description: Body for `PUT /api/admin/gates/{id}/whitelist`. Replaces the whole list — idempotent, and the only call that can switch `attr` or clear the whitelist.
|
|
11505
|
+
AddToGateWhitelistRequest:
|
|
11506
|
+
type: object
|
|
11507
|
+
properties:
|
|
11508
|
+
attr:
|
|
11509
|
+
anyOf:
|
|
11510
|
+
- $ref: '#/components/schemas/GateWhitelistAttr'
|
|
11511
|
+
description: Identity attribute to match on. Only honoured when the gate has no whitelist yet (this call creates it); passing an attribute that disagrees with an existing whitelist is a 409 rather than a silent re-key of the entries already there.
|
|
11512
|
+
entries:
|
|
11513
|
+
type: array
|
|
11514
|
+
minItems: 1
|
|
11515
|
+
items:
|
|
11516
|
+
type: string
|
|
11517
|
+
minLength: 1
|
|
11518
|
+
description: Identities to admit. Already-listed entries are skipped, so the call is idempotent.
|
|
11519
|
+
required:
|
|
11520
|
+
- entries
|
|
11521
|
+
additionalProperties: false
|
|
11522
|
+
description: Body for `POST /api/admin/gates/{id}/whitelist`. Adds entries to the whitelist, creating it if the gate doesn't have one.
|
|
11523
|
+
RemoveFromGateWhitelistRequest:
|
|
11524
|
+
type: object
|
|
11525
|
+
properties:
|
|
11526
|
+
entries:
|
|
11527
|
+
type: array
|
|
11528
|
+
minItems: 1
|
|
11529
|
+
items:
|
|
11530
|
+
type: string
|
|
11531
|
+
minLength: 1
|
|
11532
|
+
description: Identities to stop admitting. Entries that aren't listed are skipped, so the call is idempotent.
|
|
11533
|
+
required:
|
|
11534
|
+
- entries
|
|
11535
|
+
additionalProperties: false
|
|
11536
|
+
description: 'Body for `DELETE /api/admin/gates/{id}/whitelist`. Removes entries from the whitelist. Removing the last entry leaves an empty whitelist in place — use `PUT` with `entries: []` to drop the block itself.'
|
|
10188
11537
|
ExperimentApiRow:
|
|
10189
11538
|
type: object
|
|
10190
11539
|
properties:
|
|
@@ -10502,13 +11851,10 @@ components:
|
|
|
10502
11851
|
aggregation:
|
|
10503
11852
|
type: string
|
|
10504
11853
|
enum:
|
|
10505
|
-
- count_users
|
|
10506
11854
|
- count_events
|
|
10507
|
-
- retention_7d
|
|
10508
|
-
- retention_30d
|
|
10509
11855
|
- sum
|
|
10510
11856
|
- avg
|
|
10511
|
-
description: Reducer for the `event` form. Defaults to `count_users
|
|
11857
|
+
description: 'Reducer for the `event` form. Defaults to `count_events`. `count_users` was removed: Analytics Engine samples rows and weights the survivors, and a distinct count cannot be reweighted, so it under-reports by the sample interval. `retention_7d` / `retention_30d` were removed on 2026-08-10: the day count reached no query and no reducer, so both produced the same number as a distinct user count and reported it as a returning-user rate.'
|
|
10512
11858
|
value:
|
|
10513
11859
|
type: string
|
|
10514
11860
|
minLength: 1
|
|
@@ -12214,12 +13560,76 @@ components:
|
|
|
12214
13560
|
- version
|
|
12215
13561
|
- published
|
|
12216
13562
|
additionalProperties: false
|
|
12217
|
-
|
|
13563
|
+
ToggleKillswitchRequest:
|
|
12218
13564
|
type: object
|
|
12219
13565
|
properties:
|
|
12220
|
-
|
|
12221
|
-
|
|
12222
|
-
|
|
13566
|
+
switchKey:
|
|
13567
|
+
anyOf:
|
|
13568
|
+
- type: string
|
|
13569
|
+
maxLength: 64
|
|
13570
|
+
pattern: ^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$
|
|
13571
|
+
- type: 'null'
|
|
13572
|
+
description: Which target to flip. Omit (or `null`) to flip the killswitch's own flat `value`; name a switch key to flip that nested sub-switch instead, creating the entry if it doesn't exist yet.
|
|
13573
|
+
value:
|
|
13574
|
+
anyOf:
|
|
13575
|
+
- type: boolean
|
|
13576
|
+
- type: 'null'
|
|
13577
|
+
description: The value to publish. Omit (or `null`) to flip whatever is stored now — read-modify-write in one call. Pass an explicit `true`/`false` to make the call idempotent, so a retry can't undo the first attempt.
|
|
13578
|
+
env:
|
|
13579
|
+
anyOf:
|
|
13580
|
+
- $ref: '#/components/schemas/Env'
|
|
13581
|
+
description: Environment to publish on. Defaults to `prod` — the environment an incident response means when it says "kill it".
|
|
13582
|
+
additionalProperties: false
|
|
13583
|
+
description: |-
|
|
13584
|
+
Body for `POST /api/admin/killswitches/{id}/toggle`. Every field is optional, so the four useful calls read as one method with a widening argument list:
|
|
13585
|
+
|
|
13586
|
+
- `{}` — flip the flat value on prod.
|
|
13587
|
+
- `{ "switchKey": "eu_region" }` — flip that sub-switch on prod.
|
|
13588
|
+
- `{ "switchKey": "eu_region", "value": true }` — set that sub-switch on prod, idempotently.
|
|
13589
|
+
- `{ "switchKey": "eu_region", "value": true, "env": "staging" }` — the same, on a chosen env.
|
|
13590
|
+
ToggleKillswitchResponse:
|
|
13591
|
+
type: object
|
|
13592
|
+
properties:
|
|
13593
|
+
id:
|
|
13594
|
+
type: string
|
|
13595
|
+
description: Resolved killswitch id.
|
|
13596
|
+
env:
|
|
13597
|
+
$ref: '#/components/schemas/Env'
|
|
13598
|
+
switchKey:
|
|
13599
|
+
anyOf:
|
|
13600
|
+
- type: string
|
|
13601
|
+
maxLength: 64
|
|
13602
|
+
pattern: ^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$
|
|
13603
|
+
- type: 'null'
|
|
13604
|
+
description: The sub-switch that was flipped, or `null` when the flat `value` was.
|
|
13605
|
+
previous:
|
|
13606
|
+
type: boolean
|
|
13607
|
+
description: The value that was in effect before this call. Equal to `value` when an idempotent `value` matched what was already stored.
|
|
13608
|
+
value:
|
|
13609
|
+
type: boolean
|
|
13610
|
+
description: The value now in effect on `env`.
|
|
13611
|
+
version:
|
|
13612
|
+
type: integer
|
|
13613
|
+
minimum: -9007199254740991
|
|
13614
|
+
maximum: 9007199254740991
|
|
13615
|
+
description: Newly published version on `env`.
|
|
13616
|
+
published:
|
|
13617
|
+
$ref: '#/components/schemas/KillswitchValue'
|
|
13618
|
+
required:
|
|
13619
|
+
- id
|
|
13620
|
+
- env
|
|
13621
|
+
- switchKey
|
|
13622
|
+
- previous
|
|
13623
|
+
- value
|
|
13624
|
+
- version
|
|
13625
|
+
- published
|
|
13626
|
+
additionalProperties: false
|
|
13627
|
+
UniverseParam:
|
|
13628
|
+
type: object
|
|
13629
|
+
properties:
|
|
13630
|
+
name:
|
|
13631
|
+
type: string
|
|
13632
|
+
minLength: 1
|
|
12223
13633
|
maxLength: 128
|
|
12224
13634
|
pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
|
|
12225
13635
|
description: Param key, referenced by `groups[].params` on every experiment in the universe.
|
|
@@ -12861,253 +14271,60 @@ components:
|
|
|
12861
14271
|
- id
|
|
12862
14272
|
additionalProperties: false
|
|
12863
14273
|
description: Response for `PATCH /api/admin/attributes/{id}`.
|
|
14274
|
+
MetricDisplayConfig:
|
|
14275
|
+
description: How the metric's series is DRAWN, as opposed to what it measures. Both parts used to be DSL functions (`expected(q, seasonal)`, `forecast(q, …)`), which meant turning a band on minted a different metric; they are properties now, so every chart of the metric picks them up and nothing that JUDGES the metric — an alert rule, the experiment analyzer — reads them at all.
|
|
14276
|
+
type: object
|
|
14277
|
+
properties:
|
|
14278
|
+
band:
|
|
14279
|
+
description: Shade the seasonal baseline around the series. The fit is the median of this hour of the week over the four weeks before the window, and it is the SAME fit an `anomaly` alert rule fires on — so the shaded region is exactly where such a rule would stay quiet, whether or not one exists.
|
|
14280
|
+
type: object
|
|
14281
|
+
properties:
|
|
14282
|
+
method:
|
|
14283
|
+
type: string
|
|
14284
|
+
enum:
|
|
14285
|
+
- seasonal
|
|
14286
|
+
sigma:
|
|
14287
|
+
type: number
|
|
14288
|
+
exclusiveMinimum: 0
|
|
14289
|
+
description: Half-width of the band in sigma-equivalents. Omit for 3, the sigma an alert rule also defaults to.
|
|
14290
|
+
required:
|
|
14291
|
+
- method
|
|
14292
|
+
additionalProperties: false
|
|
14293
|
+
forecast:
|
|
14294
|
+
description: Project the series past the end of the window. Projected buckets are marked, so a chart can draw an estimate differently from a measurement.
|
|
14295
|
+
type: object
|
|
14296
|
+
properties:
|
|
14297
|
+
method:
|
|
14298
|
+
type: string
|
|
14299
|
+
enum:
|
|
14300
|
+
- linear
|
|
14301
|
+
- seasonal
|
|
14302
|
+
description: '`linear` continues a least-squares slope over the window it is already reading. `seasonal` de-seasonalises against the four weeks before the window, fits the trend on the remainder and adds the hour-of-week term back — ask for it when the metric has a shape.'
|
|
14303
|
+
horizon:
|
|
14304
|
+
type: integer
|
|
14305
|
+
minimum: 1
|
|
14306
|
+
maximum: 500
|
|
14307
|
+
description: Buckets to project. Omit for a quarter of the window, which is the same claim at every bucket width.
|
|
14308
|
+
required:
|
|
14309
|
+
- method
|
|
14310
|
+
additionalProperties: false
|
|
14311
|
+
additionalProperties: false
|
|
12864
14312
|
QueryIr:
|
|
12865
|
-
description:
|
|
14313
|
+
description: |-
|
|
14314
|
+
A metric definition as a typed expression tree — the structured alternative to the `query` DSL string, and what the API stores. Exactly one of `query` / `query_ir` is supplied per metric body; `query` is the same definition written as text, and is the spelling to prefer.
|
|
14315
|
+
Until 2026-08-10 this documented a single aggregation (`{agg, metric, filters}`, with `ratio` as a special case). That shape no longer exists — stored metrics were migrated and the code that read it was deleted — so a body sending it is rejected. Send the `query` string instead, or the tree below.
|
|
12866
14316
|
type: object
|
|
12867
14317
|
properties:
|
|
12868
|
-
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12872
|
-
|
|
12873
|
-
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
|
|
12877
|
-
|
|
12878
|
-
- type: object
|
|
12879
|
-
properties:
|
|
12880
|
-
kind:
|
|
12881
|
-
type: string
|
|
12882
|
-
const: count_events
|
|
12883
|
-
required:
|
|
12884
|
-
- kind
|
|
12885
|
-
additionalProperties: false
|
|
12886
|
-
- type: object
|
|
12887
|
-
properties:
|
|
12888
|
-
kind:
|
|
12889
|
-
type: string
|
|
12890
|
-
const: sum
|
|
12891
|
-
required:
|
|
12892
|
-
- kind
|
|
12893
|
-
additionalProperties: false
|
|
12894
|
-
- type: object
|
|
12895
|
-
properties:
|
|
12896
|
-
kind:
|
|
12897
|
-
type: string
|
|
12898
|
-
const: avg
|
|
12899
|
-
required:
|
|
12900
|
-
- kind
|
|
12901
|
-
additionalProperties: false
|
|
12902
|
-
- type: object
|
|
12903
|
-
properties:
|
|
12904
|
-
kind:
|
|
12905
|
-
type: string
|
|
12906
|
-
const: min
|
|
12907
|
-
required:
|
|
12908
|
-
- kind
|
|
12909
|
-
additionalProperties: false
|
|
12910
|
-
- type: object
|
|
12911
|
-
properties:
|
|
12912
|
-
kind:
|
|
12913
|
-
type: string
|
|
12914
|
-
const: max
|
|
12915
|
-
required:
|
|
12916
|
-
- kind
|
|
12917
|
-
additionalProperties: false
|
|
12918
|
-
- type: object
|
|
12919
|
-
properties:
|
|
12920
|
-
kind:
|
|
12921
|
-
type: string
|
|
12922
|
-
const: unique
|
|
12923
|
-
required:
|
|
12924
|
-
- kind
|
|
12925
|
-
additionalProperties: false
|
|
12926
|
-
- type: object
|
|
12927
|
-
properties:
|
|
12928
|
-
kind:
|
|
12929
|
-
type: string
|
|
12930
|
-
const: quantile
|
|
12931
|
-
p:
|
|
12932
|
-
anyOf:
|
|
12933
|
-
- type: number
|
|
12934
|
-
const: 0.5
|
|
12935
|
-
- type: number
|
|
12936
|
-
const: 0.75
|
|
12937
|
-
- type: number
|
|
12938
|
-
const: 0.9
|
|
12939
|
-
- type: number
|
|
12940
|
-
const: 0.95
|
|
12941
|
-
- type: number
|
|
12942
|
-
const: 0.99
|
|
12943
|
-
- type: number
|
|
12944
|
-
const: 0.999
|
|
12945
|
-
description: Quantile fraction (0.5 = p50 … 0.999 = p999).
|
|
12946
|
-
required:
|
|
12947
|
-
- kind
|
|
12948
|
-
- p
|
|
12949
|
-
additionalProperties: false
|
|
12950
|
-
- type: object
|
|
12951
|
-
properties:
|
|
12952
|
-
kind:
|
|
12953
|
-
type: string
|
|
12954
|
-
const: retention_Nd
|
|
12955
|
-
'n':
|
|
12956
|
-
type: integer
|
|
12957
|
-
minimum: 1
|
|
12958
|
-
maximum: 90
|
|
12959
|
-
description: Retention window in days (1–90).
|
|
12960
|
-
required:
|
|
12961
|
-
- kind
|
|
12962
|
-
- 'n'
|
|
12963
|
-
additionalProperties: false
|
|
12964
|
-
- type: object
|
|
12965
|
-
properties:
|
|
12966
|
-
kind:
|
|
12967
|
-
type: string
|
|
12968
|
-
const: ratio
|
|
12969
|
-
numerator:
|
|
12970
|
-
type: object
|
|
12971
|
-
properties:
|
|
12972
|
-
agg:
|
|
12973
|
-
type: string
|
|
12974
|
-
enum:
|
|
12975
|
-
- count_users
|
|
12976
|
-
- count_events
|
|
12977
|
-
description: Counting mode for this ratio arm.
|
|
12978
|
-
metric:
|
|
12979
|
-
type: string
|
|
12980
|
-
minLength: 1
|
|
12981
|
-
maxLength: 128
|
|
12982
|
-
description: Source event name for this ratio arm.
|
|
12983
|
-
filters:
|
|
12984
|
-
description: Optional label filters.
|
|
12985
|
-
maxItems: 16
|
|
12986
|
-
type: array
|
|
12987
|
-
items:
|
|
12988
|
-
type: object
|
|
12989
|
-
properties:
|
|
12990
|
-
label:
|
|
12991
|
-
type: string
|
|
12992
|
-
pattern: ^[a-z_][a-z0-9_]{0,63}$
|
|
12993
|
-
description: Event property / label identifier.
|
|
12994
|
-
op:
|
|
12995
|
-
type: string
|
|
12996
|
-
enum:
|
|
12997
|
-
- '='
|
|
12998
|
-
- '!='
|
|
12999
|
-
- '=~'
|
|
13000
|
-
- '!~'
|
|
13001
|
-
description: Match operator (`=~`/`!~` are regex).
|
|
13002
|
-
value:
|
|
13003
|
-
type: string
|
|
13004
|
-
maxLength: 512
|
|
13005
|
-
description: Quoted filter value (coerced for numeric labels).
|
|
13006
|
-
required:
|
|
13007
|
-
- label
|
|
13008
|
-
- op
|
|
13009
|
-
- value
|
|
13010
|
-
additionalProperties: false
|
|
13011
|
-
description: One label filter on the source event.
|
|
13012
|
-
required:
|
|
13013
|
-
- agg
|
|
13014
|
-
- metric
|
|
13015
|
-
additionalProperties: false
|
|
13016
|
-
description: Numerator or denominator arm of a `ratio` aggregation.
|
|
13017
|
-
denominator:
|
|
13018
|
-
type: object
|
|
13019
|
-
properties:
|
|
13020
|
-
agg:
|
|
13021
|
-
type: string
|
|
13022
|
-
enum:
|
|
13023
|
-
- count_users
|
|
13024
|
-
- count_events
|
|
13025
|
-
description: Counting mode for this ratio arm.
|
|
13026
|
-
metric:
|
|
13027
|
-
type: string
|
|
13028
|
-
minLength: 1
|
|
13029
|
-
maxLength: 128
|
|
13030
|
-
description: Source event name for this ratio arm.
|
|
13031
|
-
filters:
|
|
13032
|
-
description: Optional label filters.
|
|
13033
|
-
maxItems: 16
|
|
13034
|
-
type: array
|
|
13035
|
-
items:
|
|
13036
|
-
type: object
|
|
13037
|
-
properties:
|
|
13038
|
-
label:
|
|
13039
|
-
type: string
|
|
13040
|
-
pattern: ^[a-z_][a-z0-9_]{0,63}$
|
|
13041
|
-
description: Event property / label identifier.
|
|
13042
|
-
op:
|
|
13043
|
-
type: string
|
|
13044
|
-
enum:
|
|
13045
|
-
- '='
|
|
13046
|
-
- '!='
|
|
13047
|
-
- '=~'
|
|
13048
|
-
- '!~'
|
|
13049
|
-
description: Match operator (`=~`/`!~` are regex).
|
|
13050
|
-
value:
|
|
13051
|
-
type: string
|
|
13052
|
-
maxLength: 512
|
|
13053
|
-
description: Quoted filter value (coerced for numeric labels).
|
|
13054
|
-
required:
|
|
13055
|
-
- label
|
|
13056
|
-
- op
|
|
13057
|
-
- value
|
|
13058
|
-
additionalProperties: false
|
|
13059
|
-
description: One label filter on the source event.
|
|
13060
|
-
required:
|
|
13061
|
-
- agg
|
|
13062
|
-
- metric
|
|
13063
|
-
additionalProperties: false
|
|
13064
|
-
description: Numerator or denominator arm of a `ratio` aggregation.
|
|
13065
|
-
required:
|
|
13066
|
-
- kind
|
|
13067
|
-
- numerator
|
|
13068
|
-
- denominator
|
|
13069
|
-
additionalProperties: false
|
|
13070
|
-
description: Aggregation function applied to the source event.
|
|
13071
|
-
metric:
|
|
13072
|
-
type: string
|
|
13073
|
-
minLength: 1
|
|
13074
|
-
maxLength: 128
|
|
13075
|
-
description: Source event name (must equal `event_name`).
|
|
13076
|
-
valueLabel:
|
|
13077
|
-
description: Numeric property summed/averaged for `sum`/`avg`/quantile aggregations.
|
|
13078
|
-
type: string
|
|
13079
|
-
minLength: 1
|
|
13080
|
-
maxLength: 128
|
|
13081
|
-
filters:
|
|
13082
|
-
default: []
|
|
13083
|
-
description: Label filters on the event.
|
|
13084
|
-
maxItems: 16
|
|
13085
|
-
type: array
|
|
13086
|
-
items:
|
|
13087
|
-
type: object
|
|
13088
|
-
properties:
|
|
13089
|
-
label:
|
|
13090
|
-
type: string
|
|
13091
|
-
pattern: ^[a-z_][a-z0-9_]{0,63}$
|
|
13092
|
-
description: Event property / label identifier.
|
|
13093
|
-
op:
|
|
13094
|
-
type: string
|
|
13095
|
-
enum:
|
|
13096
|
-
- '='
|
|
13097
|
-
- '!='
|
|
13098
|
-
- '=~'
|
|
13099
|
-
- '!~'
|
|
13100
|
-
description: Match operator (`=~`/`!~` are regex).
|
|
13101
|
-
value:
|
|
13102
|
-
type: string
|
|
13103
|
-
maxLength: 512
|
|
13104
|
-
description: Quoted filter value (coerced for numeric labels).
|
|
13105
|
-
required:
|
|
13106
|
-
- label
|
|
13107
|
-
- op
|
|
13108
|
-
- value
|
|
13109
|
-
additionalProperties: false
|
|
13110
|
-
description: One label filter on the source event.
|
|
14318
|
+
v:
|
|
14319
|
+
type: integer
|
|
14320
|
+
const: 2
|
|
14321
|
+
description: Storage version of the definition. `2` is the only one.
|
|
14322
|
+
expr:
|
|
14323
|
+
type: object
|
|
14324
|
+
additionalProperties: true
|
|
14325
|
+
description: |-
|
|
14326
|
+
The expression tree: aggregate leaves (`{node: "agg", event, agg, filters, valueLabel?}`), arithmetic over them (`{node: "binary", op, left, right}`), scalars, and function calls (`{node: "call", fn, arg, params?}`). A ratio is ordinary division of two leaves.
|
|
14327
|
+
Deliberately opaque here rather than mirrored node by node: the grammar belongs to the query language, a second copy of it in this spec would drift from the one the server enforces, and the server validates every tree by planning it before the metric saves. `GET /api/admin/metrics` returns the grammar itself; the `query` string is the same tree in the form humans and the CLI write.
|
|
13111
14328
|
groupBy:
|
|
13112
14329
|
type: object
|
|
13113
14330
|
properties:
|
|
@@ -13116,23 +14333,25 @@ components:
|
|
|
13116
14333
|
enum:
|
|
13117
14334
|
- by
|
|
13118
14335
|
- without
|
|
13119
|
-
description: '`by`
|
|
14336
|
+
description: '`by` names the output dimensions; `without` names the ones to drop.'
|
|
13120
14337
|
labels:
|
|
13121
|
-
maxItems: 5
|
|
13122
14338
|
type: array
|
|
14339
|
+
maxItems: 8
|
|
13123
14340
|
items:
|
|
13124
14341
|
type: string
|
|
13125
14342
|
pattern: ^[a-z_][a-z0-9_]{0,63}$
|
|
13126
14343
|
description: Event property / label identifier.
|
|
13127
|
-
description: Labels
|
|
14344
|
+
description: Labels the grouping names.
|
|
13128
14345
|
required:
|
|
13129
14346
|
- op
|
|
13130
14347
|
- labels
|
|
13131
14348
|
additionalProperties: false
|
|
13132
|
-
description:
|
|
14349
|
+
description: How the series is split. On the envelope rather than in `expr` because every leaf of one expression shares it.
|
|
14350
|
+
display:
|
|
14351
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
13133
14352
|
required:
|
|
13134
|
-
-
|
|
13135
|
-
-
|
|
14353
|
+
- v
|
|
14354
|
+
- expr
|
|
13136
14355
|
additionalProperties: false
|
|
13137
14356
|
ListMetricsResponse:
|
|
13138
14357
|
type: array
|
|
@@ -13234,6 +14453,12 @@ components:
|
|
|
13234
14453
|
additionalProperties: {}
|
|
13235
14454
|
description: A metric definition.
|
|
13236
14455
|
description: Every metric in the project (the list endpoint is not paginated).
|
|
14456
|
+
MetricDisplayName:
|
|
14457
|
+
description: 'What a human calls the metric — "Checkout revenue" beside the `checkout.revenue` that identifies it. Unlike `name` it is free text, it is editable, and nothing addresses the metric by it: the dashboard leads with it and falls back to `name` when it is absent, so a metric nobody named simply reads as its key. Send `null` to clear it.'
|
|
14458
|
+
maxLength: 200
|
|
14459
|
+
anyOf:
|
|
14460
|
+
- type: string
|
|
14461
|
+
- type: 'null'
|
|
13237
14462
|
MetricEventName:
|
|
13238
14463
|
type: string
|
|
13239
14464
|
minLength: 1
|
|
@@ -13273,6 +14498,8 @@ components:
|
|
|
13273
14498
|
properties:
|
|
13274
14499
|
name:
|
|
13275
14500
|
$ref: '#/components/schemas/MetricName'
|
|
14501
|
+
display_name:
|
|
14502
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
13276
14503
|
folder:
|
|
13277
14504
|
$ref: '#/components/schemas/Folder'
|
|
13278
14505
|
event_name:
|
|
@@ -13287,6 +14514,8 @@ components:
|
|
|
13287
14514
|
$ref: '#/components/schemas/MetricDirection'
|
|
13288
14515
|
unit:
|
|
13289
14516
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14517
|
+
display:
|
|
14518
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
13290
14519
|
required:
|
|
13291
14520
|
- name
|
|
13292
14521
|
- event_name
|
|
@@ -13298,6 +14527,8 @@ components:
|
|
|
13298
14527
|
properties:
|
|
13299
14528
|
name:
|
|
13300
14529
|
$ref: '#/components/schemas/MetricName'
|
|
14530
|
+
display_name:
|
|
14531
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
13301
14532
|
folder:
|
|
13302
14533
|
$ref: '#/components/schemas/Folder'
|
|
13303
14534
|
event_name:
|
|
@@ -13312,6 +14543,8 @@ components:
|
|
|
13312
14543
|
$ref: '#/components/schemas/MetricDirection'
|
|
13313
14544
|
unit:
|
|
13314
14545
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14546
|
+
display:
|
|
14547
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
13315
14548
|
required:
|
|
13316
14549
|
- name
|
|
13317
14550
|
- event_name
|
|
@@ -13437,6 +14670,8 @@ components:
|
|
|
13437
14670
|
UpdateMetricWithQuery:
|
|
13438
14671
|
type: object
|
|
13439
14672
|
properties:
|
|
14673
|
+
display_name:
|
|
14674
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
13440
14675
|
folder:
|
|
13441
14676
|
$ref: '#/components/schemas/Folder'
|
|
13442
14677
|
event_name:
|
|
@@ -13451,6 +14686,8 @@ components:
|
|
|
13451
14686
|
$ref: '#/components/schemas/MetricDirection'
|
|
13452
14687
|
unit:
|
|
13453
14688
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14689
|
+
display:
|
|
14690
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
13454
14691
|
required:
|
|
13455
14692
|
- query
|
|
13456
14693
|
additionalProperties: false
|
|
@@ -13458,6 +14695,8 @@ components:
|
|
|
13458
14695
|
UpdateMetricWithQueryIr:
|
|
13459
14696
|
type: object
|
|
13460
14697
|
properties:
|
|
14698
|
+
display_name:
|
|
14699
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
13461
14700
|
folder:
|
|
13462
14701
|
$ref: '#/components/schemas/Folder'
|
|
13463
14702
|
event_name:
|
|
@@ -13472,6 +14711,8 @@ components:
|
|
|
13472
14711
|
$ref: '#/components/schemas/MetricDirection'
|
|
13473
14712
|
unit:
|
|
13474
14713
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14714
|
+
display:
|
|
14715
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
13475
14716
|
required:
|
|
13476
14717
|
- query_ir
|
|
13477
14718
|
additionalProperties: false
|
|
@@ -13479,6 +14720,8 @@ components:
|
|
|
13479
14720
|
UpdateMetricFields:
|
|
13480
14721
|
type: object
|
|
13481
14722
|
properties:
|
|
14723
|
+
display_name:
|
|
14724
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
13482
14725
|
folder:
|
|
13483
14726
|
$ref: '#/components/schemas/Folder'
|
|
13484
14727
|
event_name:
|
|
@@ -13491,8 +14734,10 @@ components:
|
|
|
13491
14734
|
$ref: '#/components/schemas/MetricDirection'
|
|
13492
14735
|
unit:
|
|
13493
14736
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14737
|
+
display:
|
|
14738
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
13494
14739
|
additionalProperties: false
|
|
13495
|
-
description: Update-metric variant that leaves the query untouched (metadata-only edit — folder, event, winsorisation, default minimum effect of interest, direction, display unit).
|
|
14740
|
+
description: Update-metric variant that leaves the query untouched (metadata-only edit — folder, event, winsorisation, default minimum effect of interest, direction, display unit, band and projection).
|
|
13496
14741
|
UpdateMetricRequest:
|
|
13497
14742
|
oneOf:
|
|
13498
14743
|
- $ref: '#/components/schemas/UpdateMetricWithQuery'
|
|
@@ -13591,6 +14836,14 @@ components:
|
|
|
13591
14836
|
v:
|
|
13592
14837
|
type: number
|
|
13593
14838
|
description: Aggregated metric value in the bucket (sample-interval weighted).
|
|
14839
|
+
lo:
|
|
14840
|
+
type: number
|
|
14841
|
+
description: |
|
|
14842
|
+
Lower edge of the seasonal band — what this hour of the week normally holds, `sigma` below the median of the four weeks before the window. Present only for a metric whose `display.band` is on, and always alongside `hi`.
|
|
14843
|
+
hi:
|
|
14844
|
+
type: number
|
|
14845
|
+
description: |
|
|
14846
|
+
Upper edge of the seasonal band. Present only for a metric whose `display.band` is on, and always alongside `lo`. A point outside `[lo, hi]` is exactly a bucket an `anomaly` alert rule at the same sigma would breach on — the band a chart draws and the condition a rule fires on come from one fit.
|
|
13594
14847
|
required:
|
|
13595
14848
|
- t
|
|
13596
14849
|
- v
|
|
@@ -13634,7 +14887,8 @@ components:
|
|
|
13634
14887
|
type: string
|
|
13635
14888
|
minLength: 1
|
|
13636
14889
|
maxLength: 64
|
|
13637
|
-
|
|
14890
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
14891
|
+
description: Property key, e.g. `amount` or `plan`. Must be a bare identifier — it is emitted as a SQL alias when the property is used as a `by()` dimension, and there is no way to quote one in the Analytics Engine dialect.
|
|
13638
14892
|
type:
|
|
13639
14893
|
type: string
|
|
13640
14894
|
enum:
|
|
@@ -13650,11 +14904,14 @@ components:
|
|
|
13650
14904
|
default: ''
|
|
13651
14905
|
description: Human-readable description of the property.
|
|
13652
14906
|
type: string
|
|
14907
|
+
pending:
|
|
14908
|
+
description: '`true` when this property was DISCOVERED in live traffic rather than declared. Nothing is recorded for it yet — a property is written to Analytics Engine only once it owns a column, and a column is allocated when an admin declares the property (include it in a `PATCH .../events/{id}` body). Approval is a gate rather than a formality: columns are finite and permanently reserved, so auto-allocating them from customer payload keys would exhaust an event''s schema irreversibly.'
|
|
14909
|
+
type: boolean
|
|
13653
14910
|
required:
|
|
13654
14911
|
- name
|
|
13655
14912
|
- type
|
|
13656
14913
|
additionalProperties: false
|
|
13657
|
-
description: One typed property
|
|
14914
|
+
description: One typed property on a catalogued event — declared by an admin, or discovered in traffic and awaiting declaration.
|
|
13658
14915
|
description: Typed properties declared on the event.
|
|
13659
14916
|
pending:
|
|
13660
14917
|
type: integer
|
|
@@ -13679,8 +14936,8 @@ components:
|
|
|
13679
14936
|
properties:
|
|
13680
14937
|
name:
|
|
13681
14938
|
type: string
|
|
13682
|
-
pattern: ^[a-zA-Z0-9_][a-zA-Z0-9_\-.]{0,
|
|
13683
|
-
description: Event name. Starts with a letter, digit, or `_`; letters, digits, `_`, `-`, `.`; max 128
|
|
14939
|
+
pattern: ^[a-zA-Z0-9_][a-zA-Z0-9_\-.]{0,49}$
|
|
14940
|
+
description: Event name. Starts with a letter, digit, or `_`; letters, digits, `_`, `-`, `.`; max 50 characters. The cap is the Analytics Engine index budget — 96 bytes total, less a 36-byte project UUID and a separator — and the API has always enforced 50 while this spec advertised 128. The charset is ASCII, so characters and bytes are the same count. Immutable after create — this is the handle metric queries reference.
|
|
13684
14941
|
folder:
|
|
13685
14942
|
$ref: '#/components/schemas/Folder'
|
|
13686
14943
|
description:
|
|
@@ -13697,7 +14954,8 @@ components:
|
|
|
13697
14954
|
type: string
|
|
13698
14955
|
minLength: 1
|
|
13699
14956
|
maxLength: 64
|
|
13700
|
-
|
|
14957
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
14958
|
+
description: Property key, e.g. `amount` or `plan`. Must be a bare identifier — it is emitted as a SQL alias when the property is used as a `by()` dimension, and there is no way to quote one in the Analytics Engine dialect.
|
|
13701
14959
|
type:
|
|
13702
14960
|
type: string
|
|
13703
14961
|
enum:
|
|
@@ -13769,7 +15027,8 @@ components:
|
|
|
13769
15027
|
type: string
|
|
13770
15028
|
minLength: 1
|
|
13771
15029
|
maxLength: 64
|
|
13772
|
-
|
|
15030
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
15031
|
+
description: Property key, e.g. `amount` or `plan`. Must be a bare identifier — it is emitted as a SQL alias when the property is used as a `by()` dimension, and there is no way to quote one in the Analytics Engine dialect.
|
|
13773
15032
|
type:
|
|
13774
15033
|
type: string
|
|
13775
15034
|
enum:
|
|
@@ -13785,11 +15044,14 @@ components:
|
|
|
13785
15044
|
default: ''
|
|
13786
15045
|
description: Human-readable description of the property.
|
|
13787
15046
|
type: string
|
|
15047
|
+
pending:
|
|
15048
|
+
description: '`true` when this property was DISCOVERED in live traffic rather than declared. Nothing is recorded for it yet — a property is written to Analytics Engine only once it owns a column, and a column is allocated when an admin declares the property (include it in a `PATCH .../events/{id}` body). Approval is a gate rather than a formality: columns are finite and permanently reserved, so auto-allocating them from customer payload keys would exhaust an event''s schema irreversibly.'
|
|
15049
|
+
type: boolean
|
|
13788
15050
|
required:
|
|
13789
15051
|
- name
|
|
13790
15052
|
- type
|
|
13791
15053
|
additionalProperties: false
|
|
13792
|
-
description: One typed property
|
|
15054
|
+
description: One typed property on a catalogued event — declared by an admin, or discovered in traffic and awaiting declaration.
|
|
13793
15055
|
description: Typed properties declared on the event.
|
|
13794
15056
|
pending:
|
|
13795
15057
|
type: integer
|
|
@@ -13836,7 +15098,8 @@ components:
|
|
|
13836
15098
|
type: string
|
|
13837
15099
|
minLength: 1
|
|
13838
15100
|
maxLength: 64
|
|
13839
|
-
|
|
15101
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
15102
|
+
description: Property key, e.g. `amount` or `plan`. Must be a bare identifier — it is emitted as a SQL alias when the property is used as a `by()` dimension, and there is no way to quote one in the Analytics Engine dialect.
|
|
13840
15103
|
type:
|
|
13841
15104
|
type: string
|
|
13842
15105
|
enum:
|
|
@@ -13887,7 +15150,8 @@ components:
|
|
|
13887
15150
|
type: string
|
|
13888
15151
|
minLength: 1
|
|
13889
15152
|
maxLength: 64
|
|
13890
|
-
|
|
15153
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
15154
|
+
description: Property key, e.g. `amount` or `plan`. Must be a bare identifier — it is emitted as a SQL alias when the property is used as a `by()` dimension, and there is no way to quote one in the Analytics Engine dialect.
|
|
13891
15155
|
type:
|
|
13892
15156
|
type: string
|
|
13893
15157
|
enum:
|
|
@@ -13945,6 +15209,7 @@ components:
|
|
|
13945
15209
|
enum:
|
|
13946
15210
|
- pr_ready
|
|
13947
15211
|
- pr_merged
|
|
15212
|
+
- pr_closed
|
|
13948
15213
|
- investigated
|
|
13949
15214
|
- detected
|
|
13950
15215
|
- question
|
|
@@ -13952,7 +15217,7 @@ components:
|
|
|
13952
15217
|
- pending_approval
|
|
13953
15218
|
- working
|
|
13954
15219
|
- backlog
|
|
13955
|
-
description: 'Where automation has taken an item in the investigation lifecycle — the signal the ops cockpit renders as "what AI did" plus the one action expected of the user. It is **written as a side-effect of the actions that already happen**, never authored on its own: linking a PR sets `pr_ready`, moving to `in_progress` sets `working`, `ready_for_qa` sets `ready_for_qa`, a system/assistant reply sets `question`, resolving clears it, and creation seeds `backlog`
|
|
15220
|
+
description: 'Where automation has taken an item in the investigation lifecycle — the signal the ops cockpit renders as "what AI did" plus the one action expected of the user. It is **written as a side-effect of the actions that already happen**, never authored on its own: linking a PR sets `pr_ready`, moving to `in_progress` sets `working`, `ready_for_qa` sets `ready_for_qa`, a system/assistant reply sets `question`, resolving clears it, and creation seeds `backlog` for every untouched item (bugs, features, and auto-filed error/alert tickets alike — type is not a signal). `backlog` is the single "nothing has happened yet" state — how urgent that is reads off `priority`, not off a separate state, and its one action is to hand the item to an agent. `investigated`/`detected` are set when a completed agent run leaves findings to review, not at filing time. `pr_merged` and `pr_closed` are written by the GitHub `pull_request` webhook when the linked PR reaches a terminal outcome — merged (the fix shipped, resolve the item) or closed without merging (the fix was rejected, decide what happens next). Absent on rows filed before the field existed — consumers should treat a missing value as "derive from the other fields".'
|
|
13956
15221
|
OpsBrowserContext:
|
|
13957
15222
|
type: object
|
|
13958
15223
|
properties:
|
|
@@ -14112,20 +15377,31 @@ components:
|
|
|
14112
15377
|
type: string
|
|
14113
15378
|
enum:
|
|
14114
15379
|
- metric_rule
|
|
15380
|
+
- killswitch_armed
|
|
14115
15381
|
- experiment_srm
|
|
14116
15382
|
- experiment_peek
|
|
14117
15383
|
- guardrail
|
|
14118
|
-
description: What kind of
|
|
15384
|
+
description: What kind of condition opened this alert instance.
|
|
14119
15385
|
dedupeKey:
|
|
14120
15386
|
type: string
|
|
14121
15387
|
description: Stable per-condition key; with `source` forms the ticket's `sourceRef`.
|
|
15388
|
+
detail:
|
|
15389
|
+
anyOf:
|
|
15390
|
+
- type: string
|
|
15391
|
+
- type: 'null'
|
|
15392
|
+
description: The instance's one-line reading — the observed condition in words.
|
|
15393
|
+
ruleId:
|
|
15394
|
+
anyOf:
|
|
15395
|
+
- type: string
|
|
15396
|
+
- type: 'null'
|
|
15397
|
+
description: Id of the alert rule that opened this instance, or `null` for a built-in condition.
|
|
14122
15398
|
severity:
|
|
14123
15399
|
type: string
|
|
14124
15400
|
enum:
|
|
14125
15401
|
- danger
|
|
14126
15402
|
- warn
|
|
14127
15403
|
- info
|
|
14128
|
-
description:
|
|
15404
|
+
description: How loud the alert is. Severity belongs to the RULE and is carried by this ticket as `priority`; it is DERIVED from that on the hydrated single-item read, and absent from the raw stored context list rows return.
|
|
14129
15405
|
observedValue:
|
|
14130
15406
|
anyOf:
|
|
14131
15407
|
- type: number
|
|
@@ -14144,7 +15420,7 @@ components:
|
|
|
14144
15420
|
- resolved
|
|
14145
15421
|
- dismissed
|
|
14146
15422
|
- type: 'null'
|
|
14147
|
-
description:
|
|
15423
|
+
description: Firing state of this instance, projected from the ticket's own status (`active` while it is open, i.e. while the condition holds). Absent from the raw stored context list rows return.
|
|
14148
15424
|
activeSince:
|
|
14149
15425
|
anyOf:
|
|
14150
15426
|
- type: string
|
|
@@ -14168,9 +15444,8 @@ components:
|
|
|
14168
15444
|
required:
|
|
14169
15445
|
- source
|
|
14170
15446
|
- dedupeKey
|
|
14171
|
-
- severity
|
|
14172
15447
|
additionalProperties: {}
|
|
14173
|
-
description:
|
|
15448
|
+
description: Detail for an `alert` ticket — the fired-alert INSTANCE this ticket is. List rows carry the stored capture subset (`source`, `dedupeKey`, `ruleId`, `detail`, `href`, `observedValue`); the single-item read hydrates the rest, resolving `severity`/`status` off the ticket itself and the rule → metric → event chain at request time.
|
|
14174
15449
|
MeasurePlanResource:
|
|
14175
15450
|
type: object
|
|
14176
15451
|
properties:
|
|
@@ -14274,7 +15549,7 @@ components:
|
|
|
14274
15549
|
properties:
|
|
14275
15550
|
t:
|
|
14276
15551
|
type: number
|
|
14277
|
-
description: Bucket start — unix epoch **milliseconds
|
|
15552
|
+
description: Bucket start — unix epoch **milliseconds**. Bucket width scales with the window (hourly up to ~5 days, coarser beyond).
|
|
14278
15553
|
v:
|
|
14279
15554
|
type: number
|
|
14280
15555
|
description: Occurrence count in the bucket (sample-rate weighted).
|
|
@@ -14282,11 +15557,11 @@ components:
|
|
|
14282
15557
|
- t
|
|
14283
15558
|
- v
|
|
14284
15559
|
additionalProperties: {}
|
|
14285
|
-
description: One
|
|
14286
|
-
description:
|
|
15560
|
+
description: One occurrence bucket.
|
|
15561
|
+
description: Occurrence buckets, oldest first. Buckets with no occurrences are omitted.
|
|
14287
15562
|
domainFrom:
|
|
14288
15563
|
type: number
|
|
14289
|
-
description: Chart domain start — unix epoch milliseconds (
|
|
15564
|
+
description: Chart domain start — unix epoch milliseconds (the window's start).
|
|
14290
15565
|
domainTo:
|
|
14291
15566
|
type: number
|
|
14292
15567
|
description: Chart domain end — unix epoch milliseconds (the read time).
|
|
@@ -14295,7 +15570,7 @@ components:
|
|
|
14295
15570
|
- domainFrom
|
|
14296
15571
|
- domainTo
|
|
14297
15572
|
additionalProperties: {}
|
|
14298
|
-
description: Occurrence timeline for an `error` ticket —
|
|
15573
|
+
description: 'Occurrence timeline for an `error` ticket — buckets over the project''s error auto-close window (Settings → Errors: `errorAutocloseDays`, 7 days when auto-close is off, capped at 30) from the sampled occurrences, hydrated at read time by the single-item read only. Plotting exactly the quiet window that auto-resolves the error is what makes an empty right-hand edge meaningful. ABSENT (not `null`) on non-error tickets, on list rows (raw context), and when no occurrence landed in the window.'
|
|
14299
15574
|
additionalProperties: {}
|
|
14300
15575
|
description: Per-type capture context on a queue item. Exactly one of `browser` (bug/feature), `error`, `alert`, or `measurePlan` is populated depending on `type`; other keys (e.g. the AI dedupe block on bugs) may also be present.
|
|
14301
15576
|
GithubPrLink:
|
|
@@ -14319,6 +15594,25 @@ components:
|
|
|
14319
15594
|
- closes
|
|
14320
15595
|
- comment
|
|
14321
15596
|
description: How the PR was connected to the issue.
|
|
15597
|
+
owner:
|
|
15598
|
+
type: string
|
|
15599
|
+
description: Repository owner (org or user) the pull request lives in. Absent on links recorded before the field existed — `url` still carries it.
|
|
15600
|
+
repo:
|
|
15601
|
+
type: string
|
|
15602
|
+
description: Repository name the pull request lives in. Absent on links recorded before the field existed — `url` still carries it.
|
|
15603
|
+
state:
|
|
15604
|
+
type: string
|
|
15605
|
+
enum:
|
|
15606
|
+
- open
|
|
15607
|
+
- merged
|
|
15608
|
+
- closed
|
|
15609
|
+
description: Outcome of the pull request on GitHub, kept current by the `pull_request` webhook. `merged` and `closed` (closed WITHOUT merging, i.e. rejected) are terminal. Absent means the outcome has never been observed — treat it as `open`.
|
|
15610
|
+
mergedAt:
|
|
15611
|
+
type: string
|
|
15612
|
+
description: ISO-8601 timestamp the pull request merged, when `state` is `merged`.
|
|
15613
|
+
closedAt:
|
|
15614
|
+
type: string
|
|
15615
|
+
description: ISO-8601 timestamp the pull request closed unmerged, when `state` is `closed`.
|
|
14322
15616
|
required:
|
|
14323
15617
|
- number
|
|
14324
15618
|
- url
|
|
@@ -14691,6 +15985,11 @@ components:
|
|
|
14691
15985
|
additionalProperties: {}
|
|
14692
15986
|
description: One queue item — any type — plus its resolved `owner` and run state.
|
|
14693
15987
|
description: A page of queue items, newest first.
|
|
15988
|
+
TagName:
|
|
15989
|
+
type: string
|
|
15990
|
+
minLength: 1
|
|
15991
|
+
maxLength: 64
|
|
15992
|
+
description: A tag name. Trimmed; matched case-insensitively against the project's existing tags.
|
|
14694
15993
|
CreateBugRequest:
|
|
14695
15994
|
type: object
|
|
14696
15995
|
properties:
|
|
@@ -14743,10 +16042,11 @@ components:
|
|
|
14743
16042
|
description: Emails of teammates to subscribe to this item's Slack pings at creation.
|
|
14744
16043
|
tags:
|
|
14745
16044
|
type: array
|
|
16045
|
+
maxItems: 50
|
|
14746
16046
|
items:
|
|
14747
|
-
|
|
16047
|
+
$ref: '#/components/schemas/TagName'
|
|
14748
16048
|
default: []
|
|
14749
|
-
description: Tag names to
|
|
16049
|
+
description: Tag names to label the item with, e.g. `["ios", "checkout"]`. Each name is matched case-insensitively against the project's existing tags and reuses that tag (keeping its stored casing) when one matches; a name with no match creates a new project tag.
|
|
14750
16050
|
reporterEmail:
|
|
14751
16051
|
anyOf:
|
|
14752
16052
|
- type: string
|
|
@@ -14834,10 +16134,11 @@ components:
|
|
|
14834
16134
|
description: Emails of teammates to subscribe to this item's Slack pings at creation.
|
|
14835
16135
|
tags:
|
|
14836
16136
|
type: array
|
|
16137
|
+
maxItems: 50
|
|
14837
16138
|
items:
|
|
14838
|
-
|
|
16139
|
+
$ref: '#/components/schemas/TagName'
|
|
14839
16140
|
default: []
|
|
14840
|
-
description: Tag names to
|
|
16141
|
+
description: Tag names to label the item with, e.g. `["ios", "checkout"]`. Each name is matched case-insensitively against the project's existing tags and reuses that tag (keeping its stored casing) when one matches; a name with no match creates a new project tag.
|
|
14841
16142
|
reporterEmail:
|
|
14842
16143
|
anyOf:
|
|
14843
16144
|
- type: string
|
|
@@ -14897,45 +16198,243 @@ components:
|
|
|
14897
16198
|
- id
|
|
14898
16199
|
additionalProperties: false
|
|
14899
16200
|
description: Response for `POST /api/admin/ops`.
|
|
14900
|
-
|
|
16201
|
+
CreatePublicBugRequest:
|
|
14901
16202
|
type: object
|
|
14902
16203
|
properties:
|
|
14903
|
-
|
|
14904
|
-
type: string
|
|
14905
|
-
description: Attachment id.
|
|
14906
|
-
kind:
|
|
14907
|
-
type: string
|
|
14908
|
-
description: '`screenshot` | `video` | `log`.'
|
|
14909
|
-
filename:
|
|
14910
|
-
type: string
|
|
14911
|
-
description: Sanitized original filename.
|
|
14912
|
-
mimeType:
|
|
16204
|
+
title:
|
|
14913
16205
|
type: string
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
|
|
14917
|
-
description:
|
|
14918
|
-
|
|
16206
|
+
minLength: 1
|
|
16207
|
+
maxLength: 200
|
|
16208
|
+
pattern: ^\S(.*\S)?$
|
|
16209
|
+
description: One-line bug title (no leading/trailing whitespace).
|
|
16210
|
+
stepsToReproduce:
|
|
14919
16211
|
type: string
|
|
14920
|
-
|
|
14921
|
-
|
|
14922
|
-
|
|
14923
|
-
|
|
14924
|
-
- filename
|
|
14925
|
-
- mimeType
|
|
14926
|
-
- sizeBytes
|
|
14927
|
-
- fetchUrl
|
|
14928
|
-
additionalProperties: {}
|
|
14929
|
-
description: A file uploaded with a bug/feature report.
|
|
14930
|
-
OpsItemRelated:
|
|
14931
|
-
type: object
|
|
14932
|
-
properties:
|
|
14933
|
-
dashboard:
|
|
16212
|
+
maxLength: 8000
|
|
16213
|
+
default: ''
|
|
16214
|
+
description: How to reproduce the bug.
|
|
16215
|
+
actualResult:
|
|
14934
16216
|
type: string
|
|
14935
|
-
|
|
14936
|
-
|
|
16217
|
+
maxLength: 8000
|
|
16218
|
+
default: ''
|
|
16219
|
+
description: What actually happened.
|
|
16220
|
+
expectedResult:
|
|
14937
16221
|
type: string
|
|
14938
|
-
|
|
16222
|
+
maxLength: 8000
|
|
16223
|
+
default: ''
|
|
16224
|
+
description: What was expected instead.
|
|
16225
|
+
priority:
|
|
16226
|
+
anyOf:
|
|
16227
|
+
- $ref: '#/components/schemas/OpsItemPriority'
|
|
16228
|
+
- type: 'null'
|
|
16229
|
+
description: Initial triage priority, or `null`.
|
|
16230
|
+
status:
|
|
16231
|
+
anyOf:
|
|
16232
|
+
- $ref: '#/components/schemas/OpsItemStatus'
|
|
16233
|
+
description: Initial lifecycle status; defaults to `open` when omitted.
|
|
16234
|
+
assigneeId:
|
|
16235
|
+
anyOf:
|
|
16236
|
+
- type: string
|
|
16237
|
+
- type: 'null'
|
|
16238
|
+
description: The `users.id` of the person to assign as owner at creation, or `null`.
|
|
16239
|
+
subscribers:
|
|
16240
|
+
type: array
|
|
16241
|
+
items:
|
|
16242
|
+
type: string
|
|
16243
|
+
format: email
|
|
16244
|
+
default: []
|
|
16245
|
+
description: Emails of teammates to subscribe to this item's Slack pings at creation.
|
|
16246
|
+
tags:
|
|
16247
|
+
type: array
|
|
16248
|
+
maxItems: 50
|
|
16249
|
+
items:
|
|
16250
|
+
$ref: '#/components/schemas/TagName'
|
|
16251
|
+
default: []
|
|
16252
|
+
description: 'Tag names to label the item with, e.g. `["ios", "checkout"]`. Each name is matched case-insensitively against the project''s existing tags and reuses that tag (keeping its stored casing) when one matches; a name with no match creates a new project tag. Here the tags only label the ticket: the project''s tag rules (owner/status/agent routing) are not applied to a public report while it awaits approval.'
|
|
16253
|
+
reporterEmail:
|
|
16254
|
+
anyOf:
|
|
16255
|
+
- type: string
|
|
16256
|
+
format: email
|
|
16257
|
+
- type: 'null'
|
|
16258
|
+
description: Email of the reporter, or `null`.
|
|
16259
|
+
pageUrl:
|
|
16260
|
+
anyOf:
|
|
16261
|
+
- type: string
|
|
16262
|
+
format: uri
|
|
16263
|
+
- type: 'null'
|
|
16264
|
+
description: URL of the page the bug relates to, or `null`.
|
|
16265
|
+
userAgent:
|
|
16266
|
+
anyOf:
|
|
16267
|
+
- type: string
|
|
16268
|
+
maxLength: 500
|
|
16269
|
+
- type: 'null'
|
|
16270
|
+
description: Reporter's user-agent string, or `null`.
|
|
16271
|
+
viewport:
|
|
16272
|
+
anyOf:
|
|
16273
|
+
- type: string
|
|
16274
|
+
maxLength: 40
|
|
16275
|
+
- type: 'null'
|
|
16276
|
+
description: Reporter's viewport (e.g. `1280x720`), or `null`.
|
|
16277
|
+
context:
|
|
16278
|
+
anyOf:
|
|
16279
|
+
- type: object
|
|
16280
|
+
additionalProperties: {}
|
|
16281
|
+
- type: 'null'
|
|
16282
|
+
description: Arbitrary capture context, or `null`.
|
|
16283
|
+
dedupKey:
|
|
16284
|
+
type: string
|
|
16285
|
+
maxLength: 200
|
|
16286
|
+
description: 'Caller-chosen dedupe identity for this report, stored on the ticket. A repeat submission carrying the same key does NOT file a second ticket: the open ticket already holding that key is refreshed from this payload (title and the report fields overwritten, a "re-triggered" comment appended) and returned with `deduped: true` and `updated: true`. Triage state a human owns — status, priority, assignee, tags — is left untouched, and a `resolved`/`wont_fix` ticket no longer holds the key, so a failure that comes back after being closed files a fresh ticket. Omit it to fall back to the derived (title + `context.step`) dedupe, whose repeats return the existing ticket unchanged.'
|
|
16287
|
+
notify:
|
|
16288
|
+
anyOf:
|
|
16289
|
+
- $ref: '#/components/schemas/NotificationTarget'
|
|
16290
|
+
- type: 'null'
|
|
16291
|
+
description: Where this bug's completion notification lands.
|
|
16292
|
+
required:
|
|
16293
|
+
- title
|
|
16294
|
+
additionalProperties: false
|
|
16295
|
+
description: Body for `POST /ops/bug`. The same bug fields as `CreateBugRequest`, minus the `type` discriminator — the path already says what is being filed, plus the public intake's own `dedupKey`.
|
|
16296
|
+
CreatePublicTicketResponse:
|
|
16297
|
+
type: object
|
|
16298
|
+
properties:
|
|
16299
|
+
id:
|
|
16300
|
+
type: string
|
|
16301
|
+
description: The new item's id. Absent on a deduped response — nothing was created, so there is no new id to report.
|
|
16302
|
+
number:
|
|
16303
|
+
type: integer
|
|
16304
|
+
description: Per-project item number. On a deduped response this is the number of the OPEN ticket already tracking the report, which is what a caller should show the user either way.
|
|
16305
|
+
deduped:
|
|
16306
|
+
type: boolean
|
|
16307
|
+
description: '`true` when an open ticket already tracked this report and nothing was filed (HTTP 200). Absent on a fresh file (HTTP 201).'
|
|
16308
|
+
updated:
|
|
16309
|
+
type: boolean
|
|
16310
|
+
description: '`true` when the deduped ticket was REFRESHED from this payload and got a "re-triggered" comment — only ever set alongside `deduped` on a submission that carried a `dedupKey`. Absent when the existing ticket was returned untouched.'
|
|
16311
|
+
required:
|
|
16312
|
+
- number
|
|
16313
|
+
additionalProperties: false
|
|
16314
|
+
description: 'Response for the public ticket intake. A fresh file returns `201` with `id` + `number`; a repeat of a report already tracked by an open ticket returns `200` with that ticket''s `number` and `deduped: true` — plus `updated: true` when a `dedupKey` re-triggered it and its fields were refreshed.'
|
|
16315
|
+
CreatePublicFeatureRequestRequest:
|
|
16316
|
+
type: object
|
|
16317
|
+
properties:
|
|
16318
|
+
title:
|
|
16319
|
+
type: string
|
|
16320
|
+
minLength: 1
|
|
16321
|
+
maxLength: 200
|
|
16322
|
+
pattern: ^\S(.*\S)?$
|
|
16323
|
+
description: One-line feature-request title (no leading/trailing whitespace).
|
|
16324
|
+
description:
|
|
16325
|
+
type: string
|
|
16326
|
+
maxLength: 8000
|
|
16327
|
+
default: ''
|
|
16328
|
+
description: What the feature is.
|
|
16329
|
+
useCase:
|
|
16330
|
+
type: string
|
|
16331
|
+
maxLength: 8000
|
|
16332
|
+
default: ''
|
|
16333
|
+
description: Why it's needed / the use case.
|
|
16334
|
+
priority:
|
|
16335
|
+
anyOf:
|
|
16336
|
+
- $ref: '#/components/schemas/OpsItemPriority'
|
|
16337
|
+
- type: 'null'
|
|
16338
|
+
description: Initial triage priority, or `null`.
|
|
16339
|
+
status:
|
|
16340
|
+
anyOf:
|
|
16341
|
+
- $ref: '#/components/schemas/OpsItemStatus'
|
|
16342
|
+
description: Initial lifecycle status; defaults to `open` when omitted.
|
|
16343
|
+
assigneeId:
|
|
16344
|
+
anyOf:
|
|
16345
|
+
- type: string
|
|
16346
|
+
- type: 'null'
|
|
16347
|
+
description: The `users.id` of the person to assign as owner at creation, or `null`.
|
|
16348
|
+
subscribers:
|
|
16349
|
+
type: array
|
|
16350
|
+
items:
|
|
16351
|
+
type: string
|
|
16352
|
+
format: email
|
|
16353
|
+
default: []
|
|
16354
|
+
description: Emails of teammates to subscribe to this item's Slack pings at creation.
|
|
16355
|
+
tags:
|
|
16356
|
+
type: array
|
|
16357
|
+
maxItems: 50
|
|
16358
|
+
items:
|
|
16359
|
+
$ref: '#/components/schemas/TagName'
|
|
16360
|
+
default: []
|
|
16361
|
+
description: 'Tag names to label the item with, e.g. `["ios", "checkout"]`. Each name is matched case-insensitively against the project''s existing tags and reuses that tag (keeping its stored casing) when one matches; a name with no match creates a new project tag. Here the tags only label the ticket: the project''s tag rules (owner/status/agent routing) are not applied to a public report while it awaits approval.'
|
|
16362
|
+
reporterEmail:
|
|
16363
|
+
anyOf:
|
|
16364
|
+
- type: string
|
|
16365
|
+
format: email
|
|
16366
|
+
- type: 'null'
|
|
16367
|
+
description: Email of the reporter, or `null`.
|
|
16368
|
+
pageUrl:
|
|
16369
|
+
anyOf:
|
|
16370
|
+
- type: string
|
|
16371
|
+
format: uri
|
|
16372
|
+
- type: 'null'
|
|
16373
|
+
description: URL of the page the request relates to, or `null`.
|
|
16374
|
+
userAgent:
|
|
16375
|
+
anyOf:
|
|
16376
|
+
- type: string
|
|
16377
|
+
maxLength: 500
|
|
16378
|
+
- type: 'null'
|
|
16379
|
+
description: Reporter's user-agent string, or `null`.
|
|
16380
|
+
context:
|
|
16381
|
+
anyOf:
|
|
16382
|
+
- type: object
|
|
16383
|
+
additionalProperties: {}
|
|
16384
|
+
- type: 'null'
|
|
16385
|
+
description: Arbitrary capture context, or `null`.
|
|
16386
|
+
dedupKey:
|
|
16387
|
+
type: string
|
|
16388
|
+
maxLength: 200
|
|
16389
|
+
description: 'Caller-chosen dedupe identity for this request, stored on the ticket. Behaves exactly as on `POST /ops/bug`: a repeat carrying the same key refreshes the open ticket already holding it (fields overwritten, a "re-triggered" comment appended) and returns `deduped: true` with `updated: true`, instead of filing a second one.'
|
|
16390
|
+
notify:
|
|
16391
|
+
anyOf:
|
|
16392
|
+
- $ref: '#/components/schemas/NotificationTarget'
|
|
16393
|
+
- type: 'null'
|
|
16394
|
+
description: Where this request's completion notification lands.
|
|
16395
|
+
required:
|
|
16396
|
+
- title
|
|
16397
|
+
additionalProperties: false
|
|
16398
|
+
description: Body for `POST /ops/feature-request`. The same feature-request fields as `CreateFeatureRequestRequest`, minus the `type` discriminator — the path already says what is being filed, plus the public intake's own `dedupKey`.
|
|
16399
|
+
OpsItemAttachment:
|
|
16400
|
+
type: object
|
|
16401
|
+
properties:
|
|
16402
|
+
id:
|
|
16403
|
+
type: string
|
|
16404
|
+
description: Attachment id.
|
|
16405
|
+
kind:
|
|
16406
|
+
type: string
|
|
16407
|
+
description: '`screenshot` | `video` | `log`.'
|
|
16408
|
+
filename:
|
|
16409
|
+
type: string
|
|
16410
|
+
description: Sanitized original filename.
|
|
16411
|
+
mimeType:
|
|
16412
|
+
type: string
|
|
16413
|
+
description: MIME type, e.g. `image/png`.
|
|
16414
|
+
sizeBytes:
|
|
16415
|
+
type: number
|
|
16416
|
+
description: Upload size in bytes.
|
|
16417
|
+
fetchUrl:
|
|
16418
|
+
type: string
|
|
16419
|
+
description: Admin-API path to download the file (`GET` with the admin/ops key — screenshots render inline; recordings can't be watched).
|
|
16420
|
+
required:
|
|
16421
|
+
- id
|
|
16422
|
+
- kind
|
|
16423
|
+
- filename
|
|
16424
|
+
- mimeType
|
|
16425
|
+
- sizeBytes
|
|
16426
|
+
- fetchUrl
|
|
16427
|
+
additionalProperties: {}
|
|
16428
|
+
description: A file uploaded with a bug/feature report.
|
|
16429
|
+
OpsItemRelated:
|
|
16430
|
+
type: object
|
|
16431
|
+
properties:
|
|
16432
|
+
dashboard:
|
|
16433
|
+
type: string
|
|
16434
|
+
description: Dashboard-relative deep link to this item.
|
|
16435
|
+
error:
|
|
16436
|
+
type: string
|
|
16437
|
+
description: Admin-API path to the tracked error (error tickets only).
|
|
14939
16438
|
alertRule:
|
|
14940
16439
|
type: string
|
|
14941
16440
|
description: Admin-API path to the alert rule (metric-rule alerts only).
|
|
@@ -15240,6 +16739,10 @@ components:
|
|
|
15240
16739
|
type: string
|
|
15241
16740
|
maxLength: 300
|
|
15242
16741
|
description: The agent-run session id (e.g. Claude's `session_01…`), so the dashboard can deep-link to the exact run page. Omit when the harness has no session id.
|
|
16742
|
+
launch:
|
|
16743
|
+
type: boolean
|
|
16744
|
+
default: true
|
|
16745
|
+
description: 'Whether an AI ack may FIRE the agent''s connected trigger. Default `true`: an ack naming a connected agent, with no `sessionId`, starts a new provider run of that agent. Pass `false` to only record the ack — claim the item and open the run record — without starting anything, e.g. when you ARE that agent working the item yourself and have no session id to pass. Ignored on a human ack.'
|
|
15243
16746
|
additionalProperties: false
|
|
15244
16747
|
description: Body for `POST /api/admin/ops/{handle}/ack`. With `agent` set this is an AI ack — the named agent type must have a connected trigger connector in the project, or the call fails with `AGENT_NOT_CONNECTED` and instructions to query the available agents (`ops agents list`). `gemini` is accepted as an alias for `jules`. Without `agent` it is a HUMAN ack by the authenticated caller.
|
|
15245
16748
|
AckOpsItemResponse:
|
|
@@ -15661,6 +17164,253 @@ components:
|
|
|
15661
17164
|
additionalProperties: false
|
|
15662
17165
|
minProperties: 1
|
|
15663
17166
|
description: Body for `PATCH /api/admin/ops/{handle}/investigation/{investigationId}` — a partial update of one existing investigation record (typically the `working` run record you were handed). Send only the fields you want to change; at least one is required.
|
|
17167
|
+
OpsQuestionStatus:
|
|
17168
|
+
type: string
|
|
17169
|
+
enum:
|
|
17170
|
+
- open
|
|
17171
|
+
- completed
|
|
17172
|
+
- cancelled
|
|
17173
|
+
description: Where a question stands — `open` (waiting on a person), `completed` (answered), or `cancelled` (withdrawn by the asker).
|
|
17174
|
+
OpsQuestionAnswer:
|
|
17175
|
+
type: object
|
|
17176
|
+
properties:
|
|
17177
|
+
selected:
|
|
17178
|
+
type: array
|
|
17179
|
+
items:
|
|
17180
|
+
type: string
|
|
17181
|
+
description: The option labels the person picked (empty when they only answered "Other").
|
|
17182
|
+
other:
|
|
17183
|
+
anyOf:
|
|
17184
|
+
- type: string
|
|
17185
|
+
- type: 'null'
|
|
17186
|
+
description: The free-text "Other" answer, or `null`.
|
|
17187
|
+
required:
|
|
17188
|
+
- selected
|
|
17189
|
+
- other
|
|
17190
|
+
additionalProperties: false
|
|
17191
|
+
description: A person's answer to a question.
|
|
17192
|
+
OpsQuestionDelivery:
|
|
17193
|
+
type: string
|
|
17194
|
+
enum:
|
|
17195
|
+
- resume
|
|
17196
|
+
- poll
|
|
17197
|
+
description: How the answer gets back to the asker — `resume` re-fires the asking run's trigger connector on the item once every question that run asked is answered; `poll` fires nothing and the asker reads `GET .../questions`.
|
|
17198
|
+
OpsQuestion:
|
|
17199
|
+
type: object
|
|
17200
|
+
properties:
|
|
17201
|
+
id:
|
|
17202
|
+
type: string
|
|
17203
|
+
description: Question id.
|
|
17204
|
+
feedbackId:
|
|
17205
|
+
type: string
|
|
17206
|
+
description: The queue item the question hangs off.
|
|
17207
|
+
header:
|
|
17208
|
+
type: string
|
|
17209
|
+
description: Short chip label for the question.
|
|
17210
|
+
question:
|
|
17211
|
+
type: string
|
|
17212
|
+
description: The full question (markdown).
|
|
17213
|
+
options:
|
|
17214
|
+
type: array
|
|
17215
|
+
items:
|
|
17216
|
+
type: object
|
|
17217
|
+
properties:
|
|
17218
|
+
label:
|
|
17219
|
+
type: string
|
|
17220
|
+
description: The option's display text.
|
|
17221
|
+
description:
|
|
17222
|
+
anyOf:
|
|
17223
|
+
- type: string
|
|
17224
|
+
- type: 'null'
|
|
17225
|
+
description: What picking the option means, or `null`.
|
|
17226
|
+
required:
|
|
17227
|
+
- label
|
|
17228
|
+
- description
|
|
17229
|
+
additionalProperties: false
|
|
17230
|
+
description: One offered choice.
|
|
17231
|
+
description: The offered choices, in order.
|
|
17232
|
+
multiSelect:
|
|
17233
|
+
type: boolean
|
|
17234
|
+
description: Whether several options may be picked.
|
|
17235
|
+
status:
|
|
17236
|
+
$ref: '#/components/schemas/OpsQuestionStatus'
|
|
17237
|
+
answer:
|
|
17238
|
+
anyOf:
|
|
17239
|
+
- $ref: '#/components/schemas/OpsQuestionAnswer'
|
|
17240
|
+
- type: 'null'
|
|
17241
|
+
description: The person's answer, or `null` while the question is open (or was withdrawn).
|
|
17242
|
+
answeredBy:
|
|
17243
|
+
anyOf:
|
|
17244
|
+
- type: string
|
|
17245
|
+
- type: 'null'
|
|
17246
|
+
description: Email of the person who answered, or `null`.
|
|
17247
|
+
answeredAt:
|
|
17248
|
+
anyOf:
|
|
17249
|
+
- type: string
|
|
17250
|
+
- type: 'null'
|
|
17251
|
+
description: ISO-8601 timestamp of the answer, or `null`.
|
|
17252
|
+
agent:
|
|
17253
|
+
anyOf:
|
|
17254
|
+
- type: string
|
|
17255
|
+
enum:
|
|
17256
|
+
- jarvis
|
|
17257
|
+
- claude
|
|
17258
|
+
- cursor
|
|
17259
|
+
- copilot
|
|
17260
|
+
- jules
|
|
17261
|
+
- type: 'null'
|
|
17262
|
+
description: The agent that asked, or `null` (asked by a person or an unattributed key).
|
|
17263
|
+
askedBy:
|
|
17264
|
+
anyOf:
|
|
17265
|
+
- type: string
|
|
17266
|
+
- type: 'null'
|
|
17267
|
+
description: Email of the person who asked, when a human asked, or `null`.
|
|
17268
|
+
runId:
|
|
17269
|
+
anyOf:
|
|
17270
|
+
- type: string
|
|
17271
|
+
- type: 'null'
|
|
17272
|
+
description: The run (investigation record id) the question was asked under, or `null`.
|
|
17273
|
+
delivery:
|
|
17274
|
+
$ref: '#/components/schemas/OpsQuestionDelivery'
|
|
17275
|
+
deliveredAt:
|
|
17276
|
+
anyOf:
|
|
17277
|
+
- type: string
|
|
17278
|
+
- type: 'null'
|
|
17279
|
+
description: ISO-8601 timestamp the answer was re-delivered to the asking run (`resume` only), or `null`.
|
|
17280
|
+
deliveryError:
|
|
17281
|
+
anyOf:
|
|
17282
|
+
- type: string
|
|
17283
|
+
- type: 'null'
|
|
17284
|
+
description: Why a `resume` re-delivery failed, or `null`.
|
|
17285
|
+
createdAt:
|
|
17286
|
+
type: string
|
|
17287
|
+
description: ISO-8601 creation timestamp.
|
|
17288
|
+
updatedAt:
|
|
17289
|
+
type: string
|
|
17290
|
+
description: ISO-8601 last-update timestamp.
|
|
17291
|
+
required:
|
|
17292
|
+
- id
|
|
17293
|
+
- feedbackId
|
|
17294
|
+
- header
|
|
17295
|
+
- question
|
|
17296
|
+
- options
|
|
17297
|
+
- multiSelect
|
|
17298
|
+
- status
|
|
17299
|
+
- answer
|
|
17300
|
+
- answeredBy
|
|
17301
|
+
- answeredAt
|
|
17302
|
+
- agent
|
|
17303
|
+
- askedBy
|
|
17304
|
+
- runId
|
|
17305
|
+
- delivery
|
|
17306
|
+
- deliveredAt
|
|
17307
|
+
- deliveryError
|
|
17308
|
+
- createdAt
|
|
17309
|
+
- updatedAt
|
|
17310
|
+
additionalProperties: false
|
|
17311
|
+
description: One structured question on a queue item and, once answered, its answer.
|
|
17312
|
+
ListOpsQuestionsResponse:
|
|
17313
|
+
type: array
|
|
17314
|
+
items:
|
|
17315
|
+
$ref: '#/components/schemas/OpsQuestion'
|
|
17316
|
+
description: Response for `GET /api/admin/ops/{handle}/questions` — the item's questions, newest first (max 100).
|
|
17317
|
+
OpsQuestionOption:
|
|
17318
|
+
type: object
|
|
17319
|
+
properties:
|
|
17320
|
+
label:
|
|
17321
|
+
type: string
|
|
17322
|
+
minLength: 1
|
|
17323
|
+
maxLength: 120
|
|
17324
|
+
description: The option's display text — short (1–5 words). Answers name options by this label.
|
|
17325
|
+
description:
|
|
17326
|
+
type: string
|
|
17327
|
+
maxLength: 500
|
|
17328
|
+
description: What picking this option means — its trade-off or consequence.
|
|
17329
|
+
required:
|
|
17330
|
+
- label
|
|
17331
|
+
additionalProperties: false
|
|
17332
|
+
description: One choice offered by a question — rendered as a radio, or a checkbox when the question is `multiSelect`.
|
|
17333
|
+
AskOpsQuestionInput:
|
|
17334
|
+
type: object
|
|
17335
|
+
properties:
|
|
17336
|
+
header:
|
|
17337
|
+
type: string
|
|
17338
|
+
minLength: 1
|
|
17339
|
+
maxLength: 24
|
|
17340
|
+
description: Very short chip label for the question (max 24 chars), e.g. `Auth method`.
|
|
17341
|
+
question:
|
|
17342
|
+
type: string
|
|
17343
|
+
minLength: 1
|
|
17344
|
+
maxLength: 2000
|
|
17345
|
+
description: The complete question, ending with a question mark (markdown).
|
|
17346
|
+
options:
|
|
17347
|
+
type: array
|
|
17348
|
+
minItems: 2
|
|
17349
|
+
maxItems: 4
|
|
17350
|
+
items:
|
|
17351
|
+
$ref: '#/components/schemas/OpsQuestionOption'
|
|
17352
|
+
description: 2–4 distinct choices. Do not add an "Other" option — a free-text answer is always offered.
|
|
17353
|
+
multiSelect:
|
|
17354
|
+
type: boolean
|
|
17355
|
+
default: false
|
|
17356
|
+
description: '`true` lets the person pick several options (checkboxes); `false` (the default) exactly one (radios).'
|
|
17357
|
+
required:
|
|
17358
|
+
- header
|
|
17359
|
+
- question
|
|
17360
|
+
- options
|
|
17361
|
+
additionalProperties: false
|
|
17362
|
+
description: One question to ask — the `AskUserQuestion` shape.
|
|
17363
|
+
AskOpsQuestionsRequest:
|
|
17364
|
+
type: object
|
|
17365
|
+
properties:
|
|
17366
|
+
questions:
|
|
17367
|
+
type: array
|
|
17368
|
+
minItems: 1
|
|
17369
|
+
maxItems: 4
|
|
17370
|
+
items:
|
|
17371
|
+
$ref: '#/components/schemas/AskOpsQuestionInput'
|
|
17372
|
+
description: 1–4 questions to ask at once.
|
|
17373
|
+
runId:
|
|
17374
|
+
type: string
|
|
17375
|
+
maxLength: 200
|
|
17376
|
+
description: The run (investigation record id) you are working the item under — the `runId` an ack or a launch handed you. Ties the questions to that run so a `resume` delivery continues it.
|
|
17377
|
+
agent:
|
|
17378
|
+
type: string
|
|
17379
|
+
enum:
|
|
17380
|
+
- jarvis
|
|
17381
|
+
- claude
|
|
17382
|
+
- cursor
|
|
17383
|
+
- copilot
|
|
17384
|
+
- jules
|
|
17385
|
+
description: The agent type asking — pass your own type when you are a coding agent. Defaults to the run's agent.
|
|
17386
|
+
delivery:
|
|
17387
|
+
$ref: '#/components/schemas/OpsQuestionDelivery'
|
|
17388
|
+
required:
|
|
17389
|
+
- questions
|
|
17390
|
+
additionalProperties: false
|
|
17391
|
+
description: Body for `POST /api/admin/ops/{handle}/questions`.
|
|
17392
|
+
AskOpsQuestionsResponse:
|
|
17393
|
+
type: array
|
|
17394
|
+
items:
|
|
17395
|
+
$ref: '#/components/schemas/OpsQuestion'
|
|
17396
|
+
description: Response for `POST /api/admin/ops/{handle}/questions` — the created questions, in the order asked.
|
|
17397
|
+
AnswerOpsQuestionRequest:
|
|
17398
|
+
type: object
|
|
17399
|
+
properties:
|
|
17400
|
+
selected:
|
|
17401
|
+
type: array
|
|
17402
|
+
maxItems: 4
|
|
17403
|
+
items:
|
|
17404
|
+
type: string
|
|
17405
|
+
maxLength: 120
|
|
17406
|
+
description: The option labels picked — exactly one for a single-select question (unless answering only with `other`), one or more for `multiSelect`.
|
|
17407
|
+
other:
|
|
17408
|
+
type: string
|
|
17409
|
+
maxLength: 10000
|
|
17410
|
+
description: A free-text "Other" answer.
|
|
17411
|
+
additionalProperties: false
|
|
17412
|
+
minProperties: 1
|
|
17413
|
+
description: Body for `POST /api/admin/ops/{handle}/questions/{questionId}/answer` — pick option labels, write a free-text answer, or both (multi-select only).
|
|
15664
17414
|
OpsAgentProfile:
|
|
15665
17415
|
type: object
|
|
15666
17416
|
properties:
|
|
@@ -15854,6 +17604,27 @@ components:
|
|
|
15854
17604
|
- channels
|
|
15855
17605
|
additionalProperties: false
|
|
15856
17606
|
description: Response for `GET /api/admin/slack/channels`.
|
|
17607
|
+
AlertCompositeSpec:
|
|
17608
|
+
type: object
|
|
17609
|
+
description: 'What a `composite` rule is a boolean over. `rules` are sibling alert-rule ids in the same project and `op` is how their states combine. A child''s state is what the current pass concluded about it, falling back to whether it has an open instance — so a composite still means something on a tick where a child could not be evaluated, which is exactly the tick a "two of these are broken at once" rule is for. One level deep: a child may not itself be composite.'
|
|
17610
|
+
properties:
|
|
17611
|
+
op:
|
|
17612
|
+
type: string
|
|
17613
|
+
enum:
|
|
17614
|
+
- and
|
|
17615
|
+
- or
|
|
17616
|
+
description: How the children's states combine.
|
|
17617
|
+
rules:
|
|
17618
|
+
type: array
|
|
17619
|
+
minItems: 2
|
|
17620
|
+
items:
|
|
17621
|
+
type: string
|
|
17622
|
+
minLength: 1
|
|
17623
|
+
description: Ids of the alert rules to combine. Stored sorted and de-duplicated.
|
|
17624
|
+
required:
|
|
17625
|
+
- op
|
|
17626
|
+
- rules
|
|
17627
|
+
additionalProperties: false
|
|
15857
17628
|
ListAlertRulesResponse:
|
|
15858
17629
|
type: array
|
|
15859
17630
|
items:
|
|
@@ -15873,6 +17644,15 @@ components:
|
|
|
15873
17644
|
- type: string
|
|
15874
17645
|
- type: 'null'
|
|
15875
17646
|
description: Display name of the bound metric, or `null` if the metric no longer exists.
|
|
17647
|
+
kind:
|
|
17648
|
+
type: string
|
|
17649
|
+
enum:
|
|
17650
|
+
- normal
|
|
17651
|
+
- anomaly
|
|
17652
|
+
- outliers
|
|
17653
|
+
- no_data
|
|
17654
|
+
- composite
|
|
17655
|
+
description: What the rule watches for. `normal` compares the metric's own value — against `threshold` via `comparator`, or against the [`rangeMin`, `rangeMax`] corridor it must stay inside. `anomaly` compares it against ITS OWN seasonal baseline in sigmas, which is the same fit a chart draws as the band. `outliers` compares each `by()` group against its peers in the same bucket, so it needs a grouped metric. `no_data` fires when the metric records nothing at all for `noDataMinutes` — a count of zero is not silence, and the two are distinguished by the reader's presence columns. `composite` is a boolean over OTHER rules' current state and watches no metric of its own.
|
|
15876
17656
|
comparator:
|
|
15877
17657
|
type: string
|
|
15878
17658
|
enum:
|
|
@@ -15880,15 +17660,90 @@ components:
|
|
|
15880
17660
|
- gte
|
|
15881
17661
|
- lt
|
|
15882
17662
|
- lte
|
|
15883
|
-
description: How the metric value is compared to the threshold (gt/gte/lt/lte).
|
|
17663
|
+
description: How the metric value is compared to the threshold (gt/gte/lt/lte). Read only by a `normal` rule with no range set.
|
|
15884
17664
|
threshold:
|
|
15885
17665
|
type: number
|
|
15886
|
-
description: Threshold the metric value is compared against.
|
|
17666
|
+
description: Threshold the metric value is compared against. Read only by a `normal` rule with no range set.
|
|
17667
|
+
rangeMin:
|
|
17668
|
+
anyOf:
|
|
17669
|
+
- type: number
|
|
17670
|
+
- type: 'null'
|
|
17671
|
+
description: Lower edge of the corridor a `normal` rule must stay inside; `null` if the rule is judged by comparator and threshold.
|
|
17672
|
+
rangeMax:
|
|
17673
|
+
anyOf:
|
|
17674
|
+
- type: number
|
|
17675
|
+
- type: 'null'
|
|
17676
|
+
description: Upper edge of the corridor a `normal` rule must stay inside; `null` if the rule is judged by comparator and threshold.
|
|
17677
|
+
sigma:
|
|
17678
|
+
anyOf:
|
|
17679
|
+
- type: number
|
|
17680
|
+
- type: 'null'
|
|
17681
|
+
description: How far from normal is too far, for `anomaly` and `outliers`, in sigma-equivalents. `null` takes the default of 3, which is also the width of the band a chart draws.
|
|
17682
|
+
direction:
|
|
17683
|
+
anyOf:
|
|
17684
|
+
- type: string
|
|
17685
|
+
enum:
|
|
17686
|
+
- above
|
|
17687
|
+
- below
|
|
17688
|
+
- either
|
|
17689
|
+
- type: 'null'
|
|
17690
|
+
description: Which side of the baseline an `anomaly` or `outliers` rule watches. `null` means either.
|
|
17691
|
+
sustained:
|
|
17692
|
+
type: boolean
|
|
17693
|
+
description: Whether the rule is judged by ACCUMULATED departure rather than bucket by bucket. `anomaly` and `outliers` only.
|
|
17694
|
+
warnThreshold:
|
|
17695
|
+
anyOf:
|
|
17696
|
+
- type: number
|
|
17697
|
+
- type: 'null'
|
|
17698
|
+
description: The milder bound, in the same unit the kind judges in. `null` means the rule has one level.
|
|
17699
|
+
recoveryThreshold:
|
|
17700
|
+
anyOf:
|
|
17701
|
+
- type: number
|
|
17702
|
+
- type: 'null'
|
|
17703
|
+
description: What the metric must get back to before a live alert closes. `null` means no hysteresis — the firing bound clears it.
|
|
17704
|
+
groupAlerts:
|
|
17705
|
+
type: boolean
|
|
17706
|
+
description: Whether the rule fires one alert per `by()` group rather than one for the whole metric.
|
|
17707
|
+
maxGroups:
|
|
17708
|
+
anyOf:
|
|
17709
|
+
- type: integer
|
|
17710
|
+
- type: 'null'
|
|
17711
|
+
description: How many groups this rule may alert on at once. `null` takes the shipped cap of 10.
|
|
17712
|
+
noDataMinutes:
|
|
17713
|
+
anyOf:
|
|
17714
|
+
- type: integer
|
|
17715
|
+
- type: 'null'
|
|
17716
|
+
description: How long the silence must last for a `no_data` rule. `null` on every other kind.
|
|
17717
|
+
delayMinutes:
|
|
17718
|
+
anyOf:
|
|
17719
|
+
- type: integer
|
|
17720
|
+
- type: 'null'
|
|
17721
|
+
description: How far behind live the evaluated window is held, on top of the reader's settle grace. `null` means no extra delay.
|
|
17722
|
+
autoResolveMinutes:
|
|
17723
|
+
anyOf:
|
|
17724
|
+
- type: integer
|
|
17725
|
+
- type: 'null'
|
|
17726
|
+
description: Close a live instance that has gone this long without a fresh verdict. `null` never auto-resolves.
|
|
17727
|
+
composite:
|
|
17728
|
+
anyOf:
|
|
17729
|
+
- $ref: '#/components/schemas/AlertCompositeSpec'
|
|
17730
|
+
- type: 'null'
|
|
17731
|
+
description: For a `composite` rule, the child rules and how their states combine. `null` on every other kind.
|
|
15887
17732
|
windowHours:
|
|
15888
17733
|
type: integer
|
|
15889
17734
|
minimum: -9007199254740991
|
|
15890
17735
|
maximum: 9007199254740991
|
|
15891
17736
|
description: Lookback window (hours) the metric is aggregated over.
|
|
17737
|
+
bucketMinutes:
|
|
17738
|
+
anyOf:
|
|
17739
|
+
- type: integer
|
|
17740
|
+
- type: 'null'
|
|
17741
|
+
description: Width of the buckets the window is split into, in minutes. `null` divides the window into 12 equal buckets.
|
|
17742
|
+
requiredBuckets:
|
|
17743
|
+
anyOf:
|
|
17744
|
+
- type: integer
|
|
17745
|
+
- type: 'null'
|
|
17746
|
+
description: How many buckets must breach before the rule fires. `null` means every bucket that had data.
|
|
15892
17747
|
severity:
|
|
15893
17748
|
type: string
|
|
15894
17749
|
enum:
|
|
@@ -15912,9 +17767,25 @@ components:
|
|
|
15912
17767
|
- name
|
|
15913
17768
|
- metricId
|
|
15914
17769
|
- metricName
|
|
17770
|
+
- kind
|
|
15915
17771
|
- comparator
|
|
15916
17772
|
- threshold
|
|
17773
|
+
- rangeMin
|
|
17774
|
+
- rangeMax
|
|
17775
|
+
- sigma
|
|
17776
|
+
- direction
|
|
17777
|
+
- sustained
|
|
17778
|
+
- warnThreshold
|
|
17779
|
+
- recoveryThreshold
|
|
17780
|
+
- groupAlerts
|
|
17781
|
+
- maxGroups
|
|
17782
|
+
- noDataMinutes
|
|
17783
|
+
- delayMinutes
|
|
17784
|
+
- autoResolveMinutes
|
|
17785
|
+
- composite
|
|
15917
17786
|
- windowHours
|
|
17787
|
+
- bucketMinutes
|
|
17788
|
+
- requiredBuckets
|
|
15918
17789
|
- severity
|
|
15919
17790
|
- enabled
|
|
15920
17791
|
- notify
|
|
@@ -15934,26 +17805,122 @@ components:
|
|
|
15934
17805
|
type: string
|
|
15935
17806
|
minLength: 1
|
|
15936
17807
|
description: Id of the metric to evaluate.
|
|
17808
|
+
kind:
|
|
17809
|
+
default: normal
|
|
17810
|
+
description: 'What the rule watches for. `normal` compares the metric''s own value — against `threshold` via `comparator`, or against the [`rangeMin`, `rangeMax`] corridor it must stay inside. `anomaly` compares it against its own seasonal baseline in sigmas: the same fit a chart draws as the band, so a point outside the drawn band is exactly a breaching bucket, and one metric can back rules at several sigmas. `outliers` compares each `by()` group against its peers in the same bucket and is refused on a metric with no grouping.'
|
|
17811
|
+
type: string
|
|
17812
|
+
enum:
|
|
17813
|
+
- normal
|
|
17814
|
+
- anomaly
|
|
17815
|
+
- outliers
|
|
17816
|
+
- no_data
|
|
17817
|
+
- composite
|
|
15937
17818
|
comparator:
|
|
17819
|
+
default: gt
|
|
17820
|
+
description: How the metric value is compared to the threshold. Read only by a `normal` rule with no range set.
|
|
15938
17821
|
type: string
|
|
15939
17822
|
enum:
|
|
15940
17823
|
- gt
|
|
15941
17824
|
- gte
|
|
15942
17825
|
- lt
|
|
15943
17826
|
- lte
|
|
15944
|
-
description: How the metric value is compared to the threshold (gt/gte/lt/lte).
|
|
15945
17827
|
threshold:
|
|
15946
17828
|
type: number
|
|
15947
|
-
description: Threshold the metric value is compared against.
|
|
17829
|
+
description: Threshold the metric value is compared against. Required for a `normal` rule unless a range is given; ignored by every other kind.
|
|
17830
|
+
rangeMin:
|
|
17831
|
+
anyOf:
|
|
17832
|
+
- type: number
|
|
17833
|
+
- type: 'null'
|
|
17834
|
+
description: Lower edge of the corridor the metric must stay inside. Setting either bound switches a `normal` rule off `comparator`/`threshold` and onto the range, which breaches on LEAVING it in either direction. One bound alone is a one-sided range.
|
|
17835
|
+
rangeMax:
|
|
17836
|
+
anyOf:
|
|
17837
|
+
- type: number
|
|
17838
|
+
- type: 'null'
|
|
17839
|
+
description: Upper edge of the corridor the metric must stay inside.
|
|
17840
|
+
sigma:
|
|
17841
|
+
anyOf:
|
|
17842
|
+
- type: number
|
|
17843
|
+
exclusiveMinimum: 0
|
|
17844
|
+
- type: 'null'
|
|
17845
|
+
description: How far from normal is too far, for `anomaly` and `outliers`, in sigma-equivalents. Omit (or `null`) for 3, which is also the half-width of the band a chart draws — so an unconfigured rule fires exactly where the picture says it would.
|
|
17846
|
+
direction:
|
|
17847
|
+
anyOf:
|
|
17848
|
+
- type: string
|
|
17849
|
+
enum:
|
|
17850
|
+
- above
|
|
17851
|
+
- below
|
|
17852
|
+
- either
|
|
17853
|
+
- type: 'null'
|
|
17854
|
+
description: Which side of the baseline an `anomaly` or `outliers` rule watches. Omit (or `null`) for either, which is what "is this unusual" means; name a side for a metric that is only bad in one direction.
|
|
17855
|
+
sustained:
|
|
17856
|
+
default: false
|
|
17857
|
+
type: boolean
|
|
17858
|
+
description: 'Judge the window by ACCUMULATED departure instead of bucket by bucket. The ordinary check asks every bucket to be past `sigma`, which a slow regression never manages: a metric running 1.5σ worse than normal since Tuesday puts no single bucket past 3σ and pages nobody. A sustained rule adds up each bucket''s excess over half a sigma and fires once the total passes twice `sigma` — four buckets at 2σ do it, a lone 3σ spike does not. `anomaly` and `outliers` only, and refused alongside `requiredBuckets`: the accumulated bar IS the evidence bar, and a second one counted in buckets would silently override it.'
|
|
15948
17859
|
windowHours:
|
|
15949
17860
|
default: 24
|
|
15950
17861
|
description: Lookback window (hours) the metric is aggregated over. 1–720.
|
|
15951
17862
|
type: integer
|
|
15952
17863
|
minimum: 1
|
|
15953
17864
|
maximum: 720
|
|
17865
|
+
bucketMinutes:
|
|
17866
|
+
anyOf:
|
|
17867
|
+
- type: integer
|
|
17868
|
+
minimum: 1
|
|
17869
|
+
maximum: 43200
|
|
17870
|
+
- type: 'null'
|
|
17871
|
+
description: Width of the buckets the window is split into, in minutes. Omit (or `null`) to divide the window into 12 equal buckets. The rule is judged per bucket, so this is the resolution at which "sustained" is measured — a short bucket asks the condition to hold through finer detail.
|
|
17872
|
+
requiredBuckets:
|
|
17873
|
+
anyOf:
|
|
17874
|
+
- type: integer
|
|
17875
|
+
minimum: 1
|
|
17876
|
+
- type: 'null'
|
|
17877
|
+
description: How many buckets must breach before the rule fires. Omit (or `null`) to require every bucket that had data. Buckets with nothing in them are excluded before this is counted, so on a sparse metric `null` can mean a single bucket — set this to 2 or more where one lone sample must never page.
|
|
17878
|
+
warnThreshold:
|
|
17879
|
+
anyOf:
|
|
17880
|
+
- type: number
|
|
17881
|
+
- type: 'null'
|
|
17882
|
+
description: 'The milder bound — a second level, in the same unit the kind judges in, that raises a quieter alert before the firing level is reached. Must be strictly milder than the level the rule fires at, or it could never fire on its own. Refused on a range rule and on a `sustained` one: neither condition is a single number, so there is nothing to substitute.'
|
|
17883
|
+
recoveryThreshold:
|
|
17884
|
+
anyOf:
|
|
17885
|
+
- type: number
|
|
17886
|
+
- type: 'null'
|
|
17887
|
+
description: What the metric must get back to before a live alert closes. Without it a metric sitting on its threshold pages and clears once per tick. Must be on the safe side of the firing level, or equal to it. Omit (or `null`) for no hysteresis.
|
|
17888
|
+
groupAlerts:
|
|
17889
|
+
default: false
|
|
17890
|
+
type: boolean
|
|
17891
|
+
description: Fire one alert per `by()` group instead of one for the whole metric. The firing key becomes (rule, group), so each group raises, dedupes and recovers on its own. Refused on a metric with no `by()`, and on `no_data` — a group that went silent has no rows left to be missing from.
|
|
17892
|
+
maxGroups:
|
|
17893
|
+
anyOf:
|
|
17894
|
+
- type: integer
|
|
17895
|
+
minimum: 1
|
|
17896
|
+
maximum: 50
|
|
17897
|
+
- type: 'null'
|
|
17898
|
+
description: How many groups this rule may alert on at once. Omit (or `null`) for 10. Past the cap the worst groups fire and the count of the rest is stated on each ticket — a group set is customer data, and an uncapped rule on `by(user_id)` would file a ticket per user.
|
|
17899
|
+
noDataMinutes:
|
|
17900
|
+
anyOf:
|
|
17901
|
+
- type: integer
|
|
17902
|
+
minimum: 5
|
|
17903
|
+
maximum: 43200
|
|
17904
|
+
- type: 'null'
|
|
17905
|
+
description: 'For a `no_data` rule: how long the silence must last. Omit (or `null`) for 15 minutes. Five is the floor — below it, ordinary ingest lag empties the trailing bucket and reads as an outage.'
|
|
17906
|
+
delayMinutes:
|
|
17907
|
+
anyOf:
|
|
17908
|
+
- type: integer
|
|
17909
|
+
minimum: 1
|
|
17910
|
+
maximum: 1440
|
|
17911
|
+
- type: 'null'
|
|
17912
|
+
description: Hold the evaluated window back this far behind live, on top of the reader's own settle grace. For a metric assembled from a source that lands in batches, whose trailing buckets are legitimately incomplete for longer than the grace covers.
|
|
17913
|
+
autoResolveMinutes:
|
|
17914
|
+
anyOf:
|
|
17915
|
+
- type: integer
|
|
17916
|
+
minimum: 1
|
|
17917
|
+
- type: 'null'
|
|
17918
|
+
description: Close a live instance that has gone this long without a fresh verdict. A rule that cannot reach a verdict deliberately leaves its alert alone, which is right for a tick and wrong for a week. Never closes an instance that is currently breaching. Omit (or `null`) to never auto-resolve.
|
|
17919
|
+
composite:
|
|
17920
|
+
$ref: '#/components/schemas/AlertCompositeSpec'
|
|
15954
17921
|
severity:
|
|
15955
17922
|
default: warn
|
|
15956
|
-
description: Severity of the raised alert.
|
|
17923
|
+
description: Severity of the raised alert. A `warnThreshold` breach opens one step quieter than this.
|
|
15957
17924
|
type: string
|
|
15958
17925
|
enum:
|
|
15959
17926
|
- danger
|
|
@@ -15968,8 +17935,6 @@ components:
|
|
|
15968
17935
|
required:
|
|
15969
17936
|
- name
|
|
15970
17937
|
- metricId
|
|
15971
|
-
- comparator
|
|
15972
|
-
- threshold
|
|
15973
17938
|
additionalProperties: false
|
|
15974
17939
|
CreateAlertRuleResponse:
|
|
15975
17940
|
type: object
|
|
@@ -15996,6 +17961,14 @@ components:
|
|
|
15996
17961
|
type: string
|
|
15997
17962
|
minLength: 1
|
|
15998
17963
|
maxLength: 120
|
|
17964
|
+
kind:
|
|
17965
|
+
type: string
|
|
17966
|
+
enum:
|
|
17967
|
+
- normal
|
|
17968
|
+
- anomaly
|
|
17969
|
+
- outliers
|
|
17970
|
+
- no_data
|
|
17971
|
+
- composite
|
|
15999
17972
|
comparator:
|
|
16000
17973
|
type: string
|
|
16001
17974
|
enum:
|
|
@@ -16005,10 +17978,93 @@ components:
|
|
|
16005
17978
|
- lte
|
|
16006
17979
|
threshold:
|
|
16007
17980
|
type: number
|
|
17981
|
+
rangeMin:
|
|
17982
|
+
anyOf:
|
|
17983
|
+
- type: number
|
|
17984
|
+
- type: 'null'
|
|
17985
|
+
description: Lower edge of the corridor; `null` drops it, returning the rule to comparator and threshold when both bounds are gone.
|
|
17986
|
+
rangeMax:
|
|
17987
|
+
anyOf:
|
|
17988
|
+
- type: number
|
|
17989
|
+
- type: 'null'
|
|
17990
|
+
description: Upper edge of the corridor; `null` drops it.
|
|
17991
|
+
sigma:
|
|
17992
|
+
anyOf:
|
|
17993
|
+
- type: number
|
|
17994
|
+
exclusiveMinimum: 0
|
|
17995
|
+
- type: 'null'
|
|
17996
|
+
description: Sigmas an `anomaly` or `outliers` rule fires at; `null` restores the default of 3.
|
|
17997
|
+
direction:
|
|
17998
|
+
anyOf:
|
|
17999
|
+
- type: string
|
|
18000
|
+
enum:
|
|
18001
|
+
- above
|
|
18002
|
+
- below
|
|
18003
|
+
- either
|
|
18004
|
+
- type: 'null'
|
|
18005
|
+
description: Which side an `anomaly` or `outliers` rule watches; `null` restores either.
|
|
18006
|
+
sustained:
|
|
18007
|
+
type: boolean
|
|
18008
|
+
description: Judge the window by accumulated departure rather than bucket by bucket. `anomaly` and `outliers` only; refused alongside `requiredBuckets`.
|
|
18009
|
+
warnThreshold:
|
|
18010
|
+
anyOf:
|
|
18011
|
+
- type: number
|
|
18012
|
+
- type: 'null'
|
|
18013
|
+
description: The milder bound; `null` drops the warning level, leaving the rule with one.
|
|
18014
|
+
recoveryThreshold:
|
|
18015
|
+
anyOf:
|
|
18016
|
+
- type: number
|
|
18017
|
+
- type: 'null'
|
|
18018
|
+
description: What the metric must get back to before a live alert closes; `null` drops the hysteresis.
|
|
18019
|
+
groupAlerts:
|
|
18020
|
+
type: boolean
|
|
18021
|
+
description: Fire one alert per `by()` group. Refused on a metric with no grouping.
|
|
18022
|
+
maxGroups:
|
|
18023
|
+
anyOf:
|
|
18024
|
+
- type: integer
|
|
18025
|
+
minimum: 1
|
|
18026
|
+
maximum: 50
|
|
18027
|
+
- type: 'null'
|
|
18028
|
+
description: How many groups may alert at once; `null` restores the default of 10.
|
|
18029
|
+
noDataMinutes:
|
|
18030
|
+
anyOf:
|
|
18031
|
+
- type: integer
|
|
18032
|
+
minimum: 5
|
|
18033
|
+
maximum: 43200
|
|
18034
|
+
- type: 'null'
|
|
18035
|
+
description: How long a `no_data` rule's silence must last; `null` restores 15 minutes.
|
|
18036
|
+
delayMinutes:
|
|
18037
|
+
anyOf:
|
|
18038
|
+
- type: integer
|
|
18039
|
+
minimum: 1
|
|
18040
|
+
maximum: 1440
|
|
18041
|
+
- type: 'null'
|
|
18042
|
+
description: How far behind live the window is held; `null` drops the delay.
|
|
18043
|
+
autoResolveMinutes:
|
|
18044
|
+
anyOf:
|
|
18045
|
+
- type: integer
|
|
18046
|
+
minimum: 1
|
|
18047
|
+
- type: 'null'
|
|
18048
|
+
description: Close a stale live instance after this long; `null` never auto-resolves.
|
|
18049
|
+
composite:
|
|
18050
|
+
$ref: '#/components/schemas/AlertCompositeSpec'
|
|
16008
18051
|
windowHours:
|
|
16009
18052
|
type: integer
|
|
16010
18053
|
minimum: 1
|
|
16011
18054
|
maximum: 720
|
|
18055
|
+
bucketMinutes:
|
|
18056
|
+
anyOf:
|
|
18057
|
+
- type: integer
|
|
18058
|
+
minimum: 1
|
|
18059
|
+
maximum: 43200
|
|
18060
|
+
- type: 'null'
|
|
18061
|
+
description: Bucket width in minutes; `null` restores the default 12 buckets per window.
|
|
18062
|
+
requiredBuckets:
|
|
18063
|
+
anyOf:
|
|
18064
|
+
- type: integer
|
|
18065
|
+
minimum: 1
|
|
18066
|
+
- type: 'null'
|
|
18067
|
+
description: Buckets that must breach to fire; `null` restores "every bucket that had data".
|
|
16012
18068
|
severity:
|
|
16013
18069
|
type: string
|
|
16014
18070
|
enum:
|
|
@@ -16032,13 +18088,15 @@ components:
|
|
|
16032
18088
|
AlertApiRow:
|
|
16033
18089
|
type: object
|
|
16034
18090
|
description: |-
|
|
16035
|
-
One FIRED alert — a condition the platform observed
|
|
18091
|
+
One FIRED alert — an INSTANCE of a condition the platform observed, not the rule that defines it (alert *rules* are the `/api/admin/alert-rules` resource). Instances are never filed by hand: the UI (killswitch flips) and the worker (analysis consumer + alerts cron) open them, keyed by `(source, dedupeKey)`, and at most one instance per condition is open at a time — re-raising refreshes the open one, and the condition clearing closes it.
|
|
18092
|
+
|
|
18093
|
+
An instance IS an ops queue item (`/api/admin/ops` with `type: "alert"`) seen through the alert lens: same `id`, `severity` is that item's `priority`, and `status` is its work status projected onto three states. Resolving the queue item and clearing the alert are therefore the same act.
|
|
16036
18094
|
|
|
16037
18095
|
Every field is always present on the wire; nullable fields are `null`, never absent.
|
|
16038
18096
|
properties:
|
|
16039
18097
|
id:
|
|
16040
18098
|
type: string
|
|
16041
|
-
description: Stable opaque
|
|
18099
|
+
description: Stable opaque instance id — also the id of the ops queue item this instance is.
|
|
16042
18100
|
source:
|
|
16043
18101
|
type: string
|
|
16044
18102
|
enum:
|
|
@@ -16059,10 +18117,10 @@ components:
|
|
|
16059
18117
|
- danger
|
|
16060
18118
|
- warn
|
|
16061
18119
|
- info
|
|
16062
|
-
description: How loud the alert is — `danger` pages, `warn` is the default, `info` is FYI-only.
|
|
18120
|
+
description: How loud the alert is — `danger` pages, `warn` is the default, `info` is FYI-only. Severity belongs to the RULE and seeds the instance's queue `priority` (`danger`→`critical`, `warn`→`high`, `info`→`medium`); it is read back from there, so re-prioritising the queue item changes what this reports.
|
|
16063
18121
|
dedupeKey:
|
|
16064
18122
|
type: string
|
|
16065
|
-
description: Idempotency + reconcile key within `(project, source)` — re-raising the same condition refreshes the
|
|
18123
|
+
description: Idempotency + reconcile key within `(project, source)` — re-raising the same condition refreshes the open instance instead of stacking duplicates, and the condition clearing closes it. A later firing of the same condition opens a NEW instance with its own `id`.
|
|
16066
18124
|
title:
|
|
16067
18125
|
type: string
|
|
16068
18126
|
description: Short human-readable headline (what fired).
|
|
@@ -16085,10 +18143,10 @@ components:
|
|
|
16085
18143
|
- active
|
|
16086
18144
|
- resolved
|
|
16087
18145
|
- dismissed
|
|
16088
|
-
description: Lifecycle state. `active` means the condition
|
|
18146
|
+
description: Lifecycle state, projected from the queue item's work status. `active` means the item is still open, i.e. the condition holds (shown as "Firing" in the UI); `resolved` means it cleared (auto, when the raiser reconciles, or by hand); `dismissed` means a human waved it off (the item is closed `wont_fix`).
|
|
16089
18147
|
createdAt:
|
|
16090
18148
|
type: string
|
|
16091
|
-
description: ISO-8601 timestamp the
|
|
18149
|
+
description: ISO-8601 timestamp this instance opened — when the condition started firing.
|
|
16092
18150
|
resolvedAt:
|
|
16093
18151
|
description: ISO-8601 timestamp the alert flipped to `resolved`, or `null` while it hasn't.
|
|
16094
18152
|
anyOf:
|
|
@@ -16150,7 +18208,7 @@ components:
|
|
|
16150
18208
|
- active
|
|
16151
18209
|
- resolved
|
|
16152
18210
|
- dismissed
|
|
16153
|
-
description: New lifecycle state. `resolved` / `dismissed` stamp their timestamp; `active` re-opens and clears both.
|
|
18211
|
+
description: New lifecycle state, written through to the queue item (`resolved` / `wont_fix` / `open`). `resolved` / `dismissed` stamp their timestamp; `active` re-opens and clears both.
|
|
16154
18212
|
assigneeId:
|
|
16155
18213
|
description: PERSON owner — a `users.id`, or `null` to clear the assignment.
|
|
16156
18214
|
anyOf:
|
|
@@ -16336,6 +18394,12 @@ components:
|
|
|
16336
18394
|
- type: boolean
|
|
16337
18395
|
- type: number
|
|
16338
18396
|
description: Whether key-authenticated public ticket creation (`POST /cli/report`) is allowed into this project. Off by default.
|
|
18397
|
+
errorAutocloseDays:
|
|
18398
|
+
type: integer
|
|
18399
|
+
description: Days an `open` tracked error may go unseen before the nightly sweep auto-resolves it. `0` disables auto-close for this project. Ingest reopens a resolved error the moment it recurs, so this never hides a live issue.
|
|
18400
|
+
errorTicketMinOccurrences:
|
|
18401
|
+
type: integer
|
|
18402
|
+
description: Occurrence count a tracked error must cross before an `error` ticket is auto-filed into the ops queue. Customising it requires a paid plan; unentitled projects always run at the platform default of 10.
|
|
16339
18403
|
stripeSubscriptionId:
|
|
16340
18404
|
anyOf:
|
|
16341
18405
|
- type: string
|
|
@@ -16415,6 +18479,8 @@ components:
|
|
|
16415
18479
|
- moduleUser
|
|
16416
18480
|
- moduleEvents
|
|
16417
18481
|
- allowPublicTickets
|
|
18482
|
+
- errorAutocloseDays
|
|
18483
|
+
- errorTicketMinOccurrences
|
|
16418
18484
|
- slug
|
|
16419
18485
|
- logo
|
|
16420
18486
|
- defaultEnv
|
|
@@ -16633,6 +18699,16 @@ components:
|
|
|
16633
18699
|
minimum: 0.0001
|
|
16634
18700
|
maximum: 0.05
|
|
16635
18701
|
description: SRM chi-square p-value below which the run is called invalid.
|
|
18702
|
+
errorAutocloseDays:
|
|
18703
|
+
type: integer
|
|
18704
|
+
minimum: 0
|
|
18705
|
+
maximum: 365
|
|
18706
|
+
description: Days an `open` tracked error may go unseen before the nightly sweep auto-resolves it. `0` disables auto-close for this project.
|
|
18707
|
+
errorTicketMinOccurrences:
|
|
18708
|
+
type: integer
|
|
18709
|
+
minimum: 1
|
|
18710
|
+
maximum: 10000
|
|
18711
|
+
description: Occurrence count a tracked error must cross before an `error` ticket is auto-filed into the ops queue. Requires a paid plan — the request is rejected with 403 on a plan without the `ops_auto_error_issues` entitlement.
|
|
16636
18712
|
additionalProperties: false
|
|
16637
18713
|
description: Body for `PATCH /api/admin/projects/{id}`. Partial — every field is optional; only supplied fields change. The project id in the path must match the caller's own project.
|
|
16638
18714
|
ListI18nProfilesResponse:
|
|
@@ -17701,21 +19777,50 @@ components:
|
|
|
17701
19777
|
- config
|
|
17702
19778
|
additionalProperties: false
|
|
17703
19779
|
description: Create a Claude Code routine trigger in one shot. Idempotent by `config.routineId` — re-creating with the same routine id updates the existing row.
|
|
19780
|
+
CursorTriggerRepo:
|
|
19781
|
+
type: object
|
|
19782
|
+
properties:
|
|
19783
|
+
url:
|
|
19784
|
+
type: string
|
|
19785
|
+
format: uri
|
|
19786
|
+
description: Repo the cloud agent runs against, e.g. `https://github.com/owner/repo`.
|
|
19787
|
+
startingRef:
|
|
19788
|
+
type: string
|
|
19789
|
+
minLength: 1
|
|
19790
|
+
description: Optional branch this repo's runs start from. Omit for the repo's default branch.
|
|
19791
|
+
required:
|
|
19792
|
+
- url
|
|
19793
|
+
additionalProperties: false
|
|
19794
|
+
description: One repo a trigger runs against, with the branch its runs start from.
|
|
17704
19795
|
CursorTriggerConfig:
|
|
17705
19796
|
type: object
|
|
17706
19797
|
properties:
|
|
17707
19798
|
repoUrl:
|
|
17708
19799
|
type: string
|
|
17709
19800
|
format: uri
|
|
17710
|
-
description:
|
|
19801
|
+
description: '**First** repo the cloud agent runs against, e.g. `https://github.com/owner/repo`. Idempotency key for the connector, and always a mirror of `repos[0].url` when `repos` is supplied.'
|
|
17711
19802
|
startingRef:
|
|
17712
19803
|
type: string
|
|
17713
19804
|
minLength: 1
|
|
17714
|
-
description: Optional git ref the run starts from.
|
|
19805
|
+
description: Optional git ref the run starts from. Mirrors `repos[0].startingRef`. Pinned onto the Cursor agent at creation, so changing it provisions a replacement agent.
|
|
19806
|
+
repos:
|
|
19807
|
+
type: array
|
|
19808
|
+
minItems: 1
|
|
19809
|
+
items:
|
|
19810
|
+
$ref: '#/components/schemas/CursorTriggerRepo'
|
|
19811
|
+
description: Every repo this trigger runs against, each with its own starting branch — Cursor launches ONE agent across the whole set. Omit for a single-repo trigger, which is then described by `repoUrl`/`startingRef` alone; when supplied, the first entry must match them. Changing the set re-provisions the agent (its repos are pinned at creation).
|
|
17715
19812
|
projectId:
|
|
17716
19813
|
type: string
|
|
17717
19814
|
minLength: 1
|
|
17718
19815
|
description: Shipeasy project id the run targets.
|
|
19816
|
+
agentId:
|
|
19817
|
+
type: string
|
|
19818
|
+
minLength: 1
|
|
19819
|
+
description: Server-managed. The reusable Cursor cloud agent (`bc-…`) Shipeasy provisions once at connect and then starts every run on. A supplied value is ignored on create; if Cursor stops recognising the id (404), the next fire provisions a replacement and stores it here.
|
|
19820
|
+
fireText:
|
|
19821
|
+
type: string
|
|
19822
|
+
minLength: 1
|
|
19823
|
+
description: Optional standing instruction prepended to every run's prompt — the trigger's base prompt. Lets two triggers on different repos steer their runs differently without changing the `/shipeasy-ops-work` task block.
|
|
17719
19824
|
required:
|
|
17720
19825
|
- repoUrl
|
|
17721
19826
|
- projectId
|
|
@@ -17750,7 +19855,7 @@ components:
|
|
|
17750
19855
|
opsKey:
|
|
17751
19856
|
type: string
|
|
17752
19857
|
minLength: 1
|
|
17753
|
-
description: Restricted Shipeasy ops key
|
|
19858
|
+
description: Restricted Shipeasy ops key (secret). Sent as the Bearer for the Shipeasy MCP server handed to each run inline — never in the prompt text or the run env. Encrypted; never returned.
|
|
17754
19859
|
enabled:
|
|
17755
19860
|
type: boolean
|
|
17756
19861
|
default: true
|
|
@@ -17762,13 +19867,33 @@ components:
|
|
|
17762
19867
|
- opsKey
|
|
17763
19868
|
additionalProperties: false
|
|
17764
19869
|
description: Create a Cursor cloud-agent trigger. Both keys are required up front (never tokenless). Idempotent by `config.repoUrl`.
|
|
19870
|
+
CopilotTriggerRepo:
|
|
19871
|
+
type: object
|
|
19872
|
+
properties:
|
|
19873
|
+
owner:
|
|
19874
|
+
type: string
|
|
19875
|
+
minLength: 1
|
|
19876
|
+
description: GitHub repo owner.
|
|
19877
|
+
repo:
|
|
19878
|
+
type: string
|
|
19879
|
+
minLength: 1
|
|
19880
|
+
description: GitHub repo name.
|
|
19881
|
+
baseRef:
|
|
19882
|
+
type: string
|
|
19883
|
+
minLength: 1
|
|
19884
|
+
description: Optional base ref this repo's agent task branches from. Omit for the repo's default branch.
|
|
19885
|
+
required:
|
|
19886
|
+
- owner
|
|
19887
|
+
- repo
|
|
19888
|
+
additionalProperties: false
|
|
19889
|
+
description: One repo a Copilot trigger runs against, with the base branch its tasks branch from.
|
|
17765
19890
|
CopilotTriggerConfig:
|
|
17766
19891
|
type: object
|
|
17767
19892
|
properties:
|
|
17768
19893
|
owner:
|
|
17769
19894
|
type: string
|
|
17770
19895
|
minLength: 1
|
|
17771
|
-
description: GitHub repo owner. Together with `repo` forms the connector's idempotency key (`owner/repo`).
|
|
19896
|
+
description: '**First** GitHub repo owner. Together with `repo` forms the connector''s idempotency key (`owner/repo`), and both mirror `repos[0]` when `repos` is supplied.'
|
|
17772
19897
|
repo:
|
|
17773
19898
|
type: string
|
|
17774
19899
|
minLength: 1
|
|
@@ -17776,11 +19901,21 @@ components:
|
|
|
17776
19901
|
baseRef:
|
|
17777
19902
|
type: string
|
|
17778
19903
|
minLength: 1
|
|
17779
|
-
description: Optional base ref the agent branches from.
|
|
19904
|
+
description: Optional base ref the agent branches from. Mirrors `repos[0].baseRef`.
|
|
19905
|
+
repos:
|
|
19906
|
+
type: array
|
|
19907
|
+
minItems: 1
|
|
19908
|
+
items:
|
|
19909
|
+
$ref: '#/components/schemas/CopilotTriggerRepo'
|
|
19910
|
+
description: Every repo this trigger runs against, each with its own base branch. GitHub's agent-tasks API is per-repo, so ONE fire starts one task per entry. Omit for a single-repo trigger, which is then described by `owner`/`repo`/`baseRef` alone; when supplied, the first entry must match them.
|
|
17780
19911
|
projectId:
|
|
17781
19912
|
type: string
|
|
17782
19913
|
minLength: 1
|
|
17783
19914
|
description: Shipeasy project id the run targets.
|
|
19915
|
+
fireText:
|
|
19916
|
+
type: string
|
|
19917
|
+
minLength: 1
|
|
19918
|
+
description: Optional standing instruction prepended to every run's prompt — the trigger's base prompt. Lets two triggers on different repos steer their runs differently without changing the `/shipeasy-ops-work` task block.
|
|
17784
19919
|
required:
|
|
17785
19920
|
- owner
|
|
17786
19921
|
- repo
|
|
@@ -17838,6 +19973,10 @@ components:
|
|
|
17838
19973
|
type: string
|
|
17839
19974
|
minLength: 1
|
|
17840
19975
|
description: Shipeasy project id the run targets.
|
|
19976
|
+
fireText:
|
|
19977
|
+
type: string
|
|
19978
|
+
minLength: 1
|
|
19979
|
+
description: Optional standing instruction prepended to every run's prompt — the trigger's base prompt. Lets two triggers on different repos steer their runs differently without changing the `/shipeasy-ops-work` task block.
|
|
17841
19980
|
required:
|
|
17842
19981
|
- source
|
|
17843
19982
|
- projectId
|
|
@@ -18037,7 +20176,7 @@ components:
|
|
|
18037
20176
|
- provider
|
|
18038
20177
|
- config
|
|
18039
20178
|
additionalProperties: false
|
|
18040
|
-
description: Per-provider PATCH body for editing an existing `cursor_trigger` connector. `config` replaces the stored config wholesale
|
|
20179
|
+
description: 'Per-provider PATCH body for editing an existing `cursor_trigger` connector. `config` replaces the stored config wholesale, except for the server-managed keys: the provisioned `agentId` is carried over (and dropped, so a replacement agent is provisioned, when `repoUrl`/`startingRef` change), as is the last-run pointer. `name` and either credential are optional (a supplied credential rotates just that key).'
|
|
18041
20180
|
UpdateCopilotTriggerRequest:
|
|
18042
20181
|
type: object
|
|
18043
20182
|
properties:
|
|
@@ -18163,6 +20302,11 @@ components:
|
|
|
18163
20302
|
- type: string
|
|
18164
20303
|
- type: 'null'
|
|
18165
20304
|
description: Human label for the key. `null` for unnamed dashboard mints; programmatic mints auto-name themselves.
|
|
20305
|
+
description:
|
|
20306
|
+
anyOf:
|
|
20307
|
+
- type: string
|
|
20308
|
+
- type: 'null'
|
|
20309
|
+
description: Free-text note recording what the key is for (the service that holds it, the rotation owner, the ticket it was minted under). Display only — `null` unless someone set it via `PATCH /api/admin/keys/{id}`.
|
|
18166
20310
|
scopes:
|
|
18167
20311
|
anyOf:
|
|
18168
20312
|
- type: array
|
|
@@ -18184,6 +20328,7 @@ components:
|
|
|
18184
20328
|
- expires_at
|
|
18185
20329
|
- created_by_email
|
|
18186
20330
|
- name
|
|
20331
|
+
- description
|
|
18187
20332
|
- scopes
|
|
18188
20333
|
- last4
|
|
18189
20334
|
additionalProperties: false
|
|
@@ -18222,8 +20367,8 @@ components:
|
|
|
18222
20367
|
name:
|
|
18223
20368
|
type: string
|
|
18224
20369
|
minLength: 1
|
|
18225
|
-
maxLength:
|
|
18226
|
-
description: Optional human label. Programmatic (API) mints that omit it get an auto-generated descriptive name; dashboard mints may leave it blank.
|
|
20370
|
+
maxLength: 160
|
|
20371
|
+
description: Optional human label. Programmatic (API) mints that omit it get an auto-generated descriptive name; dashboard mints may leave it blank. The cap is generous because provenance labels are composed, not typed — `shipeasy setup` mints keys named with the stack, package, date, and operator that produced them, which does not fit in a one-line-input budget.
|
|
18227
20372
|
scopes:
|
|
18228
20373
|
type: array
|
|
18229
20374
|
items:
|
|
@@ -18291,6 +20436,30 @@ components:
|
|
|
18291
20436
|
- key
|
|
18292
20437
|
- expires_at
|
|
18293
20438
|
additionalProperties: false
|
|
20439
|
+
UpdateKeyRequest:
|
|
20440
|
+
type: object
|
|
20441
|
+
description: |-
|
|
20442
|
+
Body for `PATCH /api/admin/keys/{id}`. Only the key's **label** is editable — `name` and `description`.
|
|
20443
|
+
|
|
20444
|
+
Everything that gives a key its authority (`type`, `env`, `scopes`, `expires_at`) is fixed at mint: those are the isolation boundary the worker derives the read env and permissions from, so changing them would silently re-point a credential that is already deployed. Rotate instead — mint a replacement and revoke the old key.
|
|
20445
|
+
|
|
20446
|
+
Omitted fields are left untouched; send `null` to clear one.
|
|
20447
|
+
properties:
|
|
20448
|
+
name:
|
|
20449
|
+
anyOf:
|
|
20450
|
+
- type: string
|
|
20451
|
+
minLength: 1
|
|
20452
|
+
maxLength: 160
|
|
20453
|
+
- type: 'null'
|
|
20454
|
+
description: New human label, or `null` to clear it. Same 160-char budget as create — provenance labels are composed, not typed.
|
|
20455
|
+
description:
|
|
20456
|
+
anyOf:
|
|
20457
|
+
- type: string
|
|
20458
|
+
minLength: 1
|
|
20459
|
+
maxLength: 500
|
|
20460
|
+
- type: 'null'
|
|
20461
|
+
description: New free-text note, or `null` to clear it.
|
|
20462
|
+
additionalProperties: false
|
|
18294
20463
|
RevokeKeyResponse:
|
|
18295
20464
|
type: object
|
|
18296
20465
|
description: Confirms the key is revoked. Idempotent — revoking an already-revoked key returns the same shape.
|
|
@@ -18351,6 +20520,85 @@ components:
|
|
|
18351
20520
|
required:
|
|
18352
20521
|
- hits
|
|
18353
20522
|
additionalProperties: false
|
|
20523
|
+
Tag:
|
|
20524
|
+
type: object
|
|
20525
|
+
properties:
|
|
20526
|
+
id:
|
|
20527
|
+
type: string
|
|
20528
|
+
description: Stable opaque tag id.
|
|
20529
|
+
name:
|
|
20530
|
+
type: string
|
|
20531
|
+
description: Display name — also the tag's identity, unique case-insensitively within the project.
|
|
20532
|
+
required:
|
|
20533
|
+
- id
|
|
20534
|
+
- name
|
|
20535
|
+
additionalProperties: false
|
|
20536
|
+
ListTagsResponse:
|
|
20537
|
+
type: array
|
|
20538
|
+
items:
|
|
20539
|
+
$ref: '#/components/schemas/Tag'
|
|
20540
|
+
description: The project's tags, sorted by name.
|
|
20541
|
+
TaggableEntityType:
|
|
20542
|
+
type: string
|
|
20543
|
+
enum:
|
|
20544
|
+
- ops
|
|
20545
|
+
- flag
|
|
20546
|
+
- config
|
|
20547
|
+
- killswitch
|
|
20548
|
+
- metric
|
|
20549
|
+
- error
|
|
20550
|
+
- alert_rule
|
|
20551
|
+
- experiment
|
|
20552
|
+
description: 'The kind of item a tag set hangs off: `ops` (any queue item — bug, feature request, error/alert/measure-plan ticket), `flag` (feature gate), `config` (dynamic config), `killswitch`, `metric`, `error` (tracked error group), `alert_rule`, or `experiment`.'
|
|
20553
|
+
EntityTagsResponse:
|
|
20554
|
+
type: object
|
|
20555
|
+
properties:
|
|
20556
|
+
entityType:
|
|
20557
|
+
$ref: '#/components/schemas/TaggableEntityType'
|
|
20558
|
+
entityId:
|
|
20559
|
+
type: string
|
|
20560
|
+
description: The item's canonical id (the handle you passed, resolved).
|
|
20561
|
+
tags:
|
|
20562
|
+
type: array
|
|
20563
|
+
items:
|
|
20564
|
+
type: string
|
|
20565
|
+
description: The tag names now attached to the item, sorted by name.
|
|
20566
|
+
required:
|
|
20567
|
+
- entityType
|
|
20568
|
+
- entityId
|
|
20569
|
+
- tags
|
|
20570
|
+
additionalProperties: false
|
|
20571
|
+
SetEntityTagsRequest:
|
|
20572
|
+
type: object
|
|
20573
|
+
properties:
|
|
20574
|
+
tags:
|
|
20575
|
+
type: array
|
|
20576
|
+
maxItems: 50
|
|
20577
|
+
items:
|
|
20578
|
+
$ref: '#/components/schemas/TagName'
|
|
20579
|
+
description: The complete tag set the item should carry — tags not listed are detached. Names are get-or-created (a new name mints a project tag), deduped case-insensitively; `[]` clears every tag.
|
|
20580
|
+
required:
|
|
20581
|
+
- tags
|
|
20582
|
+
additionalProperties: false
|
|
20583
|
+
UpdateEntityTagsRequest:
|
|
20584
|
+
type: object
|
|
20585
|
+
properties:
|
|
20586
|
+
add:
|
|
20587
|
+
type: array
|
|
20588
|
+
maxItems: 50
|
|
20589
|
+
items:
|
|
20590
|
+
$ref: '#/components/schemas/TagName'
|
|
20591
|
+
default: []
|
|
20592
|
+
description: Tag names to attach (get-or-created by name, case-insensitive). Already-attached names are a no-op.
|
|
20593
|
+
remove:
|
|
20594
|
+
type: array
|
|
20595
|
+
maxItems: 50
|
|
20596
|
+
items:
|
|
20597
|
+
$ref: '#/components/schemas/TagName'
|
|
20598
|
+
default: []
|
|
20599
|
+
description: Tag names to detach (case-insensitive). Names the item doesn't carry are a no-op. A name in both lists is removed.
|
|
20600
|
+
additionalProperties: false
|
|
20601
|
+
description: Incremental tag edit — pass `add`, `remove`, or both. Every other tag on the item is left as is.
|
|
18354
20602
|
responses:
|
|
18355
20603
|
BadRequest:
|
|
18356
20604
|
description: The request was malformed (bad JSON or missing project scope).
|
|
@@ -18459,6 +20707,45 @@ components:
|
|
|
18459
20707
|
value:
|
|
18460
20708
|
error: The referenced event is still pending review and cannot back a metric yet.
|
|
18461
20709
|
code: EVENT_PENDING
|
|
20710
|
+
PayloadTooLarge:
|
|
20711
|
+
description: The request body exceeded the intake's fixed size cap (16 KB).
|
|
20712
|
+
content:
|
|
20713
|
+
application/json:
|
|
20714
|
+
schema:
|
|
20715
|
+
$ref: '#/components/schemas/Error'
|
|
20716
|
+
examples:
|
|
20717
|
+
BAD_REQUEST:
|
|
20718
|
+
summary: Body too large
|
|
20719
|
+
value:
|
|
20720
|
+
error: Body too large
|
|
20721
|
+
code: BAD_REQUEST
|
|
20722
|
+
TooManyRequests:
|
|
20723
|
+
description: |-
|
|
20724
|
+
The public intake is rate-limited per (project, client IP). Back off and retry;
|
|
20725
|
+
the limit is a burst guard, not a quota, so a modest delay clears it.
|
|
20726
|
+
content:
|
|
20727
|
+
application/json:
|
|
20728
|
+
schema:
|
|
20729
|
+
$ref: '#/components/schemas/Error'
|
|
20730
|
+
examples:
|
|
20731
|
+
BAD_REQUEST:
|
|
20732
|
+
summary: Rate limited
|
|
20733
|
+
value:
|
|
20734
|
+
error: Too many requests
|
|
20735
|
+
code: BAD_REQUEST
|
|
20736
|
+
ServiceUnavailable:
|
|
20737
|
+
description: |-
|
|
20738
|
+
A backing store the endpoint needs is not bound in this environment. Transient
|
|
20739
|
+
and infrastructural — no stable `ErrorCode` is assigned, so `code` is omitted.
|
|
20740
|
+
content:
|
|
20741
|
+
application/json:
|
|
20742
|
+
schema:
|
|
20743
|
+
$ref: '#/components/schemas/Error'
|
|
20744
|
+
examples:
|
|
20745
|
+
UNAVAILABLE:
|
|
20746
|
+
summary: Storage unbound
|
|
20747
|
+
value:
|
|
20748
|
+
error: Unavailable
|
|
18462
20749
|
BadGateway:
|
|
18463
20750
|
description: |-
|
|
18464
20751
|
The request was well-formed and the resource exists, but a downstream provider
|