@shipeasy/openapi 3.2.0 → 3.4.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-RTN572TI.js → chunk-JJA7XEPU.js} +91 -1
- package/dist/chunk-JJA7XEPU.js.map +1 -0
- package/dist/{chunk-DW33MG4B.js → chunk-Z3CY5Y44.js} +514 -126
- package/dist/chunk-Z3CY5Y44.js.map +1 -0
- package/dist/{client-BPVn4hMC.d.ts → client-CkRbr8I2.d.ts} +1544 -212
- package/dist/client.d.ts +1 -1
- package/dist/client.js +23 -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 +24 -2
- package/dist/index.js.map +1 -1
- package/dist/schemas.d.ts +1935 -963
- package/dist/schemas.js +141 -1
- package/openapi-sdk.json +31 -9
- package/openapi.json +10449 -8118
- package/openapi.yaml +2274 -634
- package/package.json +1 -1
- package/spec/components/schemas/alert-rules.yaml +434 -10
- 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/keys.yaml +39 -0
- package/spec/components/schemas/metrics.yaml +131 -251
- package/spec/components/schemas/ops.yaml +471 -29
- package/spec/components/schemas/projects.yaml +18 -0
- package/spec/components/schemas/search.yaml +1 -0
- package/spec/components/schemas/tags.yaml +91 -0
- package/spec/openapi.yaml +56 -0
- package/spec/paths/alerts.yaml +5 -3
- package/spec/paths/i18n.yaml +2 -1
- package/spec/paths/keys.yaml +79 -0
- package/spec/paths/metrics.yaml +26 -17
- package/spec/paths/ops.yaml +514 -11
- package/spec/paths/tags.yaml +270 -0
- package/dist/chunk-DW33MG4B.js.map +0 -1
- package/dist/chunk-RTN572TI.js.map +0 -1
package/openapi.yaml
CHANGED
|
@@ -216,6 +216,35 @@ 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`.
|
|
237
|
+
- name: QA notes
|
|
238
|
+
parent: Ops
|
|
239
|
+
description: |-
|
|
240
|
+
Typed QA notes on a queue item — the QA follow-up that is not discussion.
|
|
241
|
+
Each note is one of four kinds: `narrowing` (only part of the bug still
|
|
242
|
+
fails), `clarification` (changes what "fixed" means), `verification` (a
|
|
243
|
+
`pass` / `fail` verdict on a fix) or `correction` (withdraws an earlier
|
|
244
|
+
framing). Notes are append-only, carry their author and time, and render in
|
|
245
|
+
their own section of the item's detail panel, separate from the comment
|
|
246
|
+
thread. A failing verification offers a "Reopen item" action in the
|
|
247
|
+
dashboard; it is always an explicit click, never a side effect of `create`.
|
|
219
248
|
- name: Projects
|
|
220
249
|
description: |-
|
|
221
250
|
Projects: the account-level container every other resource is scoped to.
|
|
@@ -258,6 +287,19 @@ tags:
|
|
|
258
287
|
Continue) schedule on their own surface — typically a GitHub Actions
|
|
259
288
|
`schedule:` cron running the platform's headless CLI with the shared
|
|
260
289
|
trigger prompt.
|
|
290
|
+
- name: Tags
|
|
291
|
+
description: |-
|
|
292
|
+
Tags: free-form, project-scoped labels any item can carry — queue items
|
|
293
|
+
(bugs, feature requests, error/alert tickets), flags, configs, kill
|
|
294
|
+
switches, metrics, tracked errors, alert rules, and experiments all share
|
|
295
|
+
one tag roster.
|
|
296
|
+
|
|
297
|
+
**Identity.** A tag is its name, unique case-insensitively per project. A
|
|
298
|
+
tag is born the first time it's attached — there is no separate create.
|
|
299
|
+
|
|
300
|
+
**Addressing.** An item is named by `entityType` + its handle (an ops
|
|
301
|
+
item's number, a resource's name, or any id). `set` replaces the full tag
|
|
302
|
+
set; `update` adds/removes names incrementally.
|
|
261
303
|
- name: Connectors
|
|
262
304
|
description: |-
|
|
263
305
|
Outbound integrations: the per-project destinations feedback + trigger
|
|
@@ -4561,12 +4603,15 @@ paths:
|
|
|
4561
4603
|
name: checkouts
|
|
4562
4604
|
folder: null
|
|
4563
4605
|
eventName: checkout_completed
|
|
4564
|
-
query:
|
|
4606
|
+
query: count(checkout_completed)
|
|
4565
4607
|
queryIr:
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4608
|
+
v: 2
|
|
4609
|
+
expr:
|
|
4610
|
+
node: agg
|
|
4611
|
+
event: checkout_completed
|
|
4612
|
+
agg:
|
|
4613
|
+
kind: count
|
|
4614
|
+
filters: []
|
|
4570
4615
|
direction: higher_better
|
|
4571
4616
|
version: 1
|
|
4572
4617
|
'400':
|
|
@@ -4600,7 +4645,7 @@ paths:
|
|
|
4600
4645
|
|
|
4601
4646
|
**Use cases**
|
|
4602
4647
|
|
|
4603
|
-
- **Track an event** — `
|
|
4648
|
+
- **Track an event** — `count(<event>)` for event counts.
|
|
4604
4649
|
- **Sum a value** — `sum(<event>, <label>)` for revenue / quantity metrics.
|
|
4605
4650
|
- **Experiment success metric** — create the metric, then attach its id to an experiment.
|
|
4606
4651
|
tags:
|
|
@@ -4614,13 +4659,13 @@ paths:
|
|
|
4614
4659
|
schema:
|
|
4615
4660
|
$ref: '#/components/schemas/CreateMetricRequest'
|
|
4616
4661
|
examples:
|
|
4617
|
-
|
|
4618
|
-
summary: Count
|
|
4619
|
-
description:
|
|
4662
|
+
countEvents:
|
|
4663
|
+
summary: Count an event (DSL)
|
|
4664
|
+
description: Completed checkouts, expressed with the query DSL.
|
|
4620
4665
|
value:
|
|
4621
4666
|
name: checkouts
|
|
4622
4667
|
event_name: checkout_completed
|
|
4623
|
-
query:
|
|
4668
|
+
query: count(checkout_completed)
|
|
4624
4669
|
sumRevenue:
|
|
4625
4670
|
summary: Sum a value label (DSL)
|
|
4626
4671
|
description: Total revenue, summing the `amount` property of the `purchase` event.
|
|
@@ -4637,10 +4682,13 @@ paths:
|
|
|
4637
4682
|
name: checkouts
|
|
4638
4683
|
event_name: checkout_completed
|
|
4639
4684
|
query_ir:
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4685
|
+
v: 2
|
|
4686
|
+
expr:
|
|
4687
|
+
node: agg
|
|
4688
|
+
event: checkout_completed
|
|
4689
|
+
agg:
|
|
4690
|
+
kind: count
|
|
4691
|
+
filters: []
|
|
4644
4692
|
responses:
|
|
4645
4693
|
'201':
|
|
4646
4694
|
description: Create a metric
|
|
@@ -4721,11 +4769,14 @@ paths:
|
|
|
4721
4769
|
eventName: purchase
|
|
4722
4770
|
query: sum(purchase, amount)
|
|
4723
4771
|
queryIr:
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4772
|
+
v: 2
|
|
4773
|
+
expr:
|
|
4774
|
+
node: agg
|
|
4775
|
+
event: purchase
|
|
4776
|
+
agg:
|
|
4777
|
+
kind: sum
|
|
4778
|
+
valueLabel: amount
|
|
4779
|
+
filters: []
|
|
4729
4780
|
direction: higher_better
|
|
4730
4781
|
winsorizePct: 99
|
|
4731
4782
|
version: 1
|
|
@@ -5431,7 +5482,11 @@ paths:
|
|
|
5431
5482
|
operationId: listOpsItems
|
|
5432
5483
|
summary: List the operational queue
|
|
5433
5484
|
description: |-
|
|
5434
|
-
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.
|
|
5485
|
+
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.
|
|
5486
|
+
|
|
5487
|
+
**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).
|
|
5488
|
+
|
|
5489
|
+
**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.
|
|
5435
5490
|
|
|
5436
5491
|
**Use case:** Pull the open queue to triage — e.g. every `bug` still `open` — before working items down one by one.
|
|
5437
5492
|
tags:
|
|
@@ -5441,8 +5496,9 @@ paths:
|
|
|
5441
5496
|
- name: type
|
|
5442
5497
|
in: query
|
|
5443
5498
|
required: false
|
|
5444
|
-
description: Filter by item type
|
|
5499
|
+
description: Filter by item type, or `all` (the default). Every type a returned item can carry is filterable, including the auto-filed ones.
|
|
5445
5500
|
schema:
|
|
5501
|
+
default: all
|
|
5446
5502
|
anyOf:
|
|
5447
5503
|
- type: string
|
|
5448
5504
|
enum:
|
|
@@ -5450,30 +5506,70 @@ paths:
|
|
|
5450
5506
|
- feature_request
|
|
5451
5507
|
- error
|
|
5452
5508
|
- alert
|
|
5453
|
-
|
|
5509
|
+
- measure_plan
|
|
5510
|
+
description: Queue item type. `bug` and `feature_request` are user-fileable; `error`, `alert`, and `measure_plan` tickets are auto-filed by the platform.
|
|
5454
5511
|
- type: string
|
|
5455
5512
|
const: all
|
|
5456
5513
|
- name: status
|
|
5457
5514
|
in: query
|
|
5458
5515
|
required: false
|
|
5459
|
-
description: Filter by lifecycle status, or `all
|
|
5516
|
+
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.
|
|
5460
5517
|
schema:
|
|
5518
|
+
default: all
|
|
5461
5519
|
anyOf:
|
|
5462
5520
|
- $ref: '#/components/schemas/OpsItemStatus'
|
|
5521
|
+
- type: string
|
|
5522
|
+
const: unresolved
|
|
5523
|
+
- type: string
|
|
5524
|
+
const: all
|
|
5525
|
+
x-cli:
|
|
5526
|
+
default: unresolved
|
|
5527
|
+
x-mcp:
|
|
5528
|
+
default: unresolved
|
|
5529
|
+
- name: priority
|
|
5530
|
+
in: query
|
|
5531
|
+
required: false
|
|
5532
|
+
description: Filter by triage priority, or `all` (the default). Items with no priority set are returned only under `all`.
|
|
5533
|
+
schema:
|
|
5534
|
+
default: all
|
|
5535
|
+
anyOf:
|
|
5536
|
+
- $ref: '#/components/schemas/OpsItemPriority'
|
|
5463
5537
|
- type: string
|
|
5464
5538
|
const: all
|
|
5539
|
+
- name: scope
|
|
5540
|
+
in: query
|
|
5541
|
+
required: false
|
|
5542
|
+
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.'
|
|
5543
|
+
schema:
|
|
5544
|
+
type: string
|
|
5545
|
+
enum:
|
|
5546
|
+
- all
|
|
5547
|
+
- ready
|
|
5548
|
+
default: all
|
|
5465
5549
|
- name: limit
|
|
5466
5550
|
in: query
|
|
5467
5551
|
required: false
|
|
5468
|
-
description:
|
|
5552
|
+
description: Page size — max items to return (1–500). A page shorter than `limit` is the last one.
|
|
5469
5553
|
schema:
|
|
5470
5554
|
type: integer
|
|
5471
5555
|
minimum: 1
|
|
5472
5556
|
maximum: 500
|
|
5557
|
+
default: 200
|
|
5558
|
+
x-mcp:
|
|
5559
|
+
required: true
|
|
5560
|
+
- name: offset
|
|
5561
|
+
in: query
|
|
5562
|
+
required: false
|
|
5563
|
+
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.
|
|
5564
|
+
schema:
|
|
5565
|
+
type: integer
|
|
5566
|
+
minimum: 0
|
|
5567
|
+
maximum: 100000
|
|
5568
|
+
default: 0
|
|
5473
5569
|
- name: owner
|
|
5474
5570
|
in: query
|
|
5475
5571
|
required: false
|
|
5476
|
-
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
|
|
5572
|
+
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.
|
|
5477
5573
|
schema:
|
|
5478
5574
|
type: string
|
|
5479
5575
|
responses:
|
|
@@ -5519,6 +5615,8 @@ paths:
|
|
|
5519
5615
|
- FORBIDDEN
|
|
5520
5616
|
x-cli:
|
|
5521
5617
|
name: list
|
|
5618
|
+
x-mcp:
|
|
5619
|
+
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.'
|
|
5522
5620
|
post:
|
|
5523
5621
|
operationId: createOpsItem
|
|
5524
5622
|
summary: File a queue item
|
|
@@ -5615,6 +5713,8 @@ paths:
|
|
|
5615
5713
|
|
|
5616
5714
|
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.
|
|
5617
5715
|
|
|
5716
|
+
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.
|
|
5717
|
+
|
|
5618
5718
|
This endpoint is served by the Shipeasy **edge worker** (`api.shipeasy.ai`), not the admin API — see `servers` below.
|
|
5619
5719
|
|
|
5620
5720
|
**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": "…" }`.
|
|
@@ -5694,7 +5794,7 @@ paths:
|
|
|
5694
5794
|
description: |-
|
|
5695
5795
|
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.
|
|
5696
5796
|
|
|
5697
|
-
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.
|
|
5797
|
+
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.
|
|
5698
5798
|
|
|
5699
5799
|
This endpoint is served by the Shipeasy **edge worker** (`api.shipeasy.ai`), not the admin API — see `servers` below.
|
|
5700
5800
|
|
|
@@ -6013,6 +6113,11 @@ paths:
|
|
|
6013
6113
|
list` and use one of those (or connect the agent under Settings →
|
|
6014
6114
|
Triggers).
|
|
6015
6115
|
|
|
6116
|
+
**Launching.** When the named agent has a connected trigger and you pass
|
|
6117
|
+
no `sessionId`, the ack also fires that trigger — a new provider run
|
|
6118
|
+
starts working the item. Pass `launch: false` to only claim the item and
|
|
6119
|
+
record the run (you are doing the work yourself), without starting one.
|
|
6120
|
+
|
|
6016
6121
|
**Completion.** The run closes automatically on the loop's final actions —
|
|
6017
6122
|
linking the fixing PR (`link-pr`), an ops-notify escalation, or a
|
|
6018
6123
|
completion status change (`ready_for_qa`/`resolved`) — and the dashboard
|
|
@@ -6134,7 +6239,9 @@ paths:
|
|
|
6134
6239
|
(`kind: investigated`), a blocking question for the team (`kind:
|
|
6135
6240
|
question`), or how to verify the fix (`kind: ready_for_qa` with
|
|
6136
6241
|
`qaNotes`). Append-only and create-only, so it is safe for restricted ops
|
|
6137
|
-
keys.
|
|
6242
|
+
keys. For a decision between options you can name, ask a structured
|
|
6243
|
+
question instead (`ops questions ask`) — it is answerable in one tap and
|
|
6244
|
+
the answer comes back to your run.
|
|
6138
6245
|
|
|
6139
6246
|
**Use case:** After working an item, leave a findings write-up (summary,
|
|
6140
6247
|
markdown findings, sources inspected, confidence) so the team — and the
|
|
@@ -6277,53 +6384,88 @@ paths:
|
|
|
6277
6384
|
positional:
|
|
6278
6385
|
- handle
|
|
6279
6386
|
- investigationId
|
|
6280
|
-
/api/admin/
|
|
6387
|
+
/api/admin/ops/{handle}/questions:
|
|
6281
6388
|
get:
|
|
6282
|
-
operationId:
|
|
6283
|
-
summary: List
|
|
6389
|
+
operationId: listOpsQuestions
|
|
6390
|
+
summary: List an item's questions
|
|
6284
6391
|
description: |-
|
|
6285
|
-
The
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6392
|
+
The structured questions asked on a queue item, with their answers —
|
|
6393
|
+
newest first (max 100). Pull this to read the answers to questions you
|
|
6394
|
+
asked: an answered question reads `status: completed` and carries
|
|
6395
|
+
`answer.selected` (the option labels picked) and `answer.other` (the
|
|
6396
|
+
free-text "Other" reply, or `null`).
|
|
6397
|
+
|
|
6398
|
+
**Use case:** You asked with `delivery: poll` from a live session — poll
|
|
6399
|
+
this until your questions read `completed`, then continue with the answers.
|
|
6291
6400
|
tags:
|
|
6292
|
-
-
|
|
6401
|
+
- Questions
|
|
6293
6402
|
parameters:
|
|
6294
6403
|
- $ref: '#/components/parameters/ProjectId'
|
|
6404
|
+
- name: handle
|
|
6405
|
+
in: path
|
|
6406
|
+
required: true
|
|
6407
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6408
|
+
schema:
|
|
6409
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6410
|
+
- name: status
|
|
6411
|
+
in: query
|
|
6412
|
+
required: false
|
|
6413
|
+
description: Filter by question status, or `all` (the default).
|
|
6414
|
+
schema:
|
|
6415
|
+
default: all
|
|
6416
|
+
anyOf:
|
|
6417
|
+
- $ref: '#/components/schemas/OpsQuestionStatus'
|
|
6418
|
+
- type: string
|
|
6419
|
+
const: all
|
|
6295
6420
|
responses:
|
|
6296
6421
|
'200':
|
|
6297
|
-
description: List
|
|
6422
|
+
description: List an item's questions
|
|
6298
6423
|
content:
|
|
6299
6424
|
application/json:
|
|
6300
6425
|
schema:
|
|
6301
|
-
$ref: '#/components/schemas/
|
|
6426
|
+
$ref: '#/components/schemas/ListOpsQuestionsResponse'
|
|
6302
6427
|
'400':
|
|
6303
6428
|
$ref: '#/components/responses/BadRequest'
|
|
6304
6429
|
'401':
|
|
6305
6430
|
$ref: '#/components/responses/Unauthorized'
|
|
6306
6431
|
'403':
|
|
6307
6432
|
$ref: '#/components/responses/Forbidden'
|
|
6433
|
+
'404':
|
|
6434
|
+
$ref: '#/components/responses/NotFound'
|
|
6435
|
+
'422':
|
|
6436
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
6308
6437
|
x-error-codes:
|
|
6309
6438
|
- BAD_REQUEST
|
|
6310
6439
|
- UNAUTHORIZED
|
|
6311
6440
|
- FORBIDDEN
|
|
6441
|
+
- NOT_FOUND
|
|
6312
6442
|
x-cli:
|
|
6313
6443
|
name: list
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6444
|
+
positional:
|
|
6445
|
+
- handle
|
|
6446
|
+
post:
|
|
6447
|
+
operationId: askOpsQuestions
|
|
6448
|
+
summary: Ask the team questions about an item
|
|
6318
6449
|
description: |-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6450
|
+
Ask 1–4 structured questions about a queue item — the way to get a
|
|
6451
|
+
decision from a person when the implementation needs one. Each question
|
|
6452
|
+
is the `AskUserQuestion` shape: a short `header` chip, the full
|
|
6453
|
+
`question`, 2–4 `options` (`label` + `description`), and `multiSelect`
|
|
6454
|
+
(checkboxes instead of radios). The person can always answer "Other" in
|
|
6455
|
+
free text, so never add an "Other" option yourself. The questions render
|
|
6456
|
+
at the very top of the item's detail panel and mark the row in the queue.
|
|
6457
|
+
|
|
6458
|
+
**Delivery.** `resume` re-fires your trigger-connector run on the item
|
|
6459
|
+
once every question it asked is answered, continuing the same run record
|
|
6460
|
+
with the answers in the prompt — stop after asking. `poll` fires nothing;
|
|
6461
|
+
poll `GET .../questions` instead. Omitted, it is `resume` when `runId`
|
|
6462
|
+
names a run launched through a trigger connector, else `poll`.
|
|
6463
|
+
|
|
6464
|
+
**Use case:** Blocked on a product decision (which behaviour to keep,
|
|
6465
|
+
which of two fixes to ship) — ask instead of guessing, then wait for the
|
|
6466
|
+
answer.
|
|
6325
6467
|
tags:
|
|
6326
|
-
-
|
|
6468
|
+
- Questions
|
|
6327
6469
|
parameters:
|
|
6328
6470
|
- $ref: '#/components/parameters/ProjectId'
|
|
6329
6471
|
- name: handle
|
|
@@ -6332,13 +6474,33 @@ paths:
|
|
|
6332
6474
|
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6333
6475
|
schema:
|
|
6334
6476
|
$ref: '#/components/schemas/ResourceId'
|
|
6477
|
+
requestBody:
|
|
6478
|
+
required: true
|
|
6479
|
+
content:
|
|
6480
|
+
application/json:
|
|
6481
|
+
schema:
|
|
6482
|
+
$ref: '#/components/schemas/AskOpsQuestionsRequest'
|
|
6483
|
+
examples:
|
|
6484
|
+
single:
|
|
6485
|
+
summary: Ask one radio question
|
|
6486
|
+
value:
|
|
6487
|
+
runId: 0d3f4c8e-7a51-4c2e-9b1f-1e2d3c4b5a69
|
|
6488
|
+
questions:
|
|
6489
|
+
- header: Legacy param
|
|
6490
|
+
question: Should the fix keep honouring the legacy `?v=1` query param?
|
|
6491
|
+
multiSelect: false
|
|
6492
|
+
options:
|
|
6493
|
+
- label: Keep it
|
|
6494
|
+
description: Old links keep working; the redirect stays
|
|
6495
|
+
- label: Drop it
|
|
6496
|
+
description: Simpler code; old links land on the default view
|
|
6335
6497
|
responses:
|
|
6336
6498
|
'200':
|
|
6337
|
-
description:
|
|
6499
|
+
description: The created questions, in the order asked
|
|
6338
6500
|
content:
|
|
6339
6501
|
application/json:
|
|
6340
6502
|
schema:
|
|
6341
|
-
$ref: '#/components/schemas/
|
|
6503
|
+
$ref: '#/components/schemas/AskOpsQuestionsResponse'
|
|
6342
6504
|
'400':
|
|
6343
6505
|
$ref: '#/components/responses/BadRequest'
|
|
6344
6506
|
'401':
|
|
@@ -6347,28 +6509,33 @@ paths:
|
|
|
6347
6509
|
$ref: '#/components/responses/Forbidden'
|
|
6348
6510
|
'404':
|
|
6349
6511
|
$ref: '#/components/responses/NotFound'
|
|
6512
|
+
'422':
|
|
6513
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
6350
6514
|
x-error-codes:
|
|
6351
6515
|
- BAD_REQUEST
|
|
6352
6516
|
- UNAUTHORIZED
|
|
6353
6517
|
- FORBIDDEN
|
|
6354
6518
|
- NOT_FOUND
|
|
6519
|
+
- VALIDATION
|
|
6355
6520
|
x-cli:
|
|
6356
|
-
name:
|
|
6521
|
+
name: ask
|
|
6357
6522
|
positional:
|
|
6358
6523
|
- handle
|
|
6524
|
+
/api/admin/ops/{handle}/questions/{questionId}/answer:
|
|
6359
6525
|
post:
|
|
6360
|
-
operationId:
|
|
6361
|
-
summary:
|
|
6526
|
+
operationId: answerOpsQuestion
|
|
6527
|
+
summary: Answer a question
|
|
6362
6528
|
description: |-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6529
|
+
Answer one open question on a queue item — pick option labels in
|
|
6530
|
+
`selected` (exactly one unless the question is `multiSelect`) and/or
|
|
6531
|
+
write a free-text `other`. The question moves to `completed`. When it was
|
|
6532
|
+
the last open question of a `resume` run, that agent is re-fired on the
|
|
6533
|
+
item with every answer. A person's action: never allow-listed for
|
|
6534
|
+
restricted ops keys.
|
|
6535
|
+
|
|
6536
|
+
**Use case:** Unblock an agent from the CLI instead of the dashboard.
|
|
6370
6537
|
tags:
|
|
6371
|
-
-
|
|
6538
|
+
- Questions
|
|
6372
6539
|
parameters:
|
|
6373
6540
|
- $ref: '#/components/parameters/ProjectId'
|
|
6374
6541
|
- name: handle
|
|
@@ -6377,31 +6544,35 @@ paths:
|
|
|
6377
6544
|
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6378
6545
|
schema:
|
|
6379
6546
|
$ref: '#/components/schemas/ResourceId'
|
|
6547
|
+
- name: questionId
|
|
6548
|
+
in: path
|
|
6549
|
+
required: true
|
|
6550
|
+
description: The question id (from `ask` or `list`).
|
|
6551
|
+
schema:
|
|
6552
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6380
6553
|
requestBody:
|
|
6381
6554
|
required: true
|
|
6382
6555
|
content:
|
|
6383
6556
|
application/json:
|
|
6384
6557
|
schema:
|
|
6385
|
-
$ref: '#/components/schemas/
|
|
6558
|
+
$ref: '#/components/schemas/AnswerOpsQuestionRequest'
|
|
6386
6559
|
examples:
|
|
6387
|
-
|
|
6388
|
-
summary:
|
|
6560
|
+
option:
|
|
6561
|
+
summary: Pick an option
|
|
6389
6562
|
value:
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6563
|
+
selected:
|
|
6564
|
+
- Keep it
|
|
6565
|
+
other:
|
|
6566
|
+
summary: Answer in free text
|
|
6393
6567
|
value:
|
|
6394
|
-
|
|
6395
|
-
parentId: cm_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
6568
|
+
other: Keep it for a release, then drop it
|
|
6396
6569
|
responses:
|
|
6397
|
-
'
|
|
6398
|
-
description:
|
|
6570
|
+
'200':
|
|
6571
|
+
description: The answered question
|
|
6399
6572
|
content:
|
|
6400
6573
|
application/json:
|
|
6401
6574
|
schema:
|
|
6402
|
-
$ref: '#/components/schemas/
|
|
6403
|
-
example:
|
|
6404
|
-
id: cm_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
6575
|
+
$ref: '#/components/schemas/OpsQuestion'
|
|
6405
6576
|
'400':
|
|
6406
6577
|
$ref: '#/components/responses/BadRequest'
|
|
6407
6578
|
'401':
|
|
@@ -6410,6 +6581,8 @@ paths:
|
|
|
6410
6581
|
$ref: '#/components/responses/Forbidden'
|
|
6411
6582
|
'404':
|
|
6412
6583
|
$ref: '#/components/responses/NotFound'
|
|
6584
|
+
'409':
|
|
6585
|
+
$ref: '#/components/responses/Conflict'
|
|
6413
6586
|
'422':
|
|
6414
6587
|
$ref: '#/components/responses/UnprocessableEntity'
|
|
6415
6588
|
x-error-codes:
|
|
@@ -6417,48 +6590,48 @@ paths:
|
|
|
6417
6590
|
- UNAUTHORIZED
|
|
6418
6591
|
- FORBIDDEN
|
|
6419
6592
|
- NOT_FOUND
|
|
6593
|
+
- INVALID_TRANSITION
|
|
6420
6594
|
- VALIDATION
|
|
6421
6595
|
x-cli:
|
|
6422
|
-
name:
|
|
6596
|
+
name: answer
|
|
6423
6597
|
positional:
|
|
6424
6598
|
- handle
|
|
6425
|
-
|
|
6599
|
+
- questionId
|
|
6600
|
+
/api/admin/ops/{handle}/questions/{questionId}/cancel:
|
|
6426
6601
|
post:
|
|
6427
|
-
operationId:
|
|
6428
|
-
summary:
|
|
6602
|
+
operationId: cancelOpsQuestion
|
|
6603
|
+
summary: Withdraw a question
|
|
6429
6604
|
description: |-
|
|
6430
|
-
|
|
6605
|
+
Withdraw one open question you asked — it no longer needs an answer
|
|
6606
|
+
(you found it out yourself, or the item moved on). The question moves to
|
|
6607
|
+
`cancelled` and leaves the detail panel. Withdrawing the last open
|
|
6608
|
+
question of a run delivers nothing.
|
|
6431
6609
|
|
|
6432
|
-
**Use case:**
|
|
6610
|
+
**Use case:** You asked, then answered it yourself from the code — take
|
|
6611
|
+
it off the person's plate.
|
|
6433
6612
|
tags:
|
|
6434
|
-
-
|
|
6613
|
+
- Questions
|
|
6435
6614
|
parameters:
|
|
6436
6615
|
- $ref: '#/components/parameters/ProjectId'
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
- 'Re-run the shipeasy-ops-work loop — #42 will be acknowledged.'
|
|
6450
|
-
dedupeKey: feedback:42
|
|
6451
|
-
href: /dashboard/prj_0abc/bugs/42
|
|
6616
|
+
- name: handle
|
|
6617
|
+
in: path
|
|
6618
|
+
required: true
|
|
6619
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6620
|
+
schema:
|
|
6621
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6622
|
+
- name: questionId
|
|
6623
|
+
in: path
|
|
6624
|
+
required: true
|
|
6625
|
+
description: The question id (from `ask` or `list`).
|
|
6626
|
+
schema:
|
|
6627
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6452
6628
|
responses:
|
|
6453
|
-
'
|
|
6454
|
-
description:
|
|
6629
|
+
'200':
|
|
6630
|
+
description: The withdrawn question
|
|
6455
6631
|
content:
|
|
6456
6632
|
application/json:
|
|
6457
6633
|
schema:
|
|
6458
|
-
$ref: '#/components/schemas/
|
|
6459
|
-
example:
|
|
6460
|
-
dedupeKey: error:checkout:5xx
|
|
6461
|
-
dispatched: true
|
|
6634
|
+
$ref: '#/components/schemas/OpsQuestion'
|
|
6462
6635
|
'400':
|
|
6463
6636
|
$ref: '#/components/responses/BadRequest'
|
|
6464
6637
|
'401':
|
|
@@ -6469,41 +6642,53 @@ paths:
|
|
|
6469
6642
|
$ref: '#/components/responses/NotFound'
|
|
6470
6643
|
'409':
|
|
6471
6644
|
$ref: '#/components/responses/Conflict'
|
|
6472
|
-
'422':
|
|
6473
|
-
$ref: '#/components/responses/UnprocessableEntity'
|
|
6474
6645
|
x-error-codes:
|
|
6475
6646
|
- BAD_REQUEST
|
|
6476
6647
|
- UNAUTHORIZED
|
|
6477
6648
|
- FORBIDDEN
|
|
6478
|
-
-
|
|
6649
|
+
- NOT_FOUND
|
|
6650
|
+
- INVALID_TRANSITION
|
|
6479
6651
|
x-cli:
|
|
6480
|
-
name:
|
|
6481
|
-
|
|
6652
|
+
name: cancel
|
|
6653
|
+
positional:
|
|
6654
|
+
- handle
|
|
6655
|
+
- questionId
|
|
6656
|
+
/api/admin/ops/{handle}/qa-notes:
|
|
6482
6657
|
get:
|
|
6483
|
-
operationId:
|
|
6484
|
-
summary: List
|
|
6658
|
+
operationId: listOpsQaNotes
|
|
6659
|
+
summary: List an item's QA notes
|
|
6485
6660
|
description: |-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6661
|
+
The typed QA notes on a queue item, newest first (max 200) — narrowing,
|
|
6662
|
+
clarification, verification and correction notes, each with its author and
|
|
6663
|
+
time. They are separate from the comment thread: read these to learn the
|
|
6664
|
+
CURRENT QA state of a ticket (what remains failing, what "fixed" now means,
|
|
6665
|
+
the last verification verdict) without parsing prose comments.
|
|
6666
|
+
|
|
6667
|
+
**Use case:** A coding agent picks an item up and checks the latest
|
|
6668
|
+
`verification` verdict and any `narrowing` note before touching the code.
|
|
6489
6669
|
tags:
|
|
6490
|
-
-
|
|
6670
|
+
- QA notes
|
|
6491
6671
|
parameters:
|
|
6492
6672
|
- $ref: '#/components/parameters/ProjectId'
|
|
6673
|
+
- name: handle
|
|
6674
|
+
in: path
|
|
6675
|
+
required: true
|
|
6676
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6677
|
+
schema:
|
|
6678
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6679
|
+
- name: kind
|
|
6680
|
+
in: query
|
|
6681
|
+
required: false
|
|
6682
|
+
description: Only notes of this kind.
|
|
6683
|
+
schema:
|
|
6684
|
+
$ref: '#/components/schemas/OpsQaNoteKind'
|
|
6493
6685
|
responses:
|
|
6494
6686
|
'200':
|
|
6495
|
-
description: List
|
|
6687
|
+
description: List an item's QA notes
|
|
6496
6688
|
content:
|
|
6497
6689
|
application/json:
|
|
6498
6690
|
schema:
|
|
6499
|
-
$ref: '#/components/schemas/
|
|
6500
|
-
example:
|
|
6501
|
-
connected: true
|
|
6502
|
-
channels:
|
|
6503
|
-
- id: C0123
|
|
6504
|
-
name: alerts
|
|
6505
|
-
- id: C0456
|
|
6506
|
-
name: general
|
|
6691
|
+
$ref: '#/components/schemas/ListOpsQaNotesResponse'
|
|
6507
6692
|
'400':
|
|
6508
6693
|
$ref: '#/components/responses/BadRequest'
|
|
6509
6694
|
'401':
|
|
@@ -6512,49 +6697,68 @@ paths:
|
|
|
6512
6697
|
$ref: '#/components/responses/Forbidden'
|
|
6513
6698
|
'404':
|
|
6514
6699
|
$ref: '#/components/responses/NotFound'
|
|
6515
|
-
'409':
|
|
6516
|
-
$ref: '#/components/responses/Conflict'
|
|
6517
6700
|
'422':
|
|
6518
6701
|
$ref: '#/components/responses/UnprocessableEntity'
|
|
6519
6702
|
x-error-codes:
|
|
6520
6703
|
- BAD_REQUEST
|
|
6521
6704
|
- UNAUTHORIZED
|
|
6522
6705
|
- FORBIDDEN
|
|
6706
|
+
- NOT_FOUND
|
|
6523
6707
|
x-cli:
|
|
6524
|
-
name:
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6708
|
+
name: list
|
|
6709
|
+
positional:
|
|
6710
|
+
- handle
|
|
6711
|
+
post:
|
|
6712
|
+
operationId: createOpsQaNote
|
|
6713
|
+
summary: Add a QA note to an item
|
|
6529
6714
|
description: |-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6715
|
+
Append one typed QA note to a queue item. `kind` is `narrowing` (what now
|
|
6716
|
+
passes vs what still fails), `clarification` (what "fixed" now means),
|
|
6717
|
+
`verification` (requires a `verdict` of `pass` or `fail`, and `body` says
|
|
6718
|
+
what was checked) or `correction` (withdraws an earlier framing). Notes
|
|
6719
|
+
are append-only and appear in the item's QA notes section, not in the
|
|
6720
|
+
comment thread. The author is the caller's identity; pass `agent` to
|
|
6721
|
+
record the note as written by that agent type's QA automation. A `fail` verdict never changes the item's
|
|
6722
|
+
status by itself: the dashboard offers an explicit "Reopen item" action,
|
|
6723
|
+
and `ops update --status open` does the same from the CLI.
|
|
6724
|
+
|
|
6725
|
+
**Use case:** QA automation records "verified on production: FAIL, the
|
|
6726
|
+
second facet still errors" as data an agent can read back.
|
|
6533
6727
|
tags:
|
|
6534
|
-
-
|
|
6728
|
+
- QA notes
|
|
6535
6729
|
parameters:
|
|
6536
6730
|
- $ref: '#/components/parameters/ProjectId'
|
|
6537
|
-
-
|
|
6731
|
+
- name: handle
|
|
6732
|
+
in: path
|
|
6733
|
+
required: true
|
|
6734
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6735
|
+
schema:
|
|
6736
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6737
|
+
requestBody:
|
|
6738
|
+
required: true
|
|
6739
|
+
content:
|
|
6740
|
+
application/json:
|
|
6741
|
+
schema:
|
|
6742
|
+
$ref: '#/components/schemas/CreateOpsQaNoteRequest'
|
|
6743
|
+
examples:
|
|
6744
|
+
verification:
|
|
6745
|
+
summary: A failing verification
|
|
6746
|
+
value:
|
|
6747
|
+
kind: verification
|
|
6748
|
+
verdict: fail
|
|
6749
|
+
body: Retested on production after the deploy — the export still drops the second sheet
|
|
6750
|
+
narrowing:
|
|
6751
|
+
summary: Narrow a bug to the facet that still fails
|
|
6752
|
+
value:
|
|
6753
|
+
kind: narrowing
|
|
6754
|
+
body: The list view is fixed; only the detail panel still shows the stale count
|
|
6538
6755
|
responses:
|
|
6539
6756
|
'200':
|
|
6540
|
-
description:
|
|
6757
|
+
description: The created note
|
|
6541
6758
|
content:
|
|
6542
6759
|
application/json:
|
|
6543
6760
|
schema:
|
|
6544
|
-
$ref: '#/components/schemas/
|
|
6545
|
-
example:
|
|
6546
|
-
- id: ar_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
6547
|
-
name: Checkout error rate
|
|
6548
|
-
metricId: met_01j6abc2d3e4f5g6h7i8j9k0l1
|
|
6549
|
-
metricName: checkout_errors
|
|
6550
|
-
comparator: gt
|
|
6551
|
-
threshold: 50
|
|
6552
|
-
windowHours: 24
|
|
6553
|
-
severity: warn
|
|
6554
|
-
enabled: true
|
|
6555
|
-
notify: null
|
|
6556
|
-
createdAt: '2026-04-12T10:14:08.000Z'
|
|
6557
|
-
updatedAt: '2026-04-12T10:14:08.000Z'
|
|
6761
|
+
$ref: '#/components/schemas/OpsQaNote'
|
|
6558
6762
|
'400':
|
|
6559
6763
|
$ref: '#/components/responses/BadRequest'
|
|
6560
6764
|
'401':
|
|
@@ -6563,17 +6767,315 @@ paths:
|
|
|
6563
6767
|
$ref: '#/components/responses/Forbidden'
|
|
6564
6768
|
'404':
|
|
6565
6769
|
$ref: '#/components/responses/NotFound'
|
|
6566
|
-
'409':
|
|
6567
|
-
$ref: '#/components/responses/Conflict'
|
|
6568
6770
|
'422':
|
|
6569
6771
|
$ref: '#/components/responses/UnprocessableEntity'
|
|
6570
6772
|
x-error-codes:
|
|
6571
6773
|
- BAD_REQUEST
|
|
6572
6774
|
- UNAUTHORIZED
|
|
6573
6775
|
- FORBIDDEN
|
|
6776
|
+
- NOT_FOUND
|
|
6777
|
+
- VALIDATION
|
|
6574
6778
|
x-cli:
|
|
6575
|
-
name:
|
|
6576
|
-
|
|
6779
|
+
name: create
|
|
6780
|
+
positional:
|
|
6781
|
+
- handle
|
|
6782
|
+
/api/admin/agent-profiles:
|
|
6783
|
+
get:
|
|
6784
|
+
operationId: listOpsAgents
|
|
6785
|
+
summary: List connected AI agents
|
|
6786
|
+
description: |-
|
|
6787
|
+
The project's connected AI agents — one per authenticated trigger
|
|
6788
|
+
connector (Claude / Cursor / Copilot / Jules). These are the agent types
|
|
6789
|
+
`ops ack` accepts and the agents a queue item can be assigned to.
|
|
6790
|
+
|
|
6791
|
+
**Use case:** Discover which `agent` values an AI ack can use, e.g. after
|
|
6792
|
+
an `AGENT_NOT_CONNECTED` error.
|
|
6793
|
+
tags:
|
|
6794
|
+
- Agents
|
|
6795
|
+
parameters:
|
|
6796
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
6797
|
+
responses:
|
|
6798
|
+
'200':
|
|
6799
|
+
description: List connected AI agents
|
|
6800
|
+
content:
|
|
6801
|
+
application/json:
|
|
6802
|
+
schema:
|
|
6803
|
+
$ref: '#/components/schemas/ListOpsAgentsResponse'
|
|
6804
|
+
'400':
|
|
6805
|
+
$ref: '#/components/responses/BadRequest'
|
|
6806
|
+
'401':
|
|
6807
|
+
$ref: '#/components/responses/Unauthorized'
|
|
6808
|
+
'403':
|
|
6809
|
+
$ref: '#/components/responses/Forbidden'
|
|
6810
|
+
x-error-codes:
|
|
6811
|
+
- BAD_REQUEST
|
|
6812
|
+
- UNAUTHORIZED
|
|
6813
|
+
- FORBIDDEN
|
|
6814
|
+
x-cli:
|
|
6815
|
+
name: list
|
|
6816
|
+
/api/admin/ops/{handle}/comments:
|
|
6817
|
+
get:
|
|
6818
|
+
operationId: listOpsComments
|
|
6819
|
+
summary: List an item's comments
|
|
6820
|
+
description: |-
|
|
6821
|
+
List the comment thread on a queue item, oldest first. Each comment
|
|
6822
|
+
carries its author (a teammate email, or `system` for a comment authored by
|
|
6823
|
+
Jarvis — the AI agent), its markdown body, and `parentId` for the single
|
|
6824
|
+
level of threaded replies. Removed comments are omitted.
|
|
6825
|
+
|
|
6826
|
+
**Use case:** Read the discussion on an item before replying or acting on it.
|
|
6827
|
+
tags:
|
|
6828
|
+
- Comments
|
|
6829
|
+
parameters:
|
|
6830
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
6831
|
+
- name: handle
|
|
6832
|
+
in: path
|
|
6833
|
+
required: true
|
|
6834
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6835
|
+
schema:
|
|
6836
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6837
|
+
responses:
|
|
6838
|
+
'200':
|
|
6839
|
+
description: List an item's comments
|
|
6840
|
+
content:
|
|
6841
|
+
application/json:
|
|
6842
|
+
schema:
|
|
6843
|
+
$ref: '#/components/schemas/ListOpsCommentsResponse'
|
|
6844
|
+
'400':
|
|
6845
|
+
$ref: '#/components/responses/BadRequest'
|
|
6846
|
+
'401':
|
|
6847
|
+
$ref: '#/components/responses/Unauthorized'
|
|
6848
|
+
'403':
|
|
6849
|
+
$ref: '#/components/responses/Forbidden'
|
|
6850
|
+
'404':
|
|
6851
|
+
$ref: '#/components/responses/NotFound'
|
|
6852
|
+
x-error-codes:
|
|
6853
|
+
- BAD_REQUEST
|
|
6854
|
+
- UNAUTHORIZED
|
|
6855
|
+
- FORBIDDEN
|
|
6856
|
+
- NOT_FOUND
|
|
6857
|
+
x-cli:
|
|
6858
|
+
name: list
|
|
6859
|
+
positional:
|
|
6860
|
+
- handle
|
|
6861
|
+
post:
|
|
6862
|
+
operationId: createOpsComment
|
|
6863
|
+
summary: Comment on an item
|
|
6864
|
+
description: |-
|
|
6865
|
+
Append a comment to a queue item's thread. The body is markdown (mentions
|
|
6866
|
+
like `@teammate` notify that person; `@shipeasy` asks Jarvis, the AI agent,
|
|
6867
|
+
to reply). Pass `parentId` to reply under an existing top-level comment
|
|
6868
|
+
(one level of threading — a reply to a reply attaches to the same parent).
|
|
6869
|
+
|
|
6870
|
+
Create-only and append-only, so it is safe for restricted ops keys — the
|
|
6871
|
+
same channel the ops loop and Jarvis use to leave a note on an item.
|
|
6872
|
+
tags:
|
|
6873
|
+
- Comments
|
|
6874
|
+
parameters:
|
|
6875
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
6876
|
+
- name: handle
|
|
6877
|
+
in: path
|
|
6878
|
+
required: true
|
|
6879
|
+
description: Per-project item number (e.g. `7`) or the full ops item id.
|
|
6880
|
+
schema:
|
|
6881
|
+
$ref: '#/components/schemas/ResourceId'
|
|
6882
|
+
requestBody:
|
|
6883
|
+
required: true
|
|
6884
|
+
content:
|
|
6885
|
+
application/json:
|
|
6886
|
+
schema:
|
|
6887
|
+
$ref: '#/components/schemas/CreateOpsCommentRequest'
|
|
6888
|
+
examples:
|
|
6889
|
+
comment:
|
|
6890
|
+
summary: Leave a comment
|
|
6891
|
+
value:
|
|
6892
|
+
body: Repro'd on iOS Safari 17 — the button overflows its container. cc @alice
|
|
6893
|
+
reply:
|
|
6894
|
+
summary: Reply under an existing comment
|
|
6895
|
+
value:
|
|
6896
|
+
body: Agreed, let's ship the fix behind @shipeasy's suggested flag.
|
|
6897
|
+
parentId: cm_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
6898
|
+
responses:
|
|
6899
|
+
'201':
|
|
6900
|
+
description: Comment on an item
|
|
6901
|
+
content:
|
|
6902
|
+
application/json:
|
|
6903
|
+
schema:
|
|
6904
|
+
$ref: '#/components/schemas/CreateOpsCommentResponse'
|
|
6905
|
+
example:
|
|
6906
|
+
id: cm_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
6907
|
+
'400':
|
|
6908
|
+
$ref: '#/components/responses/BadRequest'
|
|
6909
|
+
'401':
|
|
6910
|
+
$ref: '#/components/responses/Unauthorized'
|
|
6911
|
+
'403':
|
|
6912
|
+
$ref: '#/components/responses/Forbidden'
|
|
6913
|
+
'404':
|
|
6914
|
+
$ref: '#/components/responses/NotFound'
|
|
6915
|
+
'422':
|
|
6916
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
6917
|
+
x-error-codes:
|
|
6918
|
+
- BAD_REQUEST
|
|
6919
|
+
- UNAUTHORIZED
|
|
6920
|
+
- FORBIDDEN
|
|
6921
|
+
- NOT_FOUND
|
|
6922
|
+
- VALIDATION
|
|
6923
|
+
x-cli:
|
|
6924
|
+
name: create
|
|
6925
|
+
positional:
|
|
6926
|
+
- handle
|
|
6927
|
+
/api/admin/notifications:
|
|
6928
|
+
post:
|
|
6929
|
+
operationId: notifyOps
|
|
6930
|
+
summary: Raise an attention notification
|
|
6931
|
+
description: |-
|
|
6932
|
+
Raise a 'needs your attention' bell notification. Create-only and idempotent on `dedupeKey` — re-raising with the same key updates the one card instead of stacking duplicates. It never reads, marks read, or deletes the feed, so it is safe for restricted ops keys.
|
|
6933
|
+
|
|
6934
|
+
**Use case:** Escalate work that can't land in code (a product decision, a credential only a human has, a resource only a human may edit), deduped so repeats don't spam the bell.
|
|
6935
|
+
tags:
|
|
6936
|
+
- Ops
|
|
6937
|
+
parameters:
|
|
6938
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
6939
|
+
requestBody:
|
|
6940
|
+
required: true
|
|
6941
|
+
content:
|
|
6942
|
+
application/json:
|
|
6943
|
+
schema:
|
|
6944
|
+
$ref: '#/components/schemas/NotifyOpsRequest'
|
|
6945
|
+
example:
|
|
6946
|
+
title: 'Alert rule @alert:checkout-error-rate needs a human edit for #42'
|
|
6947
|
+
summary: '#42 is a false positive — the rule fires on the expected nightly batch spike, and rule definitions can only be edited by a human.'
|
|
6948
|
+
steps:
|
|
6949
|
+
- Open @alert:checkout-error-rate in the dashboard alerts page.
|
|
6950
|
+
- Raise the threshold from `2%` to `5%` and widen the window to `1h`.
|
|
6951
|
+
- 'Re-run the shipeasy-ops-work loop — #42 will be acknowledged.'
|
|
6952
|
+
dedupeKey: feedback:42
|
|
6953
|
+
href: /dashboard/prj_0abc/bugs/42
|
|
6954
|
+
responses:
|
|
6955
|
+
'201':
|
|
6956
|
+
description: Raise an attention notification
|
|
6957
|
+
content:
|
|
6958
|
+
application/json:
|
|
6959
|
+
schema:
|
|
6960
|
+
$ref: '#/components/schemas/NotifyOpsResponse'
|
|
6961
|
+
example:
|
|
6962
|
+
dedupeKey: error:checkout:5xx
|
|
6963
|
+
dispatched: true
|
|
6964
|
+
'400':
|
|
6965
|
+
$ref: '#/components/responses/BadRequest'
|
|
6966
|
+
'401':
|
|
6967
|
+
$ref: '#/components/responses/Unauthorized'
|
|
6968
|
+
'403':
|
|
6969
|
+
$ref: '#/components/responses/Forbidden'
|
|
6970
|
+
'404':
|
|
6971
|
+
$ref: '#/components/responses/NotFound'
|
|
6972
|
+
'409':
|
|
6973
|
+
$ref: '#/components/responses/Conflict'
|
|
6974
|
+
'422':
|
|
6975
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
6976
|
+
x-error-codes:
|
|
6977
|
+
- BAD_REQUEST
|
|
6978
|
+
- UNAUTHORIZED
|
|
6979
|
+
- FORBIDDEN
|
|
6980
|
+
- VALIDATION
|
|
6981
|
+
x-cli:
|
|
6982
|
+
name: notify
|
|
6983
|
+
/api/admin/slack/channels:
|
|
6984
|
+
get:
|
|
6985
|
+
operationId: listSlackChannels
|
|
6986
|
+
summary: List Slack channels
|
|
6987
|
+
description: |-
|
|
6988
|
+
List the project's connected Slack channels — used to resolve an alert rule's notification target.
|
|
6989
|
+
|
|
6990
|
+
**Use case:** Populate a channel picker, or validate an alert rule's `--slack-channel` before saving.
|
|
6991
|
+
tags:
|
|
6992
|
+
- Alerts
|
|
6993
|
+
parameters:
|
|
6994
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
6995
|
+
responses:
|
|
6996
|
+
'200':
|
|
6997
|
+
description: List Slack channels
|
|
6998
|
+
content:
|
|
6999
|
+
application/json:
|
|
7000
|
+
schema:
|
|
7001
|
+
$ref: '#/components/schemas/ListSlackChannelsResponse'
|
|
7002
|
+
example:
|
|
7003
|
+
connected: true
|
|
7004
|
+
channels:
|
|
7005
|
+
- id: C0123
|
|
7006
|
+
name: alerts
|
|
7007
|
+
- id: C0456
|
|
7008
|
+
name: general
|
|
7009
|
+
'400':
|
|
7010
|
+
$ref: '#/components/responses/BadRequest'
|
|
7011
|
+
'401':
|
|
7012
|
+
$ref: '#/components/responses/Unauthorized'
|
|
7013
|
+
'403':
|
|
7014
|
+
$ref: '#/components/responses/Forbidden'
|
|
7015
|
+
'404':
|
|
7016
|
+
$ref: '#/components/responses/NotFound'
|
|
7017
|
+
'409':
|
|
7018
|
+
$ref: '#/components/responses/Conflict'
|
|
7019
|
+
'422':
|
|
7020
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
7021
|
+
x-error-codes:
|
|
7022
|
+
- BAD_REQUEST
|
|
7023
|
+
- UNAUTHORIZED
|
|
7024
|
+
- FORBIDDEN
|
|
7025
|
+
x-cli:
|
|
7026
|
+
name: channels
|
|
7027
|
+
/api/admin/alert-rules:
|
|
7028
|
+
get:
|
|
7029
|
+
operationId: listAlertRules
|
|
7030
|
+
summary: List alert rules
|
|
7031
|
+
description: |-
|
|
7032
|
+
Returns every alert rule in the project (not paginated). Each rule carries its bound `metricId`, the denormalised `metricName` (or `null` if the metric was removed), the comparator/threshold/window, severity, enabled flag, and delivery target.
|
|
7033
|
+
|
|
7034
|
+
**Use case:** Audit which metrics have alerting configured — for example to confirm an on-call threshold is set before a launch.
|
|
7035
|
+
tags:
|
|
7036
|
+
- Alerts
|
|
7037
|
+
parameters:
|
|
7038
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
7039
|
+
- $ref: '#/components/parameters/Q'
|
|
7040
|
+
responses:
|
|
7041
|
+
'200':
|
|
7042
|
+
description: List alert rules
|
|
7043
|
+
content:
|
|
7044
|
+
application/json:
|
|
7045
|
+
schema:
|
|
7046
|
+
$ref: '#/components/schemas/ListAlertRulesResponse'
|
|
7047
|
+
example:
|
|
7048
|
+
- id: ar_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
7049
|
+
name: Checkout error rate
|
|
7050
|
+
metricId: met_01j6abc2d3e4f5g6h7i8j9k0l1
|
|
7051
|
+
metricName: checkout_errors
|
|
7052
|
+
comparator: gt
|
|
7053
|
+
threshold: 50
|
|
7054
|
+
windowHours: 24
|
|
7055
|
+
severity: warn
|
|
7056
|
+
enabled: true
|
|
7057
|
+
notify: null
|
|
7058
|
+
createdAt: '2026-04-12T10:14:08.000Z'
|
|
7059
|
+
updatedAt: '2026-04-12T10:14:08.000Z'
|
|
7060
|
+
'400':
|
|
7061
|
+
$ref: '#/components/responses/BadRequest'
|
|
7062
|
+
'401':
|
|
7063
|
+
$ref: '#/components/responses/Unauthorized'
|
|
7064
|
+
'403':
|
|
7065
|
+
$ref: '#/components/responses/Forbidden'
|
|
7066
|
+
'404':
|
|
7067
|
+
$ref: '#/components/responses/NotFound'
|
|
7068
|
+
'409':
|
|
7069
|
+
$ref: '#/components/responses/Conflict'
|
|
7070
|
+
'422':
|
|
7071
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
7072
|
+
x-error-codes:
|
|
7073
|
+
- BAD_REQUEST
|
|
7074
|
+
- UNAUTHORIZED
|
|
7075
|
+
- FORBIDDEN
|
|
7076
|
+
x-cli:
|
|
7077
|
+
name: list
|
|
7078
|
+
post:
|
|
6577
7079
|
operationId: createAlertRule
|
|
6578
7080
|
summary: Create an alert rule
|
|
6579
7081
|
description: |-
|
|
@@ -6790,7 +7292,9 @@ paths:
|
|
|
6790
7292
|
description: |-
|
|
6791
7293
|
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`.
|
|
6792
7294
|
|
|
6793
|
-
|
|
7295
|
+
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.
|
|
7296
|
+
|
|
7297
|
+
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`.
|
|
6794
7298
|
|
|
6795
7299
|
**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.
|
|
6796
7300
|
tags:
|
|
@@ -6874,7 +7378,7 @@ paths:
|
|
|
6874
7378
|
description: |-
|
|
6875
7379
|
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.
|
|
6876
7380
|
|
|
6877
|
-
- **`status`** — flip between `active` / `resolved` / `dismissed`. `resolved` and `dismissed` stamp `resolvedAt` / `dismissedAt`; `active` re-opens and clears both.
|
|
7381
|
+
- **`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.
|
|
6878
7382
|
- **`assigneeId`** — the PERSON owner (a `users.id`), or `null` to unassign.
|
|
6879
7383
|
- **`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.
|
|
6880
7384
|
|
|
@@ -6891,7 +7395,7 @@ paths:
|
|
|
6891
7395
|
- name: id
|
|
6892
7396
|
in: path
|
|
6893
7397
|
required: true
|
|
6894
|
-
description: Stable opaque
|
|
7398
|
+
description: Stable opaque instance id — the same id as the `alert` ops item this instance is.
|
|
6895
7399
|
schema:
|
|
6896
7400
|
$ref: '#/components/schemas/ResourceId'
|
|
6897
7401
|
requestBody:
|
|
@@ -7365,11 +7869,12 @@ paths:
|
|
|
7365
7869
|
- name: limit
|
|
7366
7870
|
in: query
|
|
7367
7871
|
required: false
|
|
7368
|
-
description: Max keys to return (1–500).
|
|
7872
|
+
description: Max keys to return (1–500). Defaults to 200.
|
|
7369
7873
|
schema:
|
|
7370
7874
|
type: integer
|
|
7371
7875
|
minimum: 1
|
|
7372
7876
|
maximum: 500
|
|
7877
|
+
default: 200
|
|
7373
7878
|
- name: offset
|
|
7374
7879
|
in: query
|
|
7375
7880
|
required: false
|
|
@@ -9406,6 +9911,7 @@ paths:
|
|
|
9406
9911
|
expires_at: null
|
|
9407
9912
|
created_by_email: ana@example.com
|
|
9408
9913
|
name: production back-end
|
|
9914
|
+
description: Held by the checkout service; rotate with the quarterly credential sweep
|
|
9409
9915
|
scopes:
|
|
9410
9916
|
- gates:evaluate
|
|
9411
9917
|
- events:write
|
|
@@ -9474,18 +9980,313 @@ paths:
|
|
|
9474
9980
|
value:
|
|
9475
9981
|
type: ops
|
|
9476
9982
|
responses:
|
|
9477
|
-
'201':
|
|
9478
|
-
description: Create an API key
|
|
9983
|
+
'201':
|
|
9984
|
+
description: Create an API key
|
|
9985
|
+
content:
|
|
9986
|
+
application/json:
|
|
9987
|
+
schema:
|
|
9988
|
+
$ref: '#/components/schemas/CreateKeyResponse'
|
|
9989
|
+
example:
|
|
9990
|
+
id: 3f2a9b1c-7d4e-4a8f-9c2b-1e5d6f7a8b90
|
|
9991
|
+
type: server
|
|
9992
|
+
env: prod
|
|
9993
|
+
key: sdk_server_9c1f4f1f2c0c4a5fa1c2b6d3e7c8e3a1
|
|
9994
|
+
expires_at: null
|
|
9995
|
+
'400':
|
|
9996
|
+
$ref: '#/components/responses/BadRequest'
|
|
9997
|
+
'401':
|
|
9998
|
+
$ref: '#/components/responses/Unauthorized'
|
|
9999
|
+
'403':
|
|
10000
|
+
$ref: '#/components/responses/Forbidden'
|
|
10001
|
+
'404':
|
|
10002
|
+
$ref: '#/components/responses/NotFound'
|
|
10003
|
+
'409':
|
|
10004
|
+
$ref: '#/components/responses/Conflict'
|
|
10005
|
+
'422':
|
|
10006
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
10007
|
+
x-error-codes:
|
|
10008
|
+
- UNAUTHORIZED
|
|
10009
|
+
- FORBIDDEN
|
|
10010
|
+
- VALIDATION
|
|
10011
|
+
- PLAN_LIMIT
|
|
10012
|
+
x-cli:
|
|
10013
|
+
name: create
|
|
10014
|
+
/api/admin/keys/{id}:
|
|
10015
|
+
patch:
|
|
10016
|
+
operationId: updateKey
|
|
10017
|
+
summary: Update an API key's label
|
|
10018
|
+
description: |-
|
|
10019
|
+
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.
|
|
10020
|
+
|
|
10021
|
+
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.
|
|
10022
|
+
|
|
10023
|
+
**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.
|
|
10024
|
+
tags:
|
|
10025
|
+
- API Keys
|
|
10026
|
+
parameters:
|
|
10027
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
10028
|
+
- name: id
|
|
10029
|
+
in: path
|
|
10030
|
+
required: true
|
|
10031
|
+
description: Stable opaque key id (UUID) returned by `create` / `list`.
|
|
10032
|
+
schema:
|
|
10033
|
+
$ref: '#/components/schemas/ResourceId'
|
|
10034
|
+
requestBody:
|
|
10035
|
+
required: true
|
|
10036
|
+
content:
|
|
10037
|
+
application/json:
|
|
10038
|
+
schema:
|
|
10039
|
+
$ref: '#/components/schemas/UpdateKeyRequest'
|
|
10040
|
+
examples:
|
|
10041
|
+
rename:
|
|
10042
|
+
summary: Rename and note the key
|
|
10043
|
+
value:
|
|
10044
|
+
name: checkout-service · production
|
|
10045
|
+
description: Held by the checkout service; rotation owner is the payments team
|
|
10046
|
+
clearDescription:
|
|
10047
|
+
summary: Clear the note
|
|
10048
|
+
value:
|
|
10049
|
+
description: null
|
|
10050
|
+
responses:
|
|
10051
|
+
'200':
|
|
10052
|
+
description: Update an API key's label
|
|
10053
|
+
content:
|
|
10054
|
+
application/json:
|
|
10055
|
+
schema:
|
|
10056
|
+
$ref: '#/components/schemas/KeyRecord'
|
|
10057
|
+
example:
|
|
10058
|
+
id: 3f2a9b1c-7d4e-4a8f-9c2b-1e5d6f7a8b90
|
|
10059
|
+
type: server
|
|
10060
|
+
env: prod
|
|
10061
|
+
created_at: '2026-05-09T16:01:22.000Z'
|
|
10062
|
+
revoked_at: null
|
|
10063
|
+
expires_at: null
|
|
10064
|
+
created_by_email: ana@example.com
|
|
10065
|
+
name: checkout-service · production
|
|
10066
|
+
description: Held by the checkout service; rotation owner is the payments team
|
|
10067
|
+
scopes:
|
|
10068
|
+
- gates:evaluate
|
|
10069
|
+
- events:write
|
|
10070
|
+
last4: a1b2
|
|
10071
|
+
'400':
|
|
10072
|
+
$ref: '#/components/responses/BadRequest'
|
|
10073
|
+
'401':
|
|
10074
|
+
$ref: '#/components/responses/Unauthorized'
|
|
10075
|
+
'403':
|
|
10076
|
+
$ref: '#/components/responses/Forbidden'
|
|
10077
|
+
'404':
|
|
10078
|
+
$ref: '#/components/responses/NotFound'
|
|
10079
|
+
'409':
|
|
10080
|
+
$ref: '#/components/responses/Conflict'
|
|
10081
|
+
'422':
|
|
10082
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
10083
|
+
x-error-codes:
|
|
10084
|
+
- UNAUTHORIZED
|
|
10085
|
+
- FORBIDDEN
|
|
10086
|
+
- NOT_FOUND
|
|
10087
|
+
- VALIDATION
|
|
10088
|
+
x-cli:
|
|
10089
|
+
name: update
|
|
10090
|
+
positional:
|
|
10091
|
+
- id
|
|
10092
|
+
/api/admin/keys/{id}/revoke:
|
|
10093
|
+
post:
|
|
10094
|
+
operationId: revokeKey
|
|
10095
|
+
summary: Revoke an API key
|
|
10096
|
+
description: |-
|
|
10097
|
+
Revokes a key by id — stamps its `revoked_at` and deletes the hot-path KV entry so the token stops authenticating immediately. Takes no body.
|
|
10098
|
+
|
|
10099
|
+
Idempotent: revoking an already-revoked key is a no-op and returns the same `{ id, revoked: true }`. Returns `404` if no such key exists in the project.
|
|
10100
|
+
|
|
10101
|
+
**Use case:** Rotate a leaked or stale credential — mint the replacement, then revoke the old key.
|
|
10102
|
+
tags:
|
|
10103
|
+
- API Keys
|
|
10104
|
+
parameters:
|
|
10105
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
10106
|
+
- name: id
|
|
10107
|
+
in: path
|
|
10108
|
+
required: true
|
|
10109
|
+
description: Stable opaque key id (UUID) returned by `create` / `list`.
|
|
10110
|
+
schema:
|
|
10111
|
+
$ref: '#/components/schemas/ResourceId'
|
|
10112
|
+
responses:
|
|
10113
|
+
'200':
|
|
10114
|
+
description: Revoke an API key
|
|
10115
|
+
content:
|
|
10116
|
+
application/json:
|
|
10117
|
+
schema:
|
|
10118
|
+
$ref: '#/components/schemas/RevokeKeyResponse'
|
|
10119
|
+
example:
|
|
10120
|
+
id: 3f2a9b1c-7d4e-4a8f-9c2b-1e5d6f7a8b90
|
|
10121
|
+
revoked: true
|
|
10122
|
+
'400':
|
|
10123
|
+
$ref: '#/components/responses/BadRequest'
|
|
10124
|
+
'401':
|
|
10125
|
+
$ref: '#/components/responses/Unauthorized'
|
|
10126
|
+
'403':
|
|
10127
|
+
$ref: '#/components/responses/Forbidden'
|
|
10128
|
+
'404':
|
|
10129
|
+
$ref: '#/components/responses/NotFound'
|
|
10130
|
+
'409':
|
|
10131
|
+
$ref: '#/components/responses/Conflict'
|
|
10132
|
+
'422':
|
|
10133
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
10134
|
+
x-error-codes:
|
|
10135
|
+
- UNAUTHORIZED
|
|
10136
|
+
- FORBIDDEN
|
|
10137
|
+
- NOT_FOUND
|
|
10138
|
+
x-cli:
|
|
10139
|
+
name: revoke
|
|
10140
|
+
positional:
|
|
10141
|
+
- id
|
|
10142
|
+
/api/admin/search:
|
|
10143
|
+
get:
|
|
10144
|
+
operationId: searchResources
|
|
10145
|
+
summary: Search project resources
|
|
10146
|
+
description: |-
|
|
10147
|
+
Universal substring search across the project's primary resources — feature gates, experiments, dynamic configs, killswitches, metrics, and team members. Matches the trimmed `q` against each resource's immutable `name` and its human title/display name (members match on display name or email), newest-first, capped per resource family so one noisy type can't crowd out the rest.
|
|
10148
|
+
|
|
10149
|
+
Returns a flat, ranked-by-type list of hits (members first); an empty or whitespace-only `q` returns no hits. Each hit carries a project-relative `href` that deep-links to the row.
|
|
10150
|
+
|
|
10151
|
+
**Use case:** Back a command-palette / quick-switcher in the dashboard, or look up the id of a resource by a fragment of its name before driving another API call.
|
|
10152
|
+
tags:
|
|
10153
|
+
- Projects
|
|
10154
|
+
parameters:
|
|
10155
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
10156
|
+
- name: q
|
|
10157
|
+
in: query
|
|
10158
|
+
required: false
|
|
10159
|
+
description: Search query. Matched as a case-insensitive substring against each resource's `name` and title/display name. Trimmed; empty returns no hits.
|
|
10160
|
+
schema:
|
|
10161
|
+
type: string
|
|
10162
|
+
responses:
|
|
10163
|
+
'200':
|
|
10164
|
+
description: Search project resources
|
|
10165
|
+
content:
|
|
10166
|
+
application/json:
|
|
10167
|
+
schema:
|
|
10168
|
+
$ref: '#/components/schemas/SearchResponse'
|
|
10169
|
+
example:
|
|
10170
|
+
hits:
|
|
10171
|
+
- type: member
|
|
10172
|
+
id: ana@example.com
|
|
10173
|
+
name: Ana Ng
|
|
10174
|
+
title: ana@example.com
|
|
10175
|
+
href: /team
|
|
10176
|
+
- type: gate
|
|
10177
|
+
id: gat_01j7w7m9q4hxbf6npe6s9zr3vc
|
|
10178
|
+
name: checkout_v2
|
|
10179
|
+
title: Checkout v2
|
|
10180
|
+
href: /gates?open=gat_01j7w7m9q4hxbf6npe6s9zr3vc
|
|
10181
|
+
- type: experiment
|
|
10182
|
+
id: exp_01j7w7m9q4hxbf6npe6s9zr3vd
|
|
10183
|
+
name: checkout_button_color
|
|
10184
|
+
title: Checkout button colour test
|
|
10185
|
+
href: /experiments?open=exp_01j7w7m9q4hxbf6npe6s9zr3vd
|
|
10186
|
+
'400':
|
|
10187
|
+
$ref: '#/components/responses/BadRequest'
|
|
10188
|
+
'401':
|
|
10189
|
+
$ref: '#/components/responses/Unauthorized'
|
|
10190
|
+
'403':
|
|
10191
|
+
$ref: '#/components/responses/Forbidden'
|
|
10192
|
+
'404':
|
|
10193
|
+
$ref: '#/components/responses/NotFound'
|
|
10194
|
+
'409':
|
|
10195
|
+
$ref: '#/components/responses/Conflict'
|
|
10196
|
+
'422':
|
|
10197
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
10198
|
+
x-error-codes:
|
|
10199
|
+
- BAD_REQUEST
|
|
10200
|
+
- UNAUTHORIZED
|
|
10201
|
+
- FORBIDDEN
|
|
10202
|
+
x-cli:
|
|
10203
|
+
name: search
|
|
10204
|
+
/api/admin/tags:
|
|
10205
|
+
get:
|
|
10206
|
+
operationId: listTags
|
|
10207
|
+
summary: List the project's tags
|
|
10208
|
+
description: |-
|
|
10209
|
+
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.
|
|
10210
|
+
|
|
10211
|
+
**Use case:** See which tags already exist before tagging an item, so you reuse `ios` instead of minting `iOS-app`.
|
|
10212
|
+
tags:
|
|
10213
|
+
- Tags
|
|
10214
|
+
parameters:
|
|
10215
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
10216
|
+
- name: q
|
|
10217
|
+
in: query
|
|
10218
|
+
required: false
|
|
10219
|
+
description: Case-insensitive substring filter on the tag name. Omit to return every tag.
|
|
10220
|
+
schema:
|
|
10221
|
+
type: string
|
|
10222
|
+
maxLength: 64
|
|
10223
|
+
responses:
|
|
10224
|
+
'200':
|
|
10225
|
+
description: List the project's tags
|
|
10226
|
+
content:
|
|
10227
|
+
application/json:
|
|
10228
|
+
schema:
|
|
10229
|
+
$ref: '#/components/schemas/ListTagsResponse'
|
|
10230
|
+
example:
|
|
10231
|
+
- id: tag_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
10232
|
+
name: checkout
|
|
10233
|
+
- id: tag_01j7w8a1b2c3d4e5f6g7h8i9j1
|
|
10234
|
+
name: ios
|
|
10235
|
+
'400':
|
|
10236
|
+
$ref: '#/components/responses/BadRequest'
|
|
10237
|
+
'401':
|
|
10238
|
+
$ref: '#/components/responses/Unauthorized'
|
|
10239
|
+
'403':
|
|
10240
|
+
$ref: '#/components/responses/Forbidden'
|
|
10241
|
+
'404':
|
|
10242
|
+
$ref: '#/components/responses/NotFound'
|
|
10243
|
+
'409':
|
|
10244
|
+
$ref: '#/components/responses/Conflict'
|
|
10245
|
+
'422':
|
|
10246
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
10247
|
+
x-error-codes:
|
|
10248
|
+
- BAD_REQUEST
|
|
10249
|
+
- UNAUTHORIZED
|
|
10250
|
+
- FORBIDDEN
|
|
10251
|
+
x-cli:
|
|
10252
|
+
name: list
|
|
10253
|
+
/api/admin/tags/{entityType}/{entityId}:
|
|
10254
|
+
get:
|
|
10255
|
+
operationId: getEntityTags
|
|
10256
|
+
summary: Read an item's tags
|
|
10257
|
+
description: |-
|
|
10258
|
+
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.
|
|
10259
|
+
|
|
10260
|
+
**Use case:** Check an item's current tags before editing them.
|
|
10261
|
+
tags:
|
|
10262
|
+
- Tags
|
|
10263
|
+
parameters:
|
|
10264
|
+
- $ref: '#/components/parameters/ProjectId'
|
|
10265
|
+
- name: entityType
|
|
10266
|
+
in: path
|
|
10267
|
+
required: true
|
|
10268
|
+
description: The kind of item — `ops`, `flag`, `config`, `killswitch`, `metric`, `error`, `alert_rule`, or `experiment`.
|
|
10269
|
+
schema:
|
|
10270
|
+
$ref: '#/components/schemas/TaggableEntityType'
|
|
10271
|
+
- name: entityId
|
|
10272
|
+
in: path
|
|
10273
|
+
required: true
|
|
10274
|
+
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.
|
|
10275
|
+
schema:
|
|
10276
|
+
$ref: '#/components/schemas/ResourceId'
|
|
10277
|
+
responses:
|
|
10278
|
+
'200':
|
|
10279
|
+
description: Read an item's tags
|
|
9479
10280
|
content:
|
|
9480
10281
|
application/json:
|
|
9481
10282
|
schema:
|
|
9482
|
-
$ref: '#/components/schemas/
|
|
10283
|
+
$ref: '#/components/schemas/EntityTagsResponse'
|
|
9483
10284
|
example:
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
|
|
10285
|
+
entityType: ops
|
|
10286
|
+
entityId: fb_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
10287
|
+
tags:
|
|
10288
|
+
- checkout
|
|
10289
|
+
- ios
|
|
9489
10290
|
'400':
|
|
9490
10291
|
$ref: '#/components/responses/BadRequest'
|
|
9491
10292
|
'401':
|
|
@@ -9499,42 +10300,73 @@ paths:
|
|
|
9499
10300
|
'422':
|
|
9500
10301
|
$ref: '#/components/responses/UnprocessableEntity'
|
|
9501
10302
|
x-error-codes:
|
|
10303
|
+
- BAD_REQUEST
|
|
9502
10304
|
- UNAUTHORIZED
|
|
9503
10305
|
- FORBIDDEN
|
|
9504
|
-
-
|
|
9505
|
-
- PLAN_LIMIT
|
|
10306
|
+
- NOT_FOUND
|
|
9506
10307
|
x-cli:
|
|
9507
|
-
name:
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
|
|
10308
|
+
name: get
|
|
10309
|
+
positional:
|
|
10310
|
+
- entityType
|
|
10311
|
+
- entityId
|
|
10312
|
+
put:
|
|
10313
|
+
operationId: setEntityTags
|
|
10314
|
+
summary: Replace an item's tags
|
|
9512
10315
|
description: |-
|
|
9513
|
-
|
|
10316
|
+
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`).
|
|
9514
10317
|
|
|
9515
|
-
|
|
10318
|
+
**Use cases**
|
|
9516
10319
|
|
|
9517
|
-
**
|
|
10320
|
+
- **Tag an item** — `{ "tags": ["checkout", "ios"] }`.
|
|
10321
|
+
- **Clear tags** — `{ "tags": [] }`.
|
|
10322
|
+
|
|
10323
|
+
To add or remove a few tags without restating the rest, use the incremental `PATCH` instead.
|
|
9518
10324
|
tags:
|
|
9519
|
-
-
|
|
10325
|
+
- Tags
|
|
9520
10326
|
parameters:
|
|
9521
10327
|
- $ref: '#/components/parameters/ProjectId'
|
|
9522
|
-
- name:
|
|
10328
|
+
- name: entityType
|
|
9523
10329
|
in: path
|
|
9524
10330
|
required: true
|
|
9525
|
-
description:
|
|
10331
|
+
description: The kind of item — `ops`, `flag`, `config`, `killswitch`, `metric`, `error`, `alert_rule`, or `experiment`.
|
|
10332
|
+
schema:
|
|
10333
|
+
$ref: '#/components/schemas/TaggableEntityType'
|
|
10334
|
+
- name: entityId
|
|
10335
|
+
in: path
|
|
10336
|
+
required: true
|
|
10337
|
+
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.
|
|
9526
10338
|
schema:
|
|
9527
10339
|
$ref: '#/components/schemas/ResourceId'
|
|
10340
|
+
requestBody:
|
|
10341
|
+
required: true
|
|
10342
|
+
content:
|
|
10343
|
+
application/json:
|
|
10344
|
+
schema:
|
|
10345
|
+
$ref: '#/components/schemas/SetEntityTagsRequest'
|
|
10346
|
+
examples:
|
|
10347
|
+
tag:
|
|
10348
|
+
summary: Set the item's tags
|
|
10349
|
+
value:
|
|
10350
|
+
tags:
|
|
10351
|
+
- checkout
|
|
10352
|
+
- ios
|
|
10353
|
+
clear:
|
|
10354
|
+
summary: Remove every tag
|
|
10355
|
+
value:
|
|
10356
|
+
tags: []
|
|
9528
10357
|
responses:
|
|
9529
10358
|
'200':
|
|
9530
|
-
description:
|
|
10359
|
+
description: Replace an item's tags
|
|
9531
10360
|
content:
|
|
9532
10361
|
application/json:
|
|
9533
10362
|
schema:
|
|
9534
|
-
$ref: '#/components/schemas/
|
|
10363
|
+
$ref: '#/components/schemas/EntityTagsResponse'
|
|
9535
10364
|
example:
|
|
9536
|
-
|
|
9537
|
-
|
|
10365
|
+
entityType: ops
|
|
10366
|
+
entityId: fb_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
10367
|
+
tags:
|
|
10368
|
+
- checkout
|
|
10369
|
+
- ios
|
|
9538
10370
|
'400':
|
|
9539
10371
|
$ref: '#/components/responses/BadRequest'
|
|
9540
10372
|
'401':
|
|
@@ -9548,57 +10380,74 @@ paths:
|
|
|
9548
10380
|
'422':
|
|
9549
10381
|
$ref: '#/components/responses/UnprocessableEntity'
|
|
9550
10382
|
x-error-codes:
|
|
10383
|
+
- BAD_REQUEST
|
|
9551
10384
|
- UNAUTHORIZED
|
|
9552
10385
|
- FORBIDDEN
|
|
9553
10386
|
- NOT_FOUND
|
|
10387
|
+
- VALIDATION
|
|
9554
10388
|
x-cli:
|
|
9555
|
-
name:
|
|
10389
|
+
name: set
|
|
9556
10390
|
positional:
|
|
9557
|
-
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
operationId:
|
|
9561
|
-
summary:
|
|
10391
|
+
- entityType
|
|
10392
|
+
- entityId
|
|
10393
|
+
patch:
|
|
10394
|
+
operationId: updateEntityTags
|
|
10395
|
+
summary: Add or remove tags on an item
|
|
9562
10396
|
description: |-
|
|
9563
|
-
|
|
10397
|
+
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.
|
|
9564
10398
|
|
|
9565
|
-
|
|
10399
|
+
**Use cases**
|
|
9566
10400
|
|
|
9567
|
-
|
|
10401
|
+
- **Add a tag** — `{ "add": ["regression"] }`.
|
|
10402
|
+
- **Swap a tag** — `{ "add": ["p1"], "remove": ["p2"] }`.
|
|
9568
10403
|
tags:
|
|
9569
|
-
-
|
|
10404
|
+
- Tags
|
|
9570
10405
|
parameters:
|
|
9571
10406
|
- $ref: '#/components/parameters/ProjectId'
|
|
9572
|
-
- name:
|
|
9573
|
-
in:
|
|
9574
|
-
required:
|
|
9575
|
-
description:
|
|
10407
|
+
- name: entityType
|
|
10408
|
+
in: path
|
|
10409
|
+
required: true
|
|
10410
|
+
description: The kind of item — `ops`, `flag`, `config`, `killswitch`, `metric`, `error`, `alert_rule`, or `experiment`.
|
|
9576
10411
|
schema:
|
|
9577
|
-
|
|
10412
|
+
$ref: '#/components/schemas/TaggableEntityType'
|
|
10413
|
+
- name: entityId
|
|
10414
|
+
in: path
|
|
10415
|
+
required: true
|
|
10416
|
+
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.
|
|
10417
|
+
schema:
|
|
10418
|
+
$ref: '#/components/schemas/ResourceId'
|
|
10419
|
+
requestBody:
|
|
10420
|
+
required: true
|
|
10421
|
+
content:
|
|
10422
|
+
application/json:
|
|
10423
|
+
schema:
|
|
10424
|
+
$ref: '#/components/schemas/UpdateEntityTagsRequest'
|
|
10425
|
+
examples:
|
|
10426
|
+
add:
|
|
10427
|
+
summary: Attach one tag
|
|
10428
|
+
value:
|
|
10429
|
+
add:
|
|
10430
|
+
- regression
|
|
10431
|
+
swap:
|
|
10432
|
+
summary: Replace one tag with another
|
|
10433
|
+
value:
|
|
10434
|
+
add:
|
|
10435
|
+
- p1
|
|
10436
|
+
remove:
|
|
10437
|
+
- p2
|
|
9578
10438
|
responses:
|
|
9579
10439
|
'200':
|
|
9580
|
-
description:
|
|
10440
|
+
description: Add or remove tags on an item
|
|
9581
10441
|
content:
|
|
9582
10442
|
application/json:
|
|
9583
10443
|
schema:
|
|
9584
|
-
$ref: '#/components/schemas/
|
|
10444
|
+
$ref: '#/components/schemas/EntityTagsResponse'
|
|
9585
10445
|
example:
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
href: /team
|
|
9592
|
-
- type: gate
|
|
9593
|
-
id: gat_01j7w7m9q4hxbf6npe6s9zr3vc
|
|
9594
|
-
name: checkout_v2
|
|
9595
|
-
title: Checkout v2
|
|
9596
|
-
href: /gates?open=gat_01j7w7m9q4hxbf6npe6s9zr3vc
|
|
9597
|
-
- type: experiment
|
|
9598
|
-
id: exp_01j7w7m9q4hxbf6npe6s9zr3vd
|
|
9599
|
-
name: checkout_button_color
|
|
9600
|
-
title: Checkout button colour test
|
|
9601
|
-
href: /experiments?open=exp_01j7w7m9q4hxbf6npe6s9zr3vd
|
|
10446
|
+
entityType: ops
|
|
10447
|
+
entityId: fb_01j7w8a1b2c3d4e5f6g7h8i9j0
|
|
10448
|
+
tags:
|
|
10449
|
+
- checkout
|
|
10450
|
+
- ios
|
|
9602
10451
|
'400':
|
|
9603
10452
|
$ref: '#/components/responses/BadRequest'
|
|
9604
10453
|
'401':
|
|
@@ -9615,8 +10464,13 @@ paths:
|
|
|
9615
10464
|
- BAD_REQUEST
|
|
9616
10465
|
- UNAUTHORIZED
|
|
9617
10466
|
- FORBIDDEN
|
|
10467
|
+
- NOT_FOUND
|
|
10468
|
+
- VALIDATION
|
|
9618
10469
|
x-cli:
|
|
9619
|
-
name:
|
|
10470
|
+
name: update
|
|
10471
|
+
positional:
|
|
10472
|
+
- entityType
|
|
10473
|
+
- entityId
|
|
9620
10474
|
components:
|
|
9621
10475
|
securitySchemes:
|
|
9622
10476
|
bearerSdkKey:
|
|
@@ -11134,13 +11988,10 @@ components:
|
|
|
11134
11988
|
aggregation:
|
|
11135
11989
|
type: string
|
|
11136
11990
|
enum:
|
|
11137
|
-
- count_users
|
|
11138
11991
|
- count_events
|
|
11139
|
-
- retention_7d
|
|
11140
|
-
- retention_30d
|
|
11141
11992
|
- sum
|
|
11142
11993
|
- avg
|
|
11143
|
-
description: Reducer for the `event` form. Defaults to `count_users
|
|
11994
|
+
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.'
|
|
11144
11995
|
value:
|
|
11145
11996
|
type: string
|
|
11146
11997
|
minLength: 1
|
|
@@ -13538,272 +14389,79 @@ components:
|
|
|
13538
14389
|
description: Replacement allowed values (for `enum`), or `null` to clear.
|
|
13539
14390
|
required:
|
|
13540
14391
|
type: boolean
|
|
13541
|
-
description: Whether the attribute must be present on the evaluation context.
|
|
13542
|
-
description:
|
|
13543
|
-
type: string
|
|
13544
|
-
description: Optional human note shown in the dashboard.
|
|
13545
|
-
sdk_path:
|
|
13546
|
-
type: string
|
|
13547
|
-
description: Optional dotted path the SDK reads the value from.
|
|
13548
|
-
additionalProperties: false
|
|
13549
|
-
description: Body for `PATCH /api/admin/attributes/{id}`. Every field is optional; `name` is immutable.
|
|
13550
|
-
UpdateAttributeResponse:
|
|
13551
|
-
type: object
|
|
13552
|
-
properties:
|
|
13553
|
-
id:
|
|
13554
|
-
type: string
|
|
13555
|
-
description: Id of the attribute that was updated.
|
|
13556
|
-
required:
|
|
13557
|
-
- id
|
|
13558
|
-
additionalProperties: false
|
|
13559
|
-
description: Response for `PATCH /api/admin/attributes/{id}`.
|
|
13560
|
-
|
|
13561
|
-
description:
|
|
13562
|
-
type: object
|
|
13563
|
-
properties:
|
|
13564
|
-
|
|
13565
|
-
|
|
13566
|
-
|
|
13567
|
-
|
|
13568
|
-
|
|
13569
|
-
|
|
13570
|
-
|
|
13571
|
-
|
|
13572
|
-
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13578
|
-
|
|
13579
|
-
|
|
13580
|
-
|
|
13581
|
-
|
|
13582
|
-
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
|
|
13587
|
-
|
|
13588
|
-
|
|
13589
|
-
|
|
13590
|
-
|
|
13591
|
-
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
|
|
13595
|
-
|
|
13596
|
-
|
|
13597
|
-
|
|
13598
|
-
|
|
13599
|
-
|
|
13600
|
-
|
|
13601
|
-
|
|
13602
|
-
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
- type: object
|
|
13615
|
-
properties:
|
|
13616
|
-
kind:
|
|
13617
|
-
type: string
|
|
13618
|
-
const: unique
|
|
13619
|
-
required:
|
|
13620
|
-
- kind
|
|
13621
|
-
additionalProperties: false
|
|
13622
|
-
- type: object
|
|
13623
|
-
properties:
|
|
13624
|
-
kind:
|
|
13625
|
-
type: string
|
|
13626
|
-
const: quantile
|
|
13627
|
-
p:
|
|
13628
|
-
anyOf:
|
|
13629
|
-
- type: number
|
|
13630
|
-
const: 0.5
|
|
13631
|
-
- type: number
|
|
13632
|
-
const: 0.75
|
|
13633
|
-
- type: number
|
|
13634
|
-
const: 0.9
|
|
13635
|
-
- type: number
|
|
13636
|
-
const: 0.95
|
|
13637
|
-
- type: number
|
|
13638
|
-
const: 0.99
|
|
13639
|
-
- type: number
|
|
13640
|
-
const: 0.999
|
|
13641
|
-
description: Quantile fraction (0.5 = p50 … 0.999 = p999).
|
|
13642
|
-
required:
|
|
13643
|
-
- kind
|
|
13644
|
-
- p
|
|
13645
|
-
additionalProperties: false
|
|
13646
|
-
- type: object
|
|
13647
|
-
properties:
|
|
13648
|
-
kind:
|
|
13649
|
-
type: string
|
|
13650
|
-
const: retention_Nd
|
|
13651
|
-
'n':
|
|
13652
|
-
type: integer
|
|
13653
|
-
minimum: 1
|
|
13654
|
-
maximum: 90
|
|
13655
|
-
description: Retention window in days (1–90).
|
|
13656
|
-
required:
|
|
13657
|
-
- kind
|
|
13658
|
-
- 'n'
|
|
13659
|
-
additionalProperties: false
|
|
13660
|
-
- type: object
|
|
13661
|
-
properties:
|
|
13662
|
-
kind:
|
|
13663
|
-
type: string
|
|
13664
|
-
const: ratio
|
|
13665
|
-
numerator:
|
|
13666
|
-
type: object
|
|
13667
|
-
properties:
|
|
13668
|
-
agg:
|
|
13669
|
-
type: string
|
|
13670
|
-
enum:
|
|
13671
|
-
- count_users
|
|
13672
|
-
- count_events
|
|
13673
|
-
description: Counting mode for this ratio arm.
|
|
13674
|
-
metric:
|
|
13675
|
-
type: string
|
|
13676
|
-
minLength: 1
|
|
13677
|
-
maxLength: 128
|
|
13678
|
-
description: Source event name for this ratio arm.
|
|
13679
|
-
filters:
|
|
13680
|
-
description: Optional label filters.
|
|
13681
|
-
maxItems: 16
|
|
13682
|
-
type: array
|
|
13683
|
-
items:
|
|
13684
|
-
type: object
|
|
13685
|
-
properties:
|
|
13686
|
-
label:
|
|
13687
|
-
type: string
|
|
13688
|
-
pattern: ^[a-z_][a-z0-9_]{0,63}$
|
|
13689
|
-
description: Event property / label identifier.
|
|
13690
|
-
op:
|
|
13691
|
-
type: string
|
|
13692
|
-
enum:
|
|
13693
|
-
- '='
|
|
13694
|
-
- '!='
|
|
13695
|
-
- '=~'
|
|
13696
|
-
- '!~'
|
|
13697
|
-
description: Match operator (`=~`/`!~` are regex).
|
|
13698
|
-
value:
|
|
13699
|
-
type: string
|
|
13700
|
-
maxLength: 512
|
|
13701
|
-
description: Quoted filter value (coerced for numeric labels).
|
|
13702
|
-
required:
|
|
13703
|
-
- label
|
|
13704
|
-
- op
|
|
13705
|
-
- value
|
|
13706
|
-
additionalProperties: false
|
|
13707
|
-
description: One label filter on the source event.
|
|
13708
|
-
required:
|
|
13709
|
-
- agg
|
|
13710
|
-
- metric
|
|
13711
|
-
additionalProperties: false
|
|
13712
|
-
description: Numerator or denominator arm of a `ratio` aggregation.
|
|
13713
|
-
denominator:
|
|
13714
|
-
type: object
|
|
13715
|
-
properties:
|
|
13716
|
-
agg:
|
|
13717
|
-
type: string
|
|
13718
|
-
enum:
|
|
13719
|
-
- count_users
|
|
13720
|
-
- count_events
|
|
13721
|
-
description: Counting mode for this ratio arm.
|
|
13722
|
-
metric:
|
|
13723
|
-
type: string
|
|
13724
|
-
minLength: 1
|
|
13725
|
-
maxLength: 128
|
|
13726
|
-
description: Source event name for this ratio arm.
|
|
13727
|
-
filters:
|
|
13728
|
-
description: Optional label filters.
|
|
13729
|
-
maxItems: 16
|
|
13730
|
-
type: array
|
|
13731
|
-
items:
|
|
13732
|
-
type: object
|
|
13733
|
-
properties:
|
|
13734
|
-
label:
|
|
13735
|
-
type: string
|
|
13736
|
-
pattern: ^[a-z_][a-z0-9_]{0,63}$
|
|
13737
|
-
description: Event property / label identifier.
|
|
13738
|
-
op:
|
|
13739
|
-
type: string
|
|
13740
|
-
enum:
|
|
13741
|
-
- '='
|
|
13742
|
-
- '!='
|
|
13743
|
-
- '=~'
|
|
13744
|
-
- '!~'
|
|
13745
|
-
description: Match operator (`=~`/`!~` are regex).
|
|
13746
|
-
value:
|
|
13747
|
-
type: string
|
|
13748
|
-
maxLength: 512
|
|
13749
|
-
description: Quoted filter value (coerced for numeric labels).
|
|
13750
|
-
required:
|
|
13751
|
-
- label
|
|
13752
|
-
- op
|
|
13753
|
-
- value
|
|
13754
|
-
additionalProperties: false
|
|
13755
|
-
description: One label filter on the source event.
|
|
13756
|
-
required:
|
|
13757
|
-
- agg
|
|
13758
|
-
- metric
|
|
13759
|
-
additionalProperties: false
|
|
13760
|
-
description: Numerator or denominator arm of a `ratio` aggregation.
|
|
13761
|
-
required:
|
|
13762
|
-
- kind
|
|
13763
|
-
- numerator
|
|
13764
|
-
- denominator
|
|
13765
|
-
additionalProperties: false
|
|
13766
|
-
description: Aggregation function applied to the source event.
|
|
13767
|
-
metric:
|
|
13768
|
-
type: string
|
|
13769
|
-
minLength: 1
|
|
13770
|
-
maxLength: 128
|
|
13771
|
-
description: Source event name (must equal `event_name`).
|
|
13772
|
-
valueLabel:
|
|
13773
|
-
description: Numeric property summed/averaged for `sum`/`avg`/quantile aggregations.
|
|
13774
|
-
type: string
|
|
13775
|
-
minLength: 1
|
|
13776
|
-
maxLength: 128
|
|
13777
|
-
filters:
|
|
13778
|
-
default: []
|
|
13779
|
-
description: Label filters on the event.
|
|
13780
|
-
maxItems: 16
|
|
13781
|
-
type: array
|
|
13782
|
-
items:
|
|
13783
|
-
type: object
|
|
13784
|
-
properties:
|
|
13785
|
-
label:
|
|
13786
|
-
type: string
|
|
13787
|
-
pattern: ^[a-z_][a-z0-9_]{0,63}$
|
|
13788
|
-
description: Event property / label identifier.
|
|
13789
|
-
op:
|
|
13790
|
-
type: string
|
|
13791
|
-
enum:
|
|
13792
|
-
- '='
|
|
13793
|
-
- '!='
|
|
13794
|
-
- '=~'
|
|
13795
|
-
- '!~'
|
|
13796
|
-
description: Match operator (`=~`/`!~` are regex).
|
|
13797
|
-
value:
|
|
13798
|
-
type: string
|
|
13799
|
-
maxLength: 512
|
|
13800
|
-
description: Quoted filter value (coerced for numeric labels).
|
|
13801
|
-
required:
|
|
13802
|
-
- label
|
|
13803
|
-
- op
|
|
13804
|
-
- value
|
|
13805
|
-
additionalProperties: false
|
|
13806
|
-
description: One label filter on the source event.
|
|
14392
|
+
description: Whether the attribute must be present on the evaluation context.
|
|
14393
|
+
description:
|
|
14394
|
+
type: string
|
|
14395
|
+
description: Optional human note shown in the dashboard.
|
|
14396
|
+
sdk_path:
|
|
14397
|
+
type: string
|
|
14398
|
+
description: Optional dotted path the SDK reads the value from.
|
|
14399
|
+
additionalProperties: false
|
|
14400
|
+
description: Body for `PATCH /api/admin/attributes/{id}`. Every field is optional; `name` is immutable.
|
|
14401
|
+
UpdateAttributeResponse:
|
|
14402
|
+
type: object
|
|
14403
|
+
properties:
|
|
14404
|
+
id:
|
|
14405
|
+
type: string
|
|
14406
|
+
description: Id of the attribute that was updated.
|
|
14407
|
+
required:
|
|
14408
|
+
- id
|
|
14409
|
+
additionalProperties: false
|
|
14410
|
+
description: Response for `PATCH /api/admin/attributes/{id}`.
|
|
14411
|
+
MetricDisplayConfig:
|
|
14412
|
+
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.
|
|
14413
|
+
type: object
|
|
14414
|
+
properties:
|
|
14415
|
+
band:
|
|
14416
|
+
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.
|
|
14417
|
+
type: object
|
|
14418
|
+
properties:
|
|
14419
|
+
method:
|
|
14420
|
+
type: string
|
|
14421
|
+
enum:
|
|
14422
|
+
- seasonal
|
|
14423
|
+
sigma:
|
|
14424
|
+
type: number
|
|
14425
|
+
exclusiveMinimum: 0
|
|
14426
|
+
description: Half-width of the band in sigma-equivalents. Omit for 3, the sigma an alert rule also defaults to.
|
|
14427
|
+
required:
|
|
14428
|
+
- method
|
|
14429
|
+
additionalProperties: false
|
|
14430
|
+
forecast:
|
|
14431
|
+
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.
|
|
14432
|
+
type: object
|
|
14433
|
+
properties:
|
|
14434
|
+
method:
|
|
14435
|
+
type: string
|
|
14436
|
+
enum:
|
|
14437
|
+
- linear
|
|
14438
|
+
- seasonal
|
|
14439
|
+
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.'
|
|
14440
|
+
horizon:
|
|
14441
|
+
type: integer
|
|
14442
|
+
minimum: 1
|
|
14443
|
+
maximum: 500
|
|
14444
|
+
description: Buckets to project. Omit for a quarter of the window, which is the same claim at every bucket width.
|
|
14445
|
+
required:
|
|
14446
|
+
- method
|
|
14447
|
+
additionalProperties: false
|
|
14448
|
+
additionalProperties: false
|
|
14449
|
+
QueryIr:
|
|
14450
|
+
description: |-
|
|
14451
|
+
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.
|
|
14452
|
+
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.
|
|
14453
|
+
type: object
|
|
14454
|
+
properties:
|
|
14455
|
+
v:
|
|
14456
|
+
type: integer
|
|
14457
|
+
const: 2
|
|
14458
|
+
description: Storage version of the definition. `2` is the only one.
|
|
14459
|
+
expr:
|
|
14460
|
+
type: object
|
|
14461
|
+
additionalProperties: true
|
|
14462
|
+
description: |-
|
|
14463
|
+
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.
|
|
14464
|
+
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.
|
|
13807
14465
|
groupBy:
|
|
13808
14466
|
type: object
|
|
13809
14467
|
properties:
|
|
@@ -13812,23 +14470,25 @@ components:
|
|
|
13812
14470
|
enum:
|
|
13813
14471
|
- by
|
|
13814
14472
|
- without
|
|
13815
|
-
description: '`by`
|
|
14473
|
+
description: '`by` names the output dimensions; `without` names the ones to drop.'
|
|
13816
14474
|
labels:
|
|
13817
|
-
maxItems: 5
|
|
13818
14475
|
type: array
|
|
14476
|
+
maxItems: 8
|
|
13819
14477
|
items:
|
|
13820
14478
|
type: string
|
|
13821
14479
|
pattern: ^[a-z_][a-z0-9_]{0,63}$
|
|
13822
14480
|
description: Event property / label identifier.
|
|
13823
|
-
description: Labels
|
|
14481
|
+
description: Labels the grouping names.
|
|
13824
14482
|
required:
|
|
13825
14483
|
- op
|
|
13826
14484
|
- labels
|
|
13827
14485
|
additionalProperties: false
|
|
13828
|
-
description:
|
|
14486
|
+
description: How the series is split. On the envelope rather than in `expr` because every leaf of one expression shares it.
|
|
14487
|
+
display:
|
|
14488
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
13829
14489
|
required:
|
|
13830
|
-
-
|
|
13831
|
-
-
|
|
14490
|
+
- v
|
|
14491
|
+
- expr
|
|
13832
14492
|
additionalProperties: false
|
|
13833
14493
|
ListMetricsResponse:
|
|
13834
14494
|
type: array
|
|
@@ -13930,6 +14590,12 @@ components:
|
|
|
13930
14590
|
additionalProperties: {}
|
|
13931
14591
|
description: A metric definition.
|
|
13932
14592
|
description: Every metric in the project (the list endpoint is not paginated).
|
|
14593
|
+
MetricDisplayName:
|
|
14594
|
+
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.'
|
|
14595
|
+
maxLength: 200
|
|
14596
|
+
anyOf:
|
|
14597
|
+
- type: string
|
|
14598
|
+
- type: 'null'
|
|
13933
14599
|
MetricEventName:
|
|
13934
14600
|
type: string
|
|
13935
14601
|
minLength: 1
|
|
@@ -13969,6 +14635,8 @@ components:
|
|
|
13969
14635
|
properties:
|
|
13970
14636
|
name:
|
|
13971
14637
|
$ref: '#/components/schemas/MetricName'
|
|
14638
|
+
display_name:
|
|
14639
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
13972
14640
|
folder:
|
|
13973
14641
|
$ref: '#/components/schemas/Folder'
|
|
13974
14642
|
event_name:
|
|
@@ -13983,6 +14651,8 @@ components:
|
|
|
13983
14651
|
$ref: '#/components/schemas/MetricDirection'
|
|
13984
14652
|
unit:
|
|
13985
14653
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14654
|
+
display:
|
|
14655
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
13986
14656
|
required:
|
|
13987
14657
|
- name
|
|
13988
14658
|
- event_name
|
|
@@ -13994,6 +14664,8 @@ components:
|
|
|
13994
14664
|
properties:
|
|
13995
14665
|
name:
|
|
13996
14666
|
$ref: '#/components/schemas/MetricName'
|
|
14667
|
+
display_name:
|
|
14668
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
13997
14669
|
folder:
|
|
13998
14670
|
$ref: '#/components/schemas/Folder'
|
|
13999
14671
|
event_name:
|
|
@@ -14008,6 +14680,8 @@ components:
|
|
|
14008
14680
|
$ref: '#/components/schemas/MetricDirection'
|
|
14009
14681
|
unit:
|
|
14010
14682
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14683
|
+
display:
|
|
14684
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
14011
14685
|
required:
|
|
14012
14686
|
- name
|
|
14013
14687
|
- event_name
|
|
@@ -14133,6 +14807,8 @@ components:
|
|
|
14133
14807
|
UpdateMetricWithQuery:
|
|
14134
14808
|
type: object
|
|
14135
14809
|
properties:
|
|
14810
|
+
display_name:
|
|
14811
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
14136
14812
|
folder:
|
|
14137
14813
|
$ref: '#/components/schemas/Folder'
|
|
14138
14814
|
event_name:
|
|
@@ -14147,6 +14823,8 @@ components:
|
|
|
14147
14823
|
$ref: '#/components/schemas/MetricDirection'
|
|
14148
14824
|
unit:
|
|
14149
14825
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14826
|
+
display:
|
|
14827
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
14150
14828
|
required:
|
|
14151
14829
|
- query
|
|
14152
14830
|
additionalProperties: false
|
|
@@ -14154,6 +14832,8 @@ components:
|
|
|
14154
14832
|
UpdateMetricWithQueryIr:
|
|
14155
14833
|
type: object
|
|
14156
14834
|
properties:
|
|
14835
|
+
display_name:
|
|
14836
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
14157
14837
|
folder:
|
|
14158
14838
|
$ref: '#/components/schemas/Folder'
|
|
14159
14839
|
event_name:
|
|
@@ -14168,6 +14848,8 @@ components:
|
|
|
14168
14848
|
$ref: '#/components/schemas/MetricDirection'
|
|
14169
14849
|
unit:
|
|
14170
14850
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14851
|
+
display:
|
|
14852
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
14171
14853
|
required:
|
|
14172
14854
|
- query_ir
|
|
14173
14855
|
additionalProperties: false
|
|
@@ -14175,6 +14857,8 @@ components:
|
|
|
14175
14857
|
UpdateMetricFields:
|
|
14176
14858
|
type: object
|
|
14177
14859
|
properties:
|
|
14860
|
+
display_name:
|
|
14861
|
+
$ref: '#/components/schemas/MetricDisplayName'
|
|
14178
14862
|
folder:
|
|
14179
14863
|
$ref: '#/components/schemas/Folder'
|
|
14180
14864
|
event_name:
|
|
@@ -14187,8 +14871,10 @@ components:
|
|
|
14187
14871
|
$ref: '#/components/schemas/MetricDirection'
|
|
14188
14872
|
unit:
|
|
14189
14873
|
$ref: '#/components/schemas/MetricDisplayUnit'
|
|
14874
|
+
display:
|
|
14875
|
+
$ref: '#/components/schemas/MetricDisplayConfig'
|
|
14190
14876
|
additionalProperties: false
|
|
14191
|
-
description: Update-metric variant that leaves the query untouched (metadata-only edit — folder, event, winsorisation, default minimum effect of interest, direction, display unit).
|
|
14877
|
+
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).
|
|
14192
14878
|
UpdateMetricRequest:
|
|
14193
14879
|
oneOf:
|
|
14194
14880
|
- $ref: '#/components/schemas/UpdateMetricWithQuery'
|
|
@@ -14287,6 +14973,14 @@ components:
|
|
|
14287
14973
|
v:
|
|
14288
14974
|
type: number
|
|
14289
14975
|
description: Aggregated metric value in the bucket (sample-interval weighted).
|
|
14976
|
+
lo:
|
|
14977
|
+
type: number
|
|
14978
|
+
description: |
|
|
14979
|
+
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`.
|
|
14980
|
+
hi:
|
|
14981
|
+
type: number
|
|
14982
|
+
description: |
|
|
14983
|
+
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.
|
|
14290
14984
|
required:
|
|
14291
14985
|
- t
|
|
14292
14986
|
- v
|
|
@@ -14330,7 +15024,8 @@ components:
|
|
|
14330
15024
|
type: string
|
|
14331
15025
|
minLength: 1
|
|
14332
15026
|
maxLength: 64
|
|
14333
|
-
|
|
15027
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
15028
|
+
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.
|
|
14334
15029
|
type:
|
|
14335
15030
|
type: string
|
|
14336
15031
|
enum:
|
|
@@ -14346,11 +15041,14 @@ components:
|
|
|
14346
15041
|
default: ''
|
|
14347
15042
|
description: Human-readable description of the property.
|
|
14348
15043
|
type: string
|
|
15044
|
+
pending:
|
|
15045
|
+
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.'
|
|
15046
|
+
type: boolean
|
|
14349
15047
|
required:
|
|
14350
15048
|
- name
|
|
14351
15049
|
- type
|
|
14352
15050
|
additionalProperties: false
|
|
14353
|
-
description: One typed property
|
|
15051
|
+
description: One typed property on a catalogued event — declared by an admin, or discovered in traffic and awaiting declaration.
|
|
14354
15052
|
description: Typed properties declared on the event.
|
|
14355
15053
|
pending:
|
|
14356
15054
|
type: integer
|
|
@@ -14375,8 +15073,8 @@ components:
|
|
|
14375
15073
|
properties:
|
|
14376
15074
|
name:
|
|
14377
15075
|
type: string
|
|
14378
|
-
pattern: ^[a-zA-Z0-9_][a-zA-Z0-9_\-.]{0,
|
|
14379
|
-
description: Event name. Starts with a letter, digit, or `_`; letters, digits, `_`, `-`, `.`; max 128
|
|
15076
|
+
pattern: ^[a-zA-Z0-9_][a-zA-Z0-9_\-.]{0,49}$
|
|
15077
|
+
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.
|
|
14380
15078
|
folder:
|
|
14381
15079
|
$ref: '#/components/schemas/Folder'
|
|
14382
15080
|
description:
|
|
@@ -14393,7 +15091,8 @@ components:
|
|
|
14393
15091
|
type: string
|
|
14394
15092
|
minLength: 1
|
|
14395
15093
|
maxLength: 64
|
|
14396
|
-
|
|
15094
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
15095
|
+
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.
|
|
14397
15096
|
type:
|
|
14398
15097
|
type: string
|
|
14399
15098
|
enum:
|
|
@@ -14465,7 +15164,8 @@ components:
|
|
|
14465
15164
|
type: string
|
|
14466
15165
|
minLength: 1
|
|
14467
15166
|
maxLength: 64
|
|
14468
|
-
|
|
15167
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
15168
|
+
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.
|
|
14469
15169
|
type:
|
|
14470
15170
|
type: string
|
|
14471
15171
|
enum:
|
|
@@ -14481,11 +15181,14 @@ components:
|
|
|
14481
15181
|
default: ''
|
|
14482
15182
|
description: Human-readable description of the property.
|
|
14483
15183
|
type: string
|
|
15184
|
+
pending:
|
|
15185
|
+
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.'
|
|
15186
|
+
type: boolean
|
|
14484
15187
|
required:
|
|
14485
15188
|
- name
|
|
14486
15189
|
- type
|
|
14487
15190
|
additionalProperties: false
|
|
14488
|
-
description: One typed property
|
|
15191
|
+
description: One typed property on a catalogued event — declared by an admin, or discovered in traffic and awaiting declaration.
|
|
14489
15192
|
description: Typed properties declared on the event.
|
|
14490
15193
|
pending:
|
|
14491
15194
|
type: integer
|
|
@@ -14532,7 +15235,8 @@ components:
|
|
|
14532
15235
|
type: string
|
|
14533
15236
|
minLength: 1
|
|
14534
15237
|
maxLength: 64
|
|
14535
|
-
|
|
15238
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
15239
|
+
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.
|
|
14536
15240
|
type:
|
|
14537
15241
|
type: string
|
|
14538
15242
|
enum:
|
|
@@ -14583,7 +15287,8 @@ components:
|
|
|
14583
15287
|
type: string
|
|
14584
15288
|
minLength: 1
|
|
14585
15289
|
maxLength: 64
|
|
14586
|
-
|
|
15290
|
+
pattern: ^[a-zA-Z_][a-zA-Z_0-9]*$
|
|
15291
|
+
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.
|
|
14587
15292
|
type:
|
|
14588
15293
|
type: string
|
|
14589
15294
|
enum:
|
|
@@ -14641,6 +15346,7 @@ components:
|
|
|
14641
15346
|
enum:
|
|
14642
15347
|
- pr_ready
|
|
14643
15348
|
- pr_merged
|
|
15349
|
+
- pr_closed
|
|
14644
15350
|
- investigated
|
|
14645
15351
|
- detected
|
|
14646
15352
|
- question
|
|
@@ -14648,7 +15354,7 @@ components:
|
|
|
14648
15354
|
- pending_approval
|
|
14649
15355
|
- working
|
|
14650
15356
|
- backlog
|
|
14651
|
-
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`
|
|
15357
|
+
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".'
|
|
14652
15358
|
OpsBrowserContext:
|
|
14653
15359
|
type: object
|
|
14654
15360
|
properties:
|
|
@@ -14808,20 +15514,31 @@ components:
|
|
|
14808
15514
|
type: string
|
|
14809
15515
|
enum:
|
|
14810
15516
|
- metric_rule
|
|
15517
|
+
- killswitch_armed
|
|
14811
15518
|
- experiment_srm
|
|
14812
15519
|
- experiment_peek
|
|
14813
15520
|
- guardrail
|
|
14814
|
-
description: What kind of
|
|
15521
|
+
description: What kind of condition opened this alert instance.
|
|
14815
15522
|
dedupeKey:
|
|
14816
15523
|
type: string
|
|
14817
15524
|
description: Stable per-condition key; with `source` forms the ticket's `sourceRef`.
|
|
15525
|
+
detail:
|
|
15526
|
+
anyOf:
|
|
15527
|
+
- type: string
|
|
15528
|
+
- type: 'null'
|
|
15529
|
+
description: The instance's one-line reading — the observed condition in words.
|
|
15530
|
+
ruleId:
|
|
15531
|
+
anyOf:
|
|
15532
|
+
- type: string
|
|
15533
|
+
- type: 'null'
|
|
15534
|
+
description: Id of the alert rule that opened this instance, or `null` for a built-in condition.
|
|
14818
15535
|
severity:
|
|
14819
15536
|
type: string
|
|
14820
15537
|
enum:
|
|
14821
15538
|
- danger
|
|
14822
15539
|
- warn
|
|
14823
15540
|
- info
|
|
14824
|
-
description:
|
|
15541
|
+
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.
|
|
14825
15542
|
observedValue:
|
|
14826
15543
|
anyOf:
|
|
14827
15544
|
- type: number
|
|
@@ -14840,7 +15557,7 @@ components:
|
|
|
14840
15557
|
- resolved
|
|
14841
15558
|
- dismissed
|
|
14842
15559
|
- type: 'null'
|
|
14843
|
-
description:
|
|
15560
|
+
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.
|
|
14844
15561
|
activeSince:
|
|
14845
15562
|
anyOf:
|
|
14846
15563
|
- type: string
|
|
@@ -14864,9 +15581,8 @@ components:
|
|
|
14864
15581
|
required:
|
|
14865
15582
|
- source
|
|
14866
15583
|
- dedupeKey
|
|
14867
|
-
- severity
|
|
14868
15584
|
additionalProperties: {}
|
|
14869
|
-
description:
|
|
15585
|
+
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.
|
|
14870
15586
|
MeasurePlanResource:
|
|
14871
15587
|
type: object
|
|
14872
15588
|
properties:
|
|
@@ -14970,7 +15686,7 @@ components:
|
|
|
14970
15686
|
properties:
|
|
14971
15687
|
t:
|
|
14972
15688
|
type: number
|
|
14973
|
-
description: Bucket start — unix epoch **milliseconds
|
|
15689
|
+
description: Bucket start — unix epoch **milliseconds**. Bucket width scales with the window (hourly up to ~5 days, coarser beyond).
|
|
14974
15690
|
v:
|
|
14975
15691
|
type: number
|
|
14976
15692
|
description: Occurrence count in the bucket (sample-rate weighted).
|
|
@@ -14978,11 +15694,11 @@ components:
|
|
|
14978
15694
|
- t
|
|
14979
15695
|
- v
|
|
14980
15696
|
additionalProperties: {}
|
|
14981
|
-
description: One
|
|
14982
|
-
description:
|
|
15697
|
+
description: One occurrence bucket.
|
|
15698
|
+
description: Occurrence buckets, oldest first. Buckets with no occurrences are omitted.
|
|
14983
15699
|
domainFrom:
|
|
14984
15700
|
type: number
|
|
14985
|
-
description: Chart domain start — unix epoch milliseconds (
|
|
15701
|
+
description: Chart domain start — unix epoch milliseconds (the window's start).
|
|
14986
15702
|
domainTo:
|
|
14987
15703
|
type: number
|
|
14988
15704
|
description: Chart domain end — unix epoch milliseconds (the read time).
|
|
@@ -14991,7 +15707,7 @@ components:
|
|
|
14991
15707
|
- domainFrom
|
|
14992
15708
|
- domainTo
|
|
14993
15709
|
additionalProperties: {}
|
|
14994
|
-
description: Occurrence timeline for an `error` ticket —
|
|
15710
|
+
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.'
|
|
14995
15711
|
additionalProperties: {}
|
|
14996
15712
|
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.
|
|
14997
15713
|
GithubPrLink:
|
|
@@ -15015,6 +15731,25 @@ components:
|
|
|
15015
15731
|
- closes
|
|
15016
15732
|
- comment
|
|
15017
15733
|
description: How the PR was connected to the issue.
|
|
15734
|
+
owner:
|
|
15735
|
+
type: string
|
|
15736
|
+
description: Repository owner (org or user) the pull request lives in. Absent on links recorded before the field existed — `url` still carries it.
|
|
15737
|
+
repo:
|
|
15738
|
+
type: string
|
|
15739
|
+
description: Repository name the pull request lives in. Absent on links recorded before the field existed — `url` still carries it.
|
|
15740
|
+
state:
|
|
15741
|
+
type: string
|
|
15742
|
+
enum:
|
|
15743
|
+
- open
|
|
15744
|
+
- merged
|
|
15745
|
+
- closed
|
|
15746
|
+
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`.
|
|
15747
|
+
mergedAt:
|
|
15748
|
+
type: string
|
|
15749
|
+
description: ISO-8601 timestamp the pull request merged, when `state` is `merged`.
|
|
15750
|
+
closedAt:
|
|
15751
|
+
type: string
|
|
15752
|
+
description: ISO-8601 timestamp the pull request closed unmerged, when `state` is `closed`.
|
|
15018
15753
|
required:
|
|
15019
15754
|
- number
|
|
15020
15755
|
- url
|
|
@@ -15387,6 +16122,11 @@ components:
|
|
|
15387
16122
|
additionalProperties: {}
|
|
15388
16123
|
description: One queue item — any type — plus its resolved `owner` and run state.
|
|
15389
16124
|
description: A page of queue items, newest first.
|
|
16125
|
+
TagName:
|
|
16126
|
+
type: string
|
|
16127
|
+
minLength: 1
|
|
16128
|
+
maxLength: 64
|
|
16129
|
+
description: A tag name. Trimmed; matched case-insensitively against the project's existing tags.
|
|
15390
16130
|
CreateBugRequest:
|
|
15391
16131
|
type: object
|
|
15392
16132
|
properties:
|
|
@@ -15439,10 +16179,11 @@ components:
|
|
|
15439
16179
|
description: Emails of teammates to subscribe to this item's Slack pings at creation.
|
|
15440
16180
|
tags:
|
|
15441
16181
|
type: array
|
|
16182
|
+
maxItems: 50
|
|
15442
16183
|
items:
|
|
15443
|
-
|
|
16184
|
+
$ref: '#/components/schemas/TagName'
|
|
15444
16185
|
default: []
|
|
15445
|
-
description: Tag names to
|
|
16186
|
+
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.
|
|
15446
16187
|
reporterEmail:
|
|
15447
16188
|
anyOf:
|
|
15448
16189
|
- type: string
|
|
@@ -15530,10 +16271,11 @@ components:
|
|
|
15530
16271
|
description: Emails of teammates to subscribe to this item's Slack pings at creation.
|
|
15531
16272
|
tags:
|
|
15532
16273
|
type: array
|
|
16274
|
+
maxItems: 50
|
|
15533
16275
|
items:
|
|
15534
|
-
|
|
16276
|
+
$ref: '#/components/schemas/TagName'
|
|
15535
16277
|
default: []
|
|
15536
|
-
description: Tag names to
|
|
16278
|
+
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.
|
|
15537
16279
|
reporterEmail:
|
|
15538
16280
|
anyOf:
|
|
15539
16281
|
- type: string
|
|
@@ -15640,10 +16382,11 @@ components:
|
|
|
15640
16382
|
description: Emails of teammates to subscribe to this item's Slack pings at creation.
|
|
15641
16383
|
tags:
|
|
15642
16384
|
type: array
|
|
16385
|
+
maxItems: 50
|
|
15643
16386
|
items:
|
|
15644
|
-
|
|
16387
|
+
$ref: '#/components/schemas/TagName'
|
|
15645
16388
|
default: []
|
|
15646
|
-
description: Tag names to
|
|
16389
|
+
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.'
|
|
15647
16390
|
reporterEmail:
|
|
15648
16391
|
anyOf:
|
|
15649
16392
|
- type: string
|
|
@@ -15674,6 +16417,10 @@ components:
|
|
|
15674
16417
|
additionalProperties: {}
|
|
15675
16418
|
- type: 'null'
|
|
15676
16419
|
description: Arbitrary capture context, or `null`.
|
|
16420
|
+
dedupKey:
|
|
16421
|
+
type: string
|
|
16422
|
+
maxLength: 200
|
|
16423
|
+
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.'
|
|
15677
16424
|
notify:
|
|
15678
16425
|
anyOf:
|
|
15679
16426
|
- $ref: '#/components/schemas/NotificationTarget'
|
|
@@ -15682,7 +16429,7 @@ components:
|
|
|
15682
16429
|
required:
|
|
15683
16430
|
- title
|
|
15684
16431
|
additionalProperties: false
|
|
15685
|
-
description: Body for `POST /ops/bug`. The same bug fields as `CreateBugRequest`, minus the `type` discriminator — the path already says what is being filed
|
|
16432
|
+
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`.
|
|
15686
16433
|
CreatePublicTicketResponse:
|
|
15687
16434
|
type: object
|
|
15688
16435
|
properties:
|
|
@@ -15695,10 +16442,13 @@ components:
|
|
|
15695
16442
|
deduped:
|
|
15696
16443
|
type: boolean
|
|
15697
16444
|
description: '`true` when an open ticket already tracked this report and nothing was filed (HTTP 200). Absent on a fresh file (HTTP 201).'
|
|
16445
|
+
updated:
|
|
16446
|
+
type: boolean
|
|
16447
|
+
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.'
|
|
15698
16448
|
required:
|
|
15699
16449
|
- number
|
|
15700
16450
|
additionalProperties: false
|
|
15701
|
-
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
|
|
16451
|
+
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.'
|
|
15702
16452
|
CreatePublicFeatureRequestRequest:
|
|
15703
16453
|
type: object
|
|
15704
16454
|
properties:
|
|
@@ -15741,10 +16491,11 @@ components:
|
|
|
15741
16491
|
description: Emails of teammates to subscribe to this item's Slack pings at creation.
|
|
15742
16492
|
tags:
|
|
15743
16493
|
type: array
|
|
16494
|
+
maxItems: 50
|
|
15744
16495
|
items:
|
|
15745
|
-
|
|
16496
|
+
$ref: '#/components/schemas/TagName'
|
|
15746
16497
|
default: []
|
|
15747
|
-
description: Tag names to
|
|
16498
|
+
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.'
|
|
15748
16499
|
reporterEmail:
|
|
15749
16500
|
anyOf:
|
|
15750
16501
|
- type: string
|
|
@@ -15769,6 +16520,10 @@ components:
|
|
|
15769
16520
|
additionalProperties: {}
|
|
15770
16521
|
- type: 'null'
|
|
15771
16522
|
description: Arbitrary capture context, or `null`.
|
|
16523
|
+
dedupKey:
|
|
16524
|
+
type: string
|
|
16525
|
+
maxLength: 200
|
|
16526
|
+
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.'
|
|
15772
16527
|
notify:
|
|
15773
16528
|
anyOf:
|
|
15774
16529
|
- $ref: '#/components/schemas/NotificationTarget'
|
|
@@ -15777,7 +16532,7 @@ components:
|
|
|
15777
16532
|
required:
|
|
15778
16533
|
- title
|
|
15779
16534
|
additionalProperties: false
|
|
15780
|
-
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
|
|
16535
|
+
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`.
|
|
15781
16536
|
OpsItemAttachment:
|
|
15782
16537
|
type: object
|
|
15783
16538
|
properties:
|
|
@@ -16121,6 +16876,10 @@ components:
|
|
|
16121
16876
|
type: string
|
|
16122
16877
|
maxLength: 300
|
|
16123
16878
|
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.
|
|
16879
|
+
launch:
|
|
16880
|
+
type: boolean
|
|
16881
|
+
default: true
|
|
16882
|
+
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.'
|
|
16124
16883
|
additionalProperties: false
|
|
16125
16884
|
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.
|
|
16126
16885
|
AckOpsItemResponse:
|
|
@@ -16448,100 +17207,441 @@ components:
|
|
|
16448
17207
|
description: ISO-8601 timestamp the work finished.
|
|
16449
17208
|
sessionId:
|
|
16450
17209
|
type: string
|
|
16451
|
-
maxLength: 300
|
|
16452
|
-
description: The agent-run session id, so the dashboard can deep-link to the run.
|
|
17210
|
+
maxLength: 300
|
|
17211
|
+
description: The agent-run session id, so the dashboard can deep-link to the run.
|
|
17212
|
+
required:
|
|
17213
|
+
- kind
|
|
17214
|
+
additionalProperties: false
|
|
17215
|
+
description: Body for `POST /api/admin/ops/{handle}/investigation`. `kind` is required; include at least one content field (`summary`/`findings`/`question`/`qaNotes`) — the panel renders whatever it gets.
|
|
17216
|
+
UpdateOpsInvestigationRequest:
|
|
17217
|
+
type: object
|
|
17218
|
+
properties:
|
|
17219
|
+
kind:
|
|
17220
|
+
type: string
|
|
17221
|
+
enum:
|
|
17222
|
+
- investigated
|
|
17223
|
+
- detected
|
|
17224
|
+
- question
|
|
17225
|
+
- ready_for_qa
|
|
17226
|
+
- working
|
|
17227
|
+
- note
|
|
17228
|
+
description: Reclassify the record's lifecycle stage (e.g. flip a `working` run into `investigated` once findings land).
|
|
17229
|
+
summary:
|
|
17230
|
+
type: string
|
|
17231
|
+
maxLength: 2000
|
|
17232
|
+
description: One-line summary of the record.
|
|
17233
|
+
findings:
|
|
17234
|
+
type: string
|
|
17235
|
+
maxLength: 50000
|
|
17236
|
+
description: The full findings write-up (markdown).
|
|
17237
|
+
question:
|
|
17238
|
+
type: string
|
|
17239
|
+
maxLength: 10000
|
|
17240
|
+
description: A blocking question for the team (markdown).
|
|
17241
|
+
qaNotes:
|
|
17242
|
+
type: string
|
|
17243
|
+
maxLength: 50000
|
|
17244
|
+
description: How to verify the fix — QA notes (markdown).
|
|
17245
|
+
model:
|
|
17246
|
+
type: string
|
|
17247
|
+
maxLength: 200
|
|
17248
|
+
description: The model the agent ran on.
|
|
17249
|
+
prNumber:
|
|
17250
|
+
type: integer
|
|
17251
|
+
description: A PR the record references.
|
|
17252
|
+
prUrl:
|
|
17253
|
+
type: string
|
|
17254
|
+
format: uri
|
|
17255
|
+
maxLength: 2000
|
|
17256
|
+
description: HTML URL of that PR.
|
|
17257
|
+
sources:
|
|
17258
|
+
type: array
|
|
17259
|
+
maxItems: 200
|
|
17260
|
+
items:
|
|
17261
|
+
type: object
|
|
17262
|
+
properties:
|
|
17263
|
+
path:
|
|
17264
|
+
type: string
|
|
17265
|
+
description: Repo-relative file path inspected.
|
|
17266
|
+
url:
|
|
17267
|
+
type: string
|
|
17268
|
+
description: External link consulted.
|
|
17269
|
+
label:
|
|
17270
|
+
type: string
|
|
17271
|
+
description: Human-readable label for the source.
|
|
17272
|
+
additionalProperties: false
|
|
17273
|
+
description: One file/link inspected while producing the record.
|
|
17274
|
+
description: The files/links inspected.
|
|
17275
|
+
confidence:
|
|
17276
|
+
type: string
|
|
17277
|
+
enum:
|
|
17278
|
+
- low
|
|
17279
|
+
- medium
|
|
17280
|
+
- high
|
|
17281
|
+
description: Self-reported confidence in the record.
|
|
17282
|
+
tokensUsed:
|
|
17283
|
+
type: integer
|
|
17284
|
+
description: Tokens the run consumed.
|
|
17285
|
+
durationMs:
|
|
17286
|
+
type: integer
|
|
17287
|
+
description: Run duration in milliseconds.
|
|
17288
|
+
visibility:
|
|
17289
|
+
type: string
|
|
17290
|
+
enum:
|
|
17291
|
+
- draft
|
|
17292
|
+
- published
|
|
17293
|
+
description: Record visibility. `draft` keeps it out of the panel; `published` surfaces it.
|
|
17294
|
+
completedAt:
|
|
17295
|
+
type: string
|
|
17296
|
+
description: ISO-8601 timestamp the work finished. Set it (or flip `kind` off `working`) to mark a run record done.
|
|
17297
|
+
sessionId:
|
|
17298
|
+
type: string
|
|
17299
|
+
maxLength: 300
|
|
17300
|
+
description: The agent-run session id, so the dashboard can deep-link to the run.
|
|
17301
|
+
additionalProperties: false
|
|
17302
|
+
minProperties: 1
|
|
17303
|
+
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.
|
|
17304
|
+
OpsQuestionStatus:
|
|
17305
|
+
type: string
|
|
17306
|
+
enum:
|
|
17307
|
+
- open
|
|
17308
|
+
- completed
|
|
17309
|
+
- cancelled
|
|
17310
|
+
description: Where a question stands — `open` (waiting on a person), `completed` (answered), or `cancelled` (withdrawn by the asker).
|
|
17311
|
+
OpsQuestionAnswer:
|
|
17312
|
+
type: object
|
|
17313
|
+
properties:
|
|
17314
|
+
selected:
|
|
17315
|
+
type: array
|
|
17316
|
+
items:
|
|
17317
|
+
type: string
|
|
17318
|
+
description: The option labels the person picked (empty when they only answered "Other").
|
|
17319
|
+
other:
|
|
17320
|
+
anyOf:
|
|
17321
|
+
- type: string
|
|
17322
|
+
- type: 'null'
|
|
17323
|
+
description: The free-text "Other" answer, or `null`.
|
|
17324
|
+
required:
|
|
17325
|
+
- selected
|
|
17326
|
+
- other
|
|
17327
|
+
additionalProperties: false
|
|
17328
|
+
description: A person's answer to a question.
|
|
17329
|
+
OpsQuestionDelivery:
|
|
17330
|
+
type: string
|
|
17331
|
+
enum:
|
|
17332
|
+
- resume
|
|
17333
|
+
- poll
|
|
17334
|
+
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`.
|
|
17335
|
+
OpsQuestion:
|
|
17336
|
+
type: object
|
|
17337
|
+
properties:
|
|
17338
|
+
id:
|
|
17339
|
+
type: string
|
|
17340
|
+
description: Question id.
|
|
17341
|
+
feedbackId:
|
|
17342
|
+
type: string
|
|
17343
|
+
description: The queue item the question hangs off.
|
|
17344
|
+
header:
|
|
17345
|
+
type: string
|
|
17346
|
+
description: Short chip label for the question.
|
|
17347
|
+
question:
|
|
17348
|
+
type: string
|
|
17349
|
+
description: The full question (markdown).
|
|
17350
|
+
options:
|
|
17351
|
+
type: array
|
|
17352
|
+
items:
|
|
17353
|
+
type: object
|
|
17354
|
+
properties:
|
|
17355
|
+
label:
|
|
17356
|
+
type: string
|
|
17357
|
+
description: The option's display text.
|
|
17358
|
+
description:
|
|
17359
|
+
anyOf:
|
|
17360
|
+
- type: string
|
|
17361
|
+
- type: 'null'
|
|
17362
|
+
description: What picking the option means, or `null`.
|
|
17363
|
+
required:
|
|
17364
|
+
- label
|
|
17365
|
+
- description
|
|
17366
|
+
additionalProperties: false
|
|
17367
|
+
description: One offered choice.
|
|
17368
|
+
description: The offered choices, in order.
|
|
17369
|
+
multiSelect:
|
|
17370
|
+
type: boolean
|
|
17371
|
+
description: Whether several options may be picked.
|
|
17372
|
+
status:
|
|
17373
|
+
$ref: '#/components/schemas/OpsQuestionStatus'
|
|
17374
|
+
answer:
|
|
17375
|
+
anyOf:
|
|
17376
|
+
- $ref: '#/components/schemas/OpsQuestionAnswer'
|
|
17377
|
+
- type: 'null'
|
|
17378
|
+
description: The person's answer, or `null` while the question is open (or was withdrawn).
|
|
17379
|
+
answeredBy:
|
|
17380
|
+
anyOf:
|
|
17381
|
+
- type: string
|
|
17382
|
+
- type: 'null'
|
|
17383
|
+
description: Email of the person who answered, or `null`.
|
|
17384
|
+
answeredAt:
|
|
17385
|
+
anyOf:
|
|
17386
|
+
- type: string
|
|
17387
|
+
- type: 'null'
|
|
17388
|
+
description: ISO-8601 timestamp of the answer, or `null`.
|
|
17389
|
+
agent:
|
|
17390
|
+
anyOf:
|
|
17391
|
+
- type: string
|
|
17392
|
+
enum:
|
|
17393
|
+
- jarvis
|
|
17394
|
+
- claude
|
|
17395
|
+
- cursor
|
|
17396
|
+
- copilot
|
|
17397
|
+
- jules
|
|
17398
|
+
- type: 'null'
|
|
17399
|
+
description: The agent that asked, or `null` (asked by a person or an unattributed key).
|
|
17400
|
+
askedBy:
|
|
17401
|
+
anyOf:
|
|
17402
|
+
- type: string
|
|
17403
|
+
- type: 'null'
|
|
17404
|
+
description: Email of the person who asked, when a human asked, or `null`.
|
|
17405
|
+
runId:
|
|
17406
|
+
anyOf:
|
|
17407
|
+
- type: string
|
|
17408
|
+
- type: 'null'
|
|
17409
|
+
description: The run (investigation record id) the question was asked under, or `null`.
|
|
17410
|
+
delivery:
|
|
17411
|
+
$ref: '#/components/schemas/OpsQuestionDelivery'
|
|
17412
|
+
deliveredAt:
|
|
17413
|
+
anyOf:
|
|
17414
|
+
- type: string
|
|
17415
|
+
- type: 'null'
|
|
17416
|
+
description: ISO-8601 timestamp the answer was re-delivered to the asking run (`resume` only), or `null`.
|
|
17417
|
+
deliveryError:
|
|
17418
|
+
anyOf:
|
|
17419
|
+
- type: string
|
|
17420
|
+
- type: 'null'
|
|
17421
|
+
description: Why a `resume` re-delivery failed, or `null`.
|
|
17422
|
+
createdAt:
|
|
17423
|
+
type: string
|
|
17424
|
+
description: ISO-8601 creation timestamp.
|
|
17425
|
+
updatedAt:
|
|
17426
|
+
type: string
|
|
17427
|
+
description: ISO-8601 last-update timestamp.
|
|
16453
17428
|
required:
|
|
16454
|
-
-
|
|
17429
|
+
- id
|
|
17430
|
+
- feedbackId
|
|
17431
|
+
- header
|
|
17432
|
+
- question
|
|
17433
|
+
- options
|
|
17434
|
+
- multiSelect
|
|
17435
|
+
- status
|
|
17436
|
+
- answer
|
|
17437
|
+
- answeredBy
|
|
17438
|
+
- answeredAt
|
|
17439
|
+
- agent
|
|
17440
|
+
- askedBy
|
|
17441
|
+
- runId
|
|
17442
|
+
- delivery
|
|
17443
|
+
- deliveredAt
|
|
17444
|
+
- deliveryError
|
|
17445
|
+
- createdAt
|
|
17446
|
+
- updatedAt
|
|
16455
17447
|
additionalProperties: false
|
|
16456
|
-
description:
|
|
16457
|
-
|
|
17448
|
+
description: One structured question on a queue item and, once answered, its answer.
|
|
17449
|
+
ListOpsQuestionsResponse:
|
|
17450
|
+
type: array
|
|
17451
|
+
items:
|
|
17452
|
+
$ref: '#/components/schemas/OpsQuestion'
|
|
17453
|
+
description: Response for `GET /api/admin/ops/{handle}/questions` — the item's questions, newest first (max 100).
|
|
17454
|
+
OpsQuestionOption:
|
|
16458
17455
|
type: object
|
|
16459
17456
|
properties:
|
|
16460
|
-
|
|
17457
|
+
label:
|
|
16461
17458
|
type: string
|
|
16462
|
-
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
|
|
16466
|
-
- ready_for_qa
|
|
16467
|
-
- working
|
|
16468
|
-
- note
|
|
16469
|
-
description: Reclassify the record's lifecycle stage (e.g. flip a `working` run into `investigated` once findings land).
|
|
16470
|
-
summary:
|
|
17459
|
+
minLength: 1
|
|
17460
|
+
maxLength: 120
|
|
17461
|
+
description: The option's display text — short (1–5 words). Answers name options by this label.
|
|
17462
|
+
description:
|
|
16471
17463
|
type: string
|
|
16472
|
-
maxLength:
|
|
16473
|
-
description:
|
|
16474
|
-
|
|
17464
|
+
maxLength: 500
|
|
17465
|
+
description: What picking this option means — its trade-off or consequence.
|
|
17466
|
+
required:
|
|
17467
|
+
- label
|
|
17468
|
+
additionalProperties: false
|
|
17469
|
+
description: One choice offered by a question — rendered as a radio, or a checkbox when the question is `multiSelect`.
|
|
17470
|
+
AskOpsQuestionInput:
|
|
17471
|
+
type: object
|
|
17472
|
+
properties:
|
|
17473
|
+
header:
|
|
16475
17474
|
type: string
|
|
16476
|
-
|
|
16477
|
-
|
|
17475
|
+
minLength: 1
|
|
17476
|
+
maxLength: 24
|
|
17477
|
+
description: Very short chip label for the question (max 24 chars), e.g. `Auth method`.
|
|
16478
17478
|
question:
|
|
16479
17479
|
type: string
|
|
16480
|
-
|
|
16481
|
-
|
|
16482
|
-
|
|
16483
|
-
|
|
16484
|
-
|
|
16485
|
-
|
|
16486
|
-
|
|
17480
|
+
minLength: 1
|
|
17481
|
+
maxLength: 2000
|
|
17482
|
+
description: The complete question, ending with a question mark (markdown).
|
|
17483
|
+
options:
|
|
17484
|
+
type: array
|
|
17485
|
+
minItems: 2
|
|
17486
|
+
maxItems: 4
|
|
17487
|
+
items:
|
|
17488
|
+
$ref: '#/components/schemas/OpsQuestionOption'
|
|
17489
|
+
description: 2–4 distinct choices. Do not add an "Other" option — a free-text answer is always offered.
|
|
17490
|
+
multiSelect:
|
|
17491
|
+
type: boolean
|
|
17492
|
+
default: false
|
|
17493
|
+
description: '`true` lets the person pick several options (checkboxes); `false` (the default) exactly one (radios).'
|
|
17494
|
+
required:
|
|
17495
|
+
- header
|
|
17496
|
+
- question
|
|
17497
|
+
- options
|
|
17498
|
+
additionalProperties: false
|
|
17499
|
+
description: One question to ask — the `AskUserQuestion` shape.
|
|
17500
|
+
AskOpsQuestionsRequest:
|
|
17501
|
+
type: object
|
|
17502
|
+
properties:
|
|
17503
|
+
questions:
|
|
17504
|
+
type: array
|
|
17505
|
+
minItems: 1
|
|
17506
|
+
maxItems: 4
|
|
17507
|
+
items:
|
|
17508
|
+
$ref: '#/components/schemas/AskOpsQuestionInput'
|
|
17509
|
+
description: 1–4 questions to ask at once.
|
|
17510
|
+
runId:
|
|
16487
17511
|
type: string
|
|
16488
17512
|
maxLength: 200
|
|
16489
|
-
description: The
|
|
16490
|
-
|
|
16491
|
-
type: integer
|
|
16492
|
-
description: A PR the record references.
|
|
16493
|
-
prUrl:
|
|
17513
|
+
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.
|
|
17514
|
+
agent:
|
|
16494
17515
|
type: string
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
17516
|
+
enum:
|
|
17517
|
+
- jarvis
|
|
17518
|
+
- claude
|
|
17519
|
+
- cursor
|
|
17520
|
+
- copilot
|
|
17521
|
+
- jules
|
|
17522
|
+
description: The agent type asking — pass your own type when you are a coding agent. Defaults to the run's agent.
|
|
17523
|
+
delivery:
|
|
17524
|
+
$ref: '#/components/schemas/OpsQuestionDelivery'
|
|
17525
|
+
required:
|
|
17526
|
+
- questions
|
|
17527
|
+
additionalProperties: false
|
|
17528
|
+
description: Body for `POST /api/admin/ops/{handle}/questions`.
|
|
17529
|
+
AskOpsQuestionsResponse:
|
|
17530
|
+
type: array
|
|
17531
|
+
items:
|
|
17532
|
+
$ref: '#/components/schemas/OpsQuestion'
|
|
17533
|
+
description: Response for `POST /api/admin/ops/{handle}/questions` — the created questions, in the order asked.
|
|
17534
|
+
AnswerOpsQuestionRequest:
|
|
17535
|
+
type: object
|
|
17536
|
+
properties:
|
|
17537
|
+
selected:
|
|
16499
17538
|
type: array
|
|
16500
|
-
maxItems:
|
|
17539
|
+
maxItems: 4
|
|
16501
17540
|
items:
|
|
16502
|
-
type:
|
|
16503
|
-
|
|
16504
|
-
|
|
16505
|
-
|
|
16506
|
-
description: Repo-relative file path inspected.
|
|
16507
|
-
url:
|
|
16508
|
-
type: string
|
|
16509
|
-
description: External link consulted.
|
|
16510
|
-
label:
|
|
16511
|
-
type: string
|
|
16512
|
-
description: Human-readable label for the source.
|
|
16513
|
-
additionalProperties: false
|
|
16514
|
-
description: One file/link inspected while producing the record.
|
|
16515
|
-
description: The files/links inspected.
|
|
16516
|
-
confidence:
|
|
17541
|
+
type: string
|
|
17542
|
+
maxLength: 120
|
|
17543
|
+
description: The option labels picked — exactly one for a single-select question (unless answering only with `other`), one or more for `multiSelect`.
|
|
17544
|
+
other:
|
|
16517
17545
|
type: string
|
|
16518
|
-
|
|
16519
|
-
|
|
16520
|
-
|
|
16521
|
-
|
|
16522
|
-
|
|
16523
|
-
|
|
16524
|
-
|
|
16525
|
-
|
|
16526
|
-
|
|
16527
|
-
|
|
16528
|
-
|
|
16529
|
-
|
|
17546
|
+
maxLength: 10000
|
|
17547
|
+
description: A free-text "Other" answer.
|
|
17548
|
+
additionalProperties: false
|
|
17549
|
+
minProperties: 1
|
|
17550
|
+
description: Body for `POST /api/admin/ops/{handle}/questions/{questionId}/answer` — pick option labels, write a free-text answer, or both (multi-select only).
|
|
17551
|
+
OpsQaNoteKind:
|
|
17552
|
+
type: string
|
|
17553
|
+
enum:
|
|
17554
|
+
- narrowing
|
|
17555
|
+
- clarification
|
|
17556
|
+
- verification
|
|
17557
|
+
- correction
|
|
17558
|
+
description: What a QA note is — `narrowing` (only part of the bug still fails), `clarification` (changes what "fixed" means), `verification` (a pass/fail verdict on a fix) or `correction` (withdraws an earlier framing).
|
|
17559
|
+
OpsQaNoteVerdict:
|
|
17560
|
+
type: string
|
|
17561
|
+
enum:
|
|
17562
|
+
- pass
|
|
17563
|
+
- fail
|
|
17564
|
+
description: The outcome a `verification` note records.
|
|
17565
|
+
OpsQaNote:
|
|
17566
|
+
type: object
|
|
17567
|
+
properties:
|
|
17568
|
+
id:
|
|
16530
17569
|
type: string
|
|
16531
|
-
|
|
16532
|
-
|
|
16533
|
-
- published
|
|
16534
|
-
description: Record visibility. `draft` keeps it out of the panel; `published` surfaces it.
|
|
16535
|
-
completedAt:
|
|
17570
|
+
description: Note id.
|
|
17571
|
+
feedbackId:
|
|
16536
17572
|
type: string
|
|
16537
|
-
description:
|
|
16538
|
-
|
|
17573
|
+
description: The queue item the note hangs off.
|
|
17574
|
+
kind:
|
|
17575
|
+
$ref: '#/components/schemas/OpsQaNoteKind'
|
|
17576
|
+
verdict:
|
|
17577
|
+
anyOf:
|
|
17578
|
+
- $ref: '#/components/schemas/OpsQaNoteVerdict'
|
|
17579
|
+
- type: 'null'
|
|
17580
|
+
description: The pass/fail verdict of a `verification` note; `null` for every other kind.
|
|
17581
|
+
body:
|
|
16539
17582
|
type: string
|
|
16540
|
-
|
|
16541
|
-
|
|
17583
|
+
description: The note (markdown) — for a `verification`, what was checked.
|
|
17584
|
+
authorEmail:
|
|
17585
|
+
anyOf:
|
|
17586
|
+
- type: string
|
|
17587
|
+
- type: 'null'
|
|
17588
|
+
description: Email of the person (or the key's actor) who wrote the note, or `null` when an agent wrote it.
|
|
17589
|
+
authorAgent:
|
|
17590
|
+
anyOf:
|
|
17591
|
+
- type: string
|
|
17592
|
+
enum:
|
|
17593
|
+
- jarvis
|
|
17594
|
+
- claude
|
|
17595
|
+
- cursor
|
|
17596
|
+
- copilot
|
|
17597
|
+
- jules
|
|
17598
|
+
- type: 'null'
|
|
17599
|
+
description: The agent type that wrote the note (QA automation), or `null` for a person.
|
|
17600
|
+
createdAt:
|
|
17601
|
+
type: string
|
|
17602
|
+
description: ISO-8601 creation timestamp.
|
|
17603
|
+
required:
|
|
17604
|
+
- id
|
|
17605
|
+
- feedbackId
|
|
17606
|
+
- kind
|
|
17607
|
+
- verdict
|
|
17608
|
+
- body
|
|
17609
|
+
- authorEmail
|
|
17610
|
+
- authorAgent
|
|
17611
|
+
- createdAt
|
|
16542
17612
|
additionalProperties: false
|
|
16543
|
-
|
|
16544
|
-
|
|
17613
|
+
description: One typed, append-only QA note on a queue item.
|
|
17614
|
+
ListOpsQaNotesResponse:
|
|
17615
|
+
type: array
|
|
17616
|
+
items:
|
|
17617
|
+
$ref: '#/components/schemas/OpsQaNote'
|
|
17618
|
+
description: Response for `GET /api/admin/ops/{handle}/qa-notes` — the item's QA notes, newest first (max 200).
|
|
17619
|
+
CreateOpsQaNoteRequest:
|
|
17620
|
+
type: object
|
|
17621
|
+
properties:
|
|
17622
|
+
kind:
|
|
17623
|
+
$ref: '#/components/schemas/OpsQaNoteKind'
|
|
17624
|
+
body:
|
|
17625
|
+
type: string
|
|
17626
|
+
minLength: 1
|
|
17627
|
+
maxLength: 10000
|
|
17628
|
+
description: The note (markdown).
|
|
17629
|
+
verdict:
|
|
17630
|
+
$ref: '#/components/schemas/OpsQaNoteVerdict'
|
|
17631
|
+
agent:
|
|
17632
|
+
type: string
|
|
17633
|
+
enum:
|
|
17634
|
+
- jarvis
|
|
17635
|
+
- claude
|
|
17636
|
+
- cursor
|
|
17637
|
+
- copilot
|
|
17638
|
+
- jules
|
|
17639
|
+
description: The agent type writing the note — pass your own type when you are QA automation. Omitted, the note is attributed to the caller's identity.
|
|
17640
|
+
required:
|
|
17641
|
+
- kind
|
|
17642
|
+
- body
|
|
17643
|
+
additionalProperties: false
|
|
17644
|
+
description: Body for `POST /api/admin/ops/{handle}/qa-notes`. A `verification` note requires `verdict`; every other kind rejects it.
|
|
16545
17645
|
OpsAgentProfile:
|
|
16546
17646
|
type: object
|
|
16547
17647
|
properties:
|
|
@@ -16735,6 +17835,59 @@ components:
|
|
|
16735
17835
|
- channels
|
|
16736
17836
|
additionalProperties: false
|
|
16737
17837
|
description: Response for `GET /api/admin/slack/channels`.
|
|
17838
|
+
AlertCompositeSpec:
|
|
17839
|
+
type: object
|
|
17840
|
+
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.'
|
|
17841
|
+
properties:
|
|
17842
|
+
op:
|
|
17843
|
+
type: string
|
|
17844
|
+
enum:
|
|
17845
|
+
- and
|
|
17846
|
+
- or
|
|
17847
|
+
description: How the children's states combine.
|
|
17848
|
+
rules:
|
|
17849
|
+
type: array
|
|
17850
|
+
minItems: 2
|
|
17851
|
+
items:
|
|
17852
|
+
type: string
|
|
17853
|
+
minLength: 1
|
|
17854
|
+
description: Ids of the alert rules to combine. Stored sorted and de-duplicated.
|
|
17855
|
+
required:
|
|
17856
|
+
- op
|
|
17857
|
+
- rules
|
|
17858
|
+
additionalProperties: false
|
|
17859
|
+
AlertRuleNotify:
|
|
17860
|
+
anyOf:
|
|
17861
|
+
- type: object
|
|
17862
|
+
properties:
|
|
17863
|
+
slackChannel:
|
|
17864
|
+
anyOf:
|
|
17865
|
+
- type: object
|
|
17866
|
+
properties:
|
|
17867
|
+
id:
|
|
17868
|
+
type: string
|
|
17869
|
+
minLength: 1
|
|
17870
|
+
name:
|
|
17871
|
+
type: string
|
|
17872
|
+
minLength: 1
|
|
17873
|
+
required:
|
|
17874
|
+
- id
|
|
17875
|
+
- name
|
|
17876
|
+
additionalProperties: false
|
|
17877
|
+
- type: 'null'
|
|
17878
|
+
email:
|
|
17879
|
+
anyOf:
|
|
17880
|
+
- type: string
|
|
17881
|
+
format: email
|
|
17882
|
+
- type: 'null'
|
|
17883
|
+
inApp:
|
|
17884
|
+
anyOf:
|
|
17885
|
+
- type: boolean
|
|
17886
|
+
- type: 'null'
|
|
17887
|
+
description: Whether the in-app notification (the dashboard bell and Home) is recorded when the rule fires. Absent or `null` means on; `false` skips it for this rule.
|
|
17888
|
+
additionalProperties: false
|
|
17889
|
+
- type: 'null'
|
|
17890
|
+
description: Delivery target for a rule's alert; `null` = use the project default. The `NotificationTarget` shape plus the in-app switch.
|
|
16738
17891
|
ListAlertRulesResponse:
|
|
16739
17892
|
type: array
|
|
16740
17893
|
items:
|
|
@@ -16753,23 +17906,107 @@ components:
|
|
|
16753
17906
|
anyOf:
|
|
16754
17907
|
- type: string
|
|
16755
17908
|
- type: 'null'
|
|
16756
|
-
description: Display name of the bound metric, or `null` if the metric no longer exists.
|
|
16757
|
-
|
|
16758
|
-
type: string
|
|
16759
|
-
enum:
|
|
16760
|
-
-
|
|
16761
|
-
-
|
|
16762
|
-
-
|
|
16763
|
-
-
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
17909
|
+
description: Display name of the bound metric, or `null` if the metric no longer exists.
|
|
17910
|
+
kind:
|
|
17911
|
+
type: string
|
|
17912
|
+
enum:
|
|
17913
|
+
- normal
|
|
17914
|
+
- anomaly
|
|
17915
|
+
- outliers
|
|
17916
|
+
- no_data
|
|
17917
|
+
- composite
|
|
17918
|
+
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.
|
|
17919
|
+
comparator:
|
|
17920
|
+
type: string
|
|
17921
|
+
enum:
|
|
17922
|
+
- gt
|
|
17923
|
+
- gte
|
|
17924
|
+
- lt
|
|
17925
|
+
- lte
|
|
17926
|
+
description: How the metric value is compared to the threshold (gt/gte/lt/lte). Read only by a `normal` rule with no range set.
|
|
17927
|
+
threshold:
|
|
17928
|
+
type: number
|
|
17929
|
+
description: Threshold the metric value is compared against. Read only by a `normal` rule with no range set.
|
|
17930
|
+
rangeMin:
|
|
17931
|
+
anyOf:
|
|
17932
|
+
- type: number
|
|
17933
|
+
- type: 'null'
|
|
17934
|
+
description: Lower edge of the corridor a `normal` rule must stay inside; `null` if the rule is judged by comparator and threshold.
|
|
17935
|
+
rangeMax:
|
|
17936
|
+
anyOf:
|
|
17937
|
+
- type: number
|
|
17938
|
+
- type: 'null'
|
|
17939
|
+
description: Upper edge of the corridor a `normal` rule must stay inside; `null` if the rule is judged by comparator and threshold.
|
|
17940
|
+
sigma:
|
|
17941
|
+
anyOf:
|
|
17942
|
+
- type: number
|
|
17943
|
+
- type: 'null'
|
|
17944
|
+
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.
|
|
17945
|
+
direction:
|
|
17946
|
+
anyOf:
|
|
17947
|
+
- type: string
|
|
17948
|
+
enum:
|
|
17949
|
+
- above
|
|
17950
|
+
- below
|
|
17951
|
+
- either
|
|
17952
|
+
- type: 'null'
|
|
17953
|
+
description: Which side of the baseline an `anomaly` or `outliers` rule watches. `null` means either.
|
|
17954
|
+
sustained:
|
|
17955
|
+
type: boolean
|
|
17956
|
+
description: Whether the rule is judged by ACCUMULATED departure rather than bucket by bucket. `anomaly` and `outliers` only.
|
|
17957
|
+
warnThreshold:
|
|
17958
|
+
anyOf:
|
|
17959
|
+
- type: number
|
|
17960
|
+
- type: 'null'
|
|
17961
|
+
description: The milder bound, in the same unit the kind judges in. `null` means the rule has one level.
|
|
17962
|
+
recoveryThreshold:
|
|
17963
|
+
anyOf:
|
|
17964
|
+
- type: number
|
|
17965
|
+
- type: 'null'
|
|
17966
|
+
description: What the metric must get back to before a live alert closes. `null` means no hysteresis — the firing bound clears it.
|
|
17967
|
+
groupAlerts:
|
|
17968
|
+
type: boolean
|
|
17969
|
+
description: Whether the rule fires one alert per `by()` group rather than one for the whole metric.
|
|
17970
|
+
maxGroups:
|
|
17971
|
+
anyOf:
|
|
17972
|
+
- type: integer
|
|
17973
|
+
- type: 'null'
|
|
17974
|
+
description: How many groups this rule may alert on at once. `null` takes the shipped cap of 10.
|
|
17975
|
+
noDataMinutes:
|
|
17976
|
+
anyOf:
|
|
17977
|
+
- type: integer
|
|
17978
|
+
- type: 'null'
|
|
17979
|
+
description: How long the silence must last for a `no_data` rule. `null` on every other kind.
|
|
17980
|
+
delayMinutes:
|
|
17981
|
+
anyOf:
|
|
17982
|
+
- type: integer
|
|
17983
|
+
- type: 'null'
|
|
17984
|
+
description: How far behind live the evaluated window is held, on top of the reader's settle grace. `null` means no extra delay.
|
|
17985
|
+
autoResolveMinutes:
|
|
17986
|
+
anyOf:
|
|
17987
|
+
- type: integer
|
|
17988
|
+
- type: 'null'
|
|
17989
|
+
description: Close a live instance that has gone this long without a fresh verdict. `null` never auto-resolves.
|
|
17990
|
+
composite:
|
|
17991
|
+
anyOf:
|
|
17992
|
+
- $ref: '#/components/schemas/AlertCompositeSpec'
|
|
17993
|
+
- type: 'null'
|
|
17994
|
+
description: For a `composite` rule, the child rules and how their states combine. `null` on every other kind.
|
|
16768
17995
|
windowHours:
|
|
16769
17996
|
type: integer
|
|
16770
17997
|
minimum: -9007199254740991
|
|
16771
17998
|
maximum: 9007199254740991
|
|
16772
17999
|
description: Lookback window (hours) the metric is aggregated over.
|
|
18000
|
+
bucketMinutes:
|
|
18001
|
+
anyOf:
|
|
18002
|
+
- type: integer
|
|
18003
|
+
- type: 'null'
|
|
18004
|
+
description: Width of the buckets the window is split into, in minutes. `null` divides the window into 12 equal buckets.
|
|
18005
|
+
requiredBuckets:
|
|
18006
|
+
anyOf:
|
|
18007
|
+
- type: integer
|
|
18008
|
+
- type: 'null'
|
|
18009
|
+
description: How many buckets must breach before the rule fires. `null` means every bucket that had data.
|
|
16773
18010
|
severity:
|
|
16774
18011
|
type: string
|
|
16775
18012
|
enum:
|
|
@@ -16781,7 +18018,7 @@ components:
|
|
|
16781
18018
|
type: boolean
|
|
16782
18019
|
description: Whether the rule is evaluated by the cron.
|
|
16783
18020
|
notify:
|
|
16784
|
-
$ref: '#/components/schemas/
|
|
18021
|
+
$ref: '#/components/schemas/AlertRuleNotify'
|
|
16785
18022
|
createdAt:
|
|
16786
18023
|
type: string
|
|
16787
18024
|
description: ISO-8601 timestamp of creation.
|
|
@@ -16793,9 +18030,25 @@ components:
|
|
|
16793
18030
|
- name
|
|
16794
18031
|
- metricId
|
|
16795
18032
|
- metricName
|
|
18033
|
+
- kind
|
|
16796
18034
|
- comparator
|
|
16797
18035
|
- threshold
|
|
18036
|
+
- rangeMin
|
|
18037
|
+
- rangeMax
|
|
18038
|
+
- sigma
|
|
18039
|
+
- direction
|
|
18040
|
+
- sustained
|
|
18041
|
+
- warnThreshold
|
|
18042
|
+
- recoveryThreshold
|
|
18043
|
+
- groupAlerts
|
|
18044
|
+
- maxGroups
|
|
18045
|
+
- noDataMinutes
|
|
18046
|
+
- delayMinutes
|
|
18047
|
+
- autoResolveMinutes
|
|
18048
|
+
- composite
|
|
16798
18049
|
- windowHours
|
|
18050
|
+
- bucketMinutes
|
|
18051
|
+
- requiredBuckets
|
|
16799
18052
|
- severity
|
|
16800
18053
|
- enabled
|
|
16801
18054
|
- notify
|
|
@@ -16815,26 +18068,122 @@ components:
|
|
|
16815
18068
|
type: string
|
|
16816
18069
|
minLength: 1
|
|
16817
18070
|
description: Id of the metric to evaluate.
|
|
18071
|
+
kind:
|
|
18072
|
+
default: normal
|
|
18073
|
+
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.'
|
|
18074
|
+
type: string
|
|
18075
|
+
enum:
|
|
18076
|
+
- normal
|
|
18077
|
+
- anomaly
|
|
18078
|
+
- outliers
|
|
18079
|
+
- no_data
|
|
18080
|
+
- composite
|
|
16818
18081
|
comparator:
|
|
18082
|
+
default: gt
|
|
18083
|
+
description: How the metric value is compared to the threshold. Read only by a `normal` rule with no range set.
|
|
16819
18084
|
type: string
|
|
16820
18085
|
enum:
|
|
16821
18086
|
- gt
|
|
16822
18087
|
- gte
|
|
16823
18088
|
- lt
|
|
16824
18089
|
- lte
|
|
16825
|
-
description: How the metric value is compared to the threshold (gt/gte/lt/lte).
|
|
16826
18090
|
threshold:
|
|
16827
18091
|
type: number
|
|
16828
|
-
description: Threshold the metric value is compared against.
|
|
18092
|
+
description: Threshold the metric value is compared against. Required for a `normal` rule unless a range is given; ignored by every other kind.
|
|
18093
|
+
rangeMin:
|
|
18094
|
+
anyOf:
|
|
18095
|
+
- type: number
|
|
18096
|
+
- type: 'null'
|
|
18097
|
+
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.
|
|
18098
|
+
rangeMax:
|
|
18099
|
+
anyOf:
|
|
18100
|
+
- type: number
|
|
18101
|
+
- type: 'null'
|
|
18102
|
+
description: Upper edge of the corridor the metric must stay inside.
|
|
18103
|
+
sigma:
|
|
18104
|
+
anyOf:
|
|
18105
|
+
- type: number
|
|
18106
|
+
exclusiveMinimum: 0
|
|
18107
|
+
- type: 'null'
|
|
18108
|
+
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.
|
|
18109
|
+
direction:
|
|
18110
|
+
anyOf:
|
|
18111
|
+
- type: string
|
|
18112
|
+
enum:
|
|
18113
|
+
- above
|
|
18114
|
+
- below
|
|
18115
|
+
- either
|
|
18116
|
+
- type: 'null'
|
|
18117
|
+
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.
|
|
18118
|
+
sustained:
|
|
18119
|
+
default: false
|
|
18120
|
+
type: boolean
|
|
18121
|
+
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.'
|
|
16829
18122
|
windowHours:
|
|
16830
18123
|
default: 24
|
|
16831
18124
|
description: Lookback window (hours) the metric is aggregated over. 1–720.
|
|
16832
18125
|
type: integer
|
|
16833
18126
|
minimum: 1
|
|
16834
18127
|
maximum: 720
|
|
18128
|
+
bucketMinutes:
|
|
18129
|
+
anyOf:
|
|
18130
|
+
- type: integer
|
|
18131
|
+
minimum: 1
|
|
18132
|
+
maximum: 43200
|
|
18133
|
+
- type: 'null'
|
|
18134
|
+
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.
|
|
18135
|
+
requiredBuckets:
|
|
18136
|
+
anyOf:
|
|
18137
|
+
- type: integer
|
|
18138
|
+
minimum: 1
|
|
18139
|
+
- type: 'null'
|
|
18140
|
+
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.
|
|
18141
|
+
warnThreshold:
|
|
18142
|
+
anyOf:
|
|
18143
|
+
- type: number
|
|
18144
|
+
- type: 'null'
|
|
18145
|
+
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.'
|
|
18146
|
+
recoveryThreshold:
|
|
18147
|
+
anyOf:
|
|
18148
|
+
- type: number
|
|
18149
|
+
- type: 'null'
|
|
18150
|
+
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.
|
|
18151
|
+
groupAlerts:
|
|
18152
|
+
default: false
|
|
18153
|
+
type: boolean
|
|
18154
|
+
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.
|
|
18155
|
+
maxGroups:
|
|
18156
|
+
anyOf:
|
|
18157
|
+
- type: integer
|
|
18158
|
+
minimum: 1
|
|
18159
|
+
maximum: 50
|
|
18160
|
+
- type: 'null'
|
|
18161
|
+
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.
|
|
18162
|
+
noDataMinutes:
|
|
18163
|
+
anyOf:
|
|
18164
|
+
- type: integer
|
|
18165
|
+
minimum: 5
|
|
18166
|
+
maximum: 43200
|
|
18167
|
+
- type: 'null'
|
|
18168
|
+
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.'
|
|
18169
|
+
delayMinutes:
|
|
18170
|
+
anyOf:
|
|
18171
|
+
- type: integer
|
|
18172
|
+
minimum: 1
|
|
18173
|
+
maximum: 1440
|
|
18174
|
+
- type: 'null'
|
|
18175
|
+
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.
|
|
18176
|
+
autoResolveMinutes:
|
|
18177
|
+
anyOf:
|
|
18178
|
+
- type: integer
|
|
18179
|
+
minimum: 1
|
|
18180
|
+
- type: 'null'
|
|
18181
|
+
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.
|
|
18182
|
+
composite:
|
|
18183
|
+
$ref: '#/components/schemas/AlertCompositeSpec'
|
|
16835
18184
|
severity:
|
|
16836
18185
|
default: warn
|
|
16837
|
-
description: Severity of the raised alert.
|
|
18186
|
+
description: Severity of the raised alert. A `warnThreshold` breach opens one step quieter than this.
|
|
16838
18187
|
type: string
|
|
16839
18188
|
enum:
|
|
16840
18189
|
- danger
|
|
@@ -16845,12 +18194,10 @@ components:
|
|
|
16845
18194
|
description: Whether the rule is evaluated by the cron.
|
|
16846
18195
|
type: boolean
|
|
16847
18196
|
notify:
|
|
16848
|
-
$ref: '#/components/schemas/
|
|
18197
|
+
$ref: '#/components/schemas/AlertRuleNotify'
|
|
16849
18198
|
required:
|
|
16850
18199
|
- name
|
|
16851
18200
|
- metricId
|
|
16852
|
-
- comparator
|
|
16853
|
-
- threshold
|
|
16854
18201
|
additionalProperties: false
|
|
16855
18202
|
CreateAlertRuleResponse:
|
|
16856
18203
|
type: object
|
|
@@ -16877,6 +18224,14 @@ components:
|
|
|
16877
18224
|
type: string
|
|
16878
18225
|
minLength: 1
|
|
16879
18226
|
maxLength: 120
|
|
18227
|
+
kind:
|
|
18228
|
+
type: string
|
|
18229
|
+
enum:
|
|
18230
|
+
- normal
|
|
18231
|
+
- anomaly
|
|
18232
|
+
- outliers
|
|
18233
|
+
- no_data
|
|
18234
|
+
- composite
|
|
16880
18235
|
comparator:
|
|
16881
18236
|
type: string
|
|
16882
18237
|
enum:
|
|
@@ -16886,10 +18241,93 @@ components:
|
|
|
16886
18241
|
- lte
|
|
16887
18242
|
threshold:
|
|
16888
18243
|
type: number
|
|
18244
|
+
rangeMin:
|
|
18245
|
+
anyOf:
|
|
18246
|
+
- type: number
|
|
18247
|
+
- type: 'null'
|
|
18248
|
+
description: Lower edge of the corridor; `null` drops it, returning the rule to comparator and threshold when both bounds are gone.
|
|
18249
|
+
rangeMax:
|
|
18250
|
+
anyOf:
|
|
18251
|
+
- type: number
|
|
18252
|
+
- type: 'null'
|
|
18253
|
+
description: Upper edge of the corridor; `null` drops it.
|
|
18254
|
+
sigma:
|
|
18255
|
+
anyOf:
|
|
18256
|
+
- type: number
|
|
18257
|
+
exclusiveMinimum: 0
|
|
18258
|
+
- type: 'null'
|
|
18259
|
+
description: Sigmas an `anomaly` or `outliers` rule fires at; `null` restores the default of 3.
|
|
18260
|
+
direction:
|
|
18261
|
+
anyOf:
|
|
18262
|
+
- type: string
|
|
18263
|
+
enum:
|
|
18264
|
+
- above
|
|
18265
|
+
- below
|
|
18266
|
+
- either
|
|
18267
|
+
- type: 'null'
|
|
18268
|
+
description: Which side an `anomaly` or `outliers` rule watches; `null` restores either.
|
|
18269
|
+
sustained:
|
|
18270
|
+
type: boolean
|
|
18271
|
+
description: Judge the window by accumulated departure rather than bucket by bucket. `anomaly` and `outliers` only; refused alongside `requiredBuckets`.
|
|
18272
|
+
warnThreshold:
|
|
18273
|
+
anyOf:
|
|
18274
|
+
- type: number
|
|
18275
|
+
- type: 'null'
|
|
18276
|
+
description: The milder bound; `null` drops the warning level, leaving the rule with one.
|
|
18277
|
+
recoveryThreshold:
|
|
18278
|
+
anyOf:
|
|
18279
|
+
- type: number
|
|
18280
|
+
- type: 'null'
|
|
18281
|
+
description: What the metric must get back to before a live alert closes; `null` drops the hysteresis.
|
|
18282
|
+
groupAlerts:
|
|
18283
|
+
type: boolean
|
|
18284
|
+
description: Fire one alert per `by()` group. Refused on a metric with no grouping.
|
|
18285
|
+
maxGroups:
|
|
18286
|
+
anyOf:
|
|
18287
|
+
- type: integer
|
|
18288
|
+
minimum: 1
|
|
18289
|
+
maximum: 50
|
|
18290
|
+
- type: 'null'
|
|
18291
|
+
description: How many groups may alert at once; `null` restores the default of 10.
|
|
18292
|
+
noDataMinutes:
|
|
18293
|
+
anyOf:
|
|
18294
|
+
- type: integer
|
|
18295
|
+
minimum: 5
|
|
18296
|
+
maximum: 43200
|
|
18297
|
+
- type: 'null'
|
|
18298
|
+
description: How long a `no_data` rule's silence must last; `null` restores 15 minutes.
|
|
18299
|
+
delayMinutes:
|
|
18300
|
+
anyOf:
|
|
18301
|
+
- type: integer
|
|
18302
|
+
minimum: 1
|
|
18303
|
+
maximum: 1440
|
|
18304
|
+
- type: 'null'
|
|
18305
|
+
description: How far behind live the window is held; `null` drops the delay.
|
|
18306
|
+
autoResolveMinutes:
|
|
18307
|
+
anyOf:
|
|
18308
|
+
- type: integer
|
|
18309
|
+
minimum: 1
|
|
18310
|
+
- type: 'null'
|
|
18311
|
+
description: Close a stale live instance after this long; `null` never auto-resolves.
|
|
18312
|
+
composite:
|
|
18313
|
+
$ref: '#/components/schemas/AlertCompositeSpec'
|
|
16889
18314
|
windowHours:
|
|
16890
18315
|
type: integer
|
|
16891
18316
|
minimum: 1
|
|
16892
18317
|
maximum: 720
|
|
18318
|
+
bucketMinutes:
|
|
18319
|
+
anyOf:
|
|
18320
|
+
- type: integer
|
|
18321
|
+
minimum: 1
|
|
18322
|
+
maximum: 43200
|
|
18323
|
+
- type: 'null'
|
|
18324
|
+
description: Bucket width in minutes; `null` restores the default 12 buckets per window.
|
|
18325
|
+
requiredBuckets:
|
|
18326
|
+
anyOf:
|
|
18327
|
+
- type: integer
|
|
18328
|
+
minimum: 1
|
|
18329
|
+
- type: 'null'
|
|
18330
|
+
description: Buckets that must breach to fire; `null` restores "every bucket that had data".
|
|
16893
18331
|
severity:
|
|
16894
18332
|
type: string
|
|
16895
18333
|
enum:
|
|
@@ -16899,7 +18337,7 @@ components:
|
|
|
16899
18337
|
enabled:
|
|
16900
18338
|
type: boolean
|
|
16901
18339
|
notify:
|
|
16902
|
-
$ref: '#/components/schemas/
|
|
18340
|
+
$ref: '#/components/schemas/AlertRuleNotify'
|
|
16903
18341
|
additionalProperties: false
|
|
16904
18342
|
UpdateAlertRuleResponse:
|
|
16905
18343
|
type: object
|
|
@@ -16913,13 +18351,15 @@ components:
|
|
|
16913
18351
|
AlertApiRow:
|
|
16914
18352
|
type: object
|
|
16915
18353
|
description: |-
|
|
16916
|
-
One FIRED alert — a condition the platform observed
|
|
18354
|
+
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.
|
|
18355
|
+
|
|
18356
|
+
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.
|
|
16917
18357
|
|
|
16918
18358
|
Every field is always present on the wire; nullable fields are `null`, never absent.
|
|
16919
18359
|
properties:
|
|
16920
18360
|
id:
|
|
16921
18361
|
type: string
|
|
16922
|
-
description: Stable opaque
|
|
18362
|
+
description: Stable opaque instance id — also the id of the ops queue item this instance is.
|
|
16923
18363
|
source:
|
|
16924
18364
|
type: string
|
|
16925
18365
|
enum:
|
|
@@ -16940,10 +18380,10 @@ components:
|
|
|
16940
18380
|
- danger
|
|
16941
18381
|
- warn
|
|
16942
18382
|
- info
|
|
16943
|
-
description: How loud the alert is — `danger` pages, `warn` is the default, `info` is FYI-only.
|
|
18383
|
+
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.
|
|
16944
18384
|
dedupeKey:
|
|
16945
18385
|
type: string
|
|
16946
|
-
description: Idempotency + reconcile key within `(project, source)` — re-raising the same condition refreshes the
|
|
18386
|
+
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`.
|
|
16947
18387
|
title:
|
|
16948
18388
|
type: string
|
|
16949
18389
|
description: Short human-readable headline (what fired).
|
|
@@ -16966,10 +18406,10 @@ components:
|
|
|
16966
18406
|
- active
|
|
16967
18407
|
- resolved
|
|
16968
18408
|
- dismissed
|
|
16969
|
-
description: Lifecycle state. `active` means the condition
|
|
18409
|
+
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`).
|
|
16970
18410
|
createdAt:
|
|
16971
18411
|
type: string
|
|
16972
|
-
description: ISO-8601 timestamp the
|
|
18412
|
+
description: ISO-8601 timestamp this instance opened — when the condition started firing.
|
|
16973
18413
|
resolvedAt:
|
|
16974
18414
|
description: ISO-8601 timestamp the alert flipped to `resolved`, or `null` while it hasn't.
|
|
16975
18415
|
anyOf:
|
|
@@ -17031,7 +18471,7 @@ components:
|
|
|
17031
18471
|
- active
|
|
17032
18472
|
- resolved
|
|
17033
18473
|
- dismissed
|
|
17034
|
-
description: New lifecycle state. `resolved` / `dismissed` stamp their timestamp; `active` re-opens and clears both.
|
|
18474
|
+
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.
|
|
17035
18475
|
assigneeId:
|
|
17036
18476
|
description: PERSON owner — a `users.id`, or `null` to clear the assignment.
|
|
17037
18477
|
anyOf:
|
|
@@ -17217,6 +18657,12 @@ components:
|
|
|
17217
18657
|
- type: boolean
|
|
17218
18658
|
- type: number
|
|
17219
18659
|
description: Whether key-authenticated public ticket creation (`POST /cli/report`) is allowed into this project. Off by default.
|
|
18660
|
+
errorAutocloseDays:
|
|
18661
|
+
type: integer
|
|
18662
|
+
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.
|
|
18663
|
+
errorTicketMinOccurrences:
|
|
18664
|
+
type: integer
|
|
18665
|
+
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.
|
|
17220
18666
|
stripeSubscriptionId:
|
|
17221
18667
|
anyOf:
|
|
17222
18668
|
- type: string
|
|
@@ -17296,6 +18742,8 @@ components:
|
|
|
17296
18742
|
- moduleUser
|
|
17297
18743
|
- moduleEvents
|
|
17298
18744
|
- allowPublicTickets
|
|
18745
|
+
- errorAutocloseDays
|
|
18746
|
+
- errorTicketMinOccurrences
|
|
17299
18747
|
- slug
|
|
17300
18748
|
- logo
|
|
17301
18749
|
- defaultEnv
|
|
@@ -17514,6 +18962,16 @@ components:
|
|
|
17514
18962
|
minimum: 0.0001
|
|
17515
18963
|
maximum: 0.05
|
|
17516
18964
|
description: SRM chi-square p-value below which the run is called invalid.
|
|
18965
|
+
errorAutocloseDays:
|
|
18966
|
+
type: integer
|
|
18967
|
+
minimum: 0
|
|
18968
|
+
maximum: 365
|
|
18969
|
+
description: Days an `open` tracked error may go unseen before the nightly sweep auto-resolves it. `0` disables auto-close for this project.
|
|
18970
|
+
errorTicketMinOccurrences:
|
|
18971
|
+
type: integer
|
|
18972
|
+
minimum: 1
|
|
18973
|
+
maximum: 10000
|
|
18974
|
+
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.
|
|
17517
18975
|
additionalProperties: false
|
|
17518
18976
|
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.
|
|
17519
18977
|
ListI18nProfilesResponse:
|
|
@@ -18582,21 +20040,50 @@ components:
|
|
|
18582
20040
|
- config
|
|
18583
20041
|
additionalProperties: false
|
|
18584
20042
|
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.
|
|
20043
|
+
CursorTriggerRepo:
|
|
20044
|
+
type: object
|
|
20045
|
+
properties:
|
|
20046
|
+
url:
|
|
20047
|
+
type: string
|
|
20048
|
+
format: uri
|
|
20049
|
+
description: Repo the cloud agent runs against, e.g. `https://github.com/owner/repo`.
|
|
20050
|
+
startingRef:
|
|
20051
|
+
type: string
|
|
20052
|
+
minLength: 1
|
|
20053
|
+
description: Optional branch this repo's runs start from. Omit for the repo's default branch.
|
|
20054
|
+
required:
|
|
20055
|
+
- url
|
|
20056
|
+
additionalProperties: false
|
|
20057
|
+
description: One repo a trigger runs against, with the branch its runs start from.
|
|
18585
20058
|
CursorTriggerConfig:
|
|
18586
20059
|
type: object
|
|
18587
20060
|
properties:
|
|
18588
20061
|
repoUrl:
|
|
18589
20062
|
type: string
|
|
18590
20063
|
format: uri
|
|
18591
|
-
description:
|
|
20064
|
+
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.'
|
|
18592
20065
|
startingRef:
|
|
18593
20066
|
type: string
|
|
18594
20067
|
minLength: 1
|
|
18595
|
-
description: Optional git ref the run starts from.
|
|
20068
|
+
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.
|
|
20069
|
+
repos:
|
|
20070
|
+
type: array
|
|
20071
|
+
minItems: 1
|
|
20072
|
+
items:
|
|
20073
|
+
$ref: '#/components/schemas/CursorTriggerRepo'
|
|
20074
|
+
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).
|
|
18596
20075
|
projectId:
|
|
18597
20076
|
type: string
|
|
18598
20077
|
minLength: 1
|
|
18599
20078
|
description: Shipeasy project id the run targets.
|
|
20079
|
+
agentId:
|
|
20080
|
+
type: string
|
|
20081
|
+
minLength: 1
|
|
20082
|
+
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.
|
|
20083
|
+
fireText:
|
|
20084
|
+
type: string
|
|
20085
|
+
minLength: 1
|
|
20086
|
+
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.
|
|
18600
20087
|
required:
|
|
18601
20088
|
- repoUrl
|
|
18602
20089
|
- projectId
|
|
@@ -18631,7 +20118,7 @@ components:
|
|
|
18631
20118
|
opsKey:
|
|
18632
20119
|
type: string
|
|
18633
20120
|
minLength: 1
|
|
18634
|
-
description: Restricted Shipeasy ops key
|
|
20121
|
+
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.
|
|
18635
20122
|
enabled:
|
|
18636
20123
|
type: boolean
|
|
18637
20124
|
default: true
|
|
@@ -18643,13 +20130,33 @@ components:
|
|
|
18643
20130
|
- opsKey
|
|
18644
20131
|
additionalProperties: false
|
|
18645
20132
|
description: Create a Cursor cloud-agent trigger. Both keys are required up front (never tokenless). Idempotent by `config.repoUrl`.
|
|
20133
|
+
CopilotTriggerRepo:
|
|
20134
|
+
type: object
|
|
20135
|
+
properties:
|
|
20136
|
+
owner:
|
|
20137
|
+
type: string
|
|
20138
|
+
minLength: 1
|
|
20139
|
+
description: GitHub repo owner.
|
|
20140
|
+
repo:
|
|
20141
|
+
type: string
|
|
20142
|
+
minLength: 1
|
|
20143
|
+
description: GitHub repo name.
|
|
20144
|
+
baseRef:
|
|
20145
|
+
type: string
|
|
20146
|
+
minLength: 1
|
|
20147
|
+
description: Optional base ref this repo's agent task branches from. Omit for the repo's default branch.
|
|
20148
|
+
required:
|
|
20149
|
+
- owner
|
|
20150
|
+
- repo
|
|
20151
|
+
additionalProperties: false
|
|
20152
|
+
description: One repo a Copilot trigger runs against, with the base branch its tasks branch from.
|
|
18646
20153
|
CopilotTriggerConfig:
|
|
18647
20154
|
type: object
|
|
18648
20155
|
properties:
|
|
18649
20156
|
owner:
|
|
18650
20157
|
type: string
|
|
18651
20158
|
minLength: 1
|
|
18652
|
-
description: GitHub repo owner. Together with `repo` forms the connector's idempotency key (`owner/repo`).
|
|
20159
|
+
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.'
|
|
18653
20160
|
repo:
|
|
18654
20161
|
type: string
|
|
18655
20162
|
minLength: 1
|
|
@@ -18657,11 +20164,21 @@ components:
|
|
|
18657
20164
|
baseRef:
|
|
18658
20165
|
type: string
|
|
18659
20166
|
minLength: 1
|
|
18660
|
-
description: Optional base ref the agent branches from.
|
|
20167
|
+
description: Optional base ref the agent branches from. Mirrors `repos[0].baseRef`.
|
|
20168
|
+
repos:
|
|
20169
|
+
type: array
|
|
20170
|
+
minItems: 1
|
|
20171
|
+
items:
|
|
20172
|
+
$ref: '#/components/schemas/CopilotTriggerRepo'
|
|
20173
|
+
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.
|
|
18661
20174
|
projectId:
|
|
18662
20175
|
type: string
|
|
18663
20176
|
minLength: 1
|
|
18664
20177
|
description: Shipeasy project id the run targets.
|
|
20178
|
+
fireText:
|
|
20179
|
+
type: string
|
|
20180
|
+
minLength: 1
|
|
20181
|
+
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.
|
|
18665
20182
|
required:
|
|
18666
20183
|
- owner
|
|
18667
20184
|
- repo
|
|
@@ -18719,6 +20236,10 @@ components:
|
|
|
18719
20236
|
type: string
|
|
18720
20237
|
minLength: 1
|
|
18721
20238
|
description: Shipeasy project id the run targets.
|
|
20239
|
+
fireText:
|
|
20240
|
+
type: string
|
|
20241
|
+
minLength: 1
|
|
20242
|
+
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.
|
|
18722
20243
|
required:
|
|
18723
20244
|
- source
|
|
18724
20245
|
- projectId
|
|
@@ -18918,7 +20439,7 @@ components:
|
|
|
18918
20439
|
- provider
|
|
18919
20440
|
- config
|
|
18920
20441
|
additionalProperties: false
|
|
18921
|
-
description: Per-provider PATCH body for editing an existing `cursor_trigger` connector. `config` replaces the stored config wholesale
|
|
20442
|
+
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).'
|
|
18922
20443
|
UpdateCopilotTriggerRequest:
|
|
18923
20444
|
type: object
|
|
18924
20445
|
properties:
|
|
@@ -19044,6 +20565,11 @@ components:
|
|
|
19044
20565
|
- type: string
|
|
19045
20566
|
- type: 'null'
|
|
19046
20567
|
description: Human label for the key. `null` for unnamed dashboard mints; programmatic mints auto-name themselves.
|
|
20568
|
+
description:
|
|
20569
|
+
anyOf:
|
|
20570
|
+
- type: string
|
|
20571
|
+
- type: 'null'
|
|
20572
|
+
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}`.
|
|
19047
20573
|
scopes:
|
|
19048
20574
|
anyOf:
|
|
19049
20575
|
- type: array
|
|
@@ -19056,6 +20582,14 @@ components:
|
|
|
19056
20582
|
- type: string
|
|
19057
20583
|
- type: 'null'
|
|
19058
20584
|
description: Last 4 characters of the raw token, so the dashboard mask is matchable against the held key. `null` for keys minted before this column.
|
|
20585
|
+
origin:
|
|
20586
|
+
type: string
|
|
20587
|
+
enum:
|
|
20588
|
+
- cli
|
|
20589
|
+
- mobile
|
|
20590
|
+
- dashboard
|
|
20591
|
+
- api
|
|
20592
|
+
description: Where the key was minted. `cli` (a signed-in CLI session from device auth), `mobile` (a mobile app login), `dashboard` (the "New API key" dialog) or `api` (minted with another key — CLI, MCP, agents). Set at mint time; keys that predate the column were backfilled from their label, defaulting to `dashboard`.
|
|
19059
20593
|
required:
|
|
19060
20594
|
- id
|
|
19061
20595
|
- type
|
|
@@ -19065,8 +20599,10 @@ components:
|
|
|
19065
20599
|
- expires_at
|
|
19066
20600
|
- created_by_email
|
|
19067
20601
|
- name
|
|
20602
|
+
- description
|
|
19068
20603
|
- scopes
|
|
19069
20604
|
- last4
|
|
20605
|
+
- origin
|
|
19070
20606
|
additionalProperties: false
|
|
19071
20607
|
ListKeysResponse:
|
|
19072
20608
|
type: object
|
|
@@ -19172,6 +20708,30 @@ components:
|
|
|
19172
20708
|
- key
|
|
19173
20709
|
- expires_at
|
|
19174
20710
|
additionalProperties: false
|
|
20711
|
+
UpdateKeyRequest:
|
|
20712
|
+
type: object
|
|
20713
|
+
description: |-
|
|
20714
|
+
Body for `PATCH /api/admin/keys/{id}`. Only the key's **label** is editable — `name` and `description`.
|
|
20715
|
+
|
|
20716
|
+
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.
|
|
20717
|
+
|
|
20718
|
+
Omitted fields are left untouched; send `null` to clear one.
|
|
20719
|
+
properties:
|
|
20720
|
+
name:
|
|
20721
|
+
anyOf:
|
|
20722
|
+
- type: string
|
|
20723
|
+
minLength: 1
|
|
20724
|
+
maxLength: 160
|
|
20725
|
+
- type: 'null'
|
|
20726
|
+
description: New human label, or `null` to clear it. Same 160-char budget as create — provenance labels are composed, not typed.
|
|
20727
|
+
description:
|
|
20728
|
+
anyOf:
|
|
20729
|
+
- type: string
|
|
20730
|
+
minLength: 1
|
|
20731
|
+
maxLength: 500
|
|
20732
|
+
- type: 'null'
|
|
20733
|
+
description: New free-text note, or `null` to clear it.
|
|
20734
|
+
additionalProperties: false
|
|
19175
20735
|
RevokeKeyResponse:
|
|
19176
20736
|
type: object
|
|
19177
20737
|
description: Confirms the key is revoked. Idempotent — revoking an already-revoked key returns the same shape.
|
|
@@ -19199,6 +20759,7 @@ components:
|
|
|
19199
20759
|
- config
|
|
19200
20760
|
- killswitch
|
|
19201
20761
|
- metric
|
|
20762
|
+
- ops
|
|
19202
20763
|
description: Resource family — drives the result group + icon in the palette. (`member` hits are surfaced first.)
|
|
19203
20764
|
id:
|
|
19204
20765
|
type: string
|
|
@@ -19232,6 +20793,85 @@ components:
|
|
|
19232
20793
|
required:
|
|
19233
20794
|
- hits
|
|
19234
20795
|
additionalProperties: false
|
|
20796
|
+
Tag:
|
|
20797
|
+
type: object
|
|
20798
|
+
properties:
|
|
20799
|
+
id:
|
|
20800
|
+
type: string
|
|
20801
|
+
description: Stable opaque tag id.
|
|
20802
|
+
name:
|
|
20803
|
+
type: string
|
|
20804
|
+
description: Display name — also the tag's identity, unique case-insensitively within the project.
|
|
20805
|
+
required:
|
|
20806
|
+
- id
|
|
20807
|
+
- name
|
|
20808
|
+
additionalProperties: false
|
|
20809
|
+
ListTagsResponse:
|
|
20810
|
+
type: array
|
|
20811
|
+
items:
|
|
20812
|
+
$ref: '#/components/schemas/Tag'
|
|
20813
|
+
description: The project's tags, sorted by name.
|
|
20814
|
+
TaggableEntityType:
|
|
20815
|
+
type: string
|
|
20816
|
+
enum:
|
|
20817
|
+
- ops
|
|
20818
|
+
- flag
|
|
20819
|
+
- config
|
|
20820
|
+
- killswitch
|
|
20821
|
+
- metric
|
|
20822
|
+
- error
|
|
20823
|
+
- alert_rule
|
|
20824
|
+
- experiment
|
|
20825
|
+
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`.'
|
|
20826
|
+
EntityTagsResponse:
|
|
20827
|
+
type: object
|
|
20828
|
+
properties:
|
|
20829
|
+
entityType:
|
|
20830
|
+
$ref: '#/components/schemas/TaggableEntityType'
|
|
20831
|
+
entityId:
|
|
20832
|
+
type: string
|
|
20833
|
+
description: The item's canonical id (the handle you passed, resolved).
|
|
20834
|
+
tags:
|
|
20835
|
+
type: array
|
|
20836
|
+
items:
|
|
20837
|
+
type: string
|
|
20838
|
+
description: The tag names now attached to the item, sorted by name.
|
|
20839
|
+
required:
|
|
20840
|
+
- entityType
|
|
20841
|
+
- entityId
|
|
20842
|
+
- tags
|
|
20843
|
+
additionalProperties: false
|
|
20844
|
+
SetEntityTagsRequest:
|
|
20845
|
+
type: object
|
|
20846
|
+
properties:
|
|
20847
|
+
tags:
|
|
20848
|
+
type: array
|
|
20849
|
+
maxItems: 50
|
|
20850
|
+
items:
|
|
20851
|
+
$ref: '#/components/schemas/TagName'
|
|
20852
|
+
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.
|
|
20853
|
+
required:
|
|
20854
|
+
- tags
|
|
20855
|
+
additionalProperties: false
|
|
20856
|
+
UpdateEntityTagsRequest:
|
|
20857
|
+
type: object
|
|
20858
|
+
properties:
|
|
20859
|
+
add:
|
|
20860
|
+
type: array
|
|
20861
|
+
maxItems: 50
|
|
20862
|
+
items:
|
|
20863
|
+
$ref: '#/components/schemas/TagName'
|
|
20864
|
+
default: []
|
|
20865
|
+
description: Tag names to attach (get-or-created by name, case-insensitive). Already-attached names are a no-op.
|
|
20866
|
+
remove:
|
|
20867
|
+
type: array
|
|
20868
|
+
maxItems: 50
|
|
20869
|
+
items:
|
|
20870
|
+
$ref: '#/components/schemas/TagName'
|
|
20871
|
+
default: []
|
|
20872
|
+
description: Tag names to detach (case-insensitive). Names the item doesn't carry are a no-op. A name in both lists is removed.
|
|
20873
|
+
additionalProperties: false
|
|
20874
|
+
description: Incremental tag edit — pass `add`, `remove`, or both. Every other tag on the item is left as is.
|
|
19235
20875
|
responses:
|
|
19236
20876
|
BadRequest:
|
|
19237
20877
|
description: The request was malformed (bad JSON or missing project scope).
|