@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.
Files changed (40) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-RTN572TI.js → chunk-JJA7XEPU.js} +91 -1
  3. package/dist/chunk-JJA7XEPU.js.map +1 -0
  4. package/dist/{chunk-DW33MG4B.js → chunk-Z3CY5Y44.js} +514 -126
  5. package/dist/chunk-Z3CY5Y44.js.map +1 -0
  6. package/dist/{client-BPVn4hMC.d.ts → client-CkRbr8I2.d.ts} +1544 -212
  7. package/dist/client.d.ts +1 -1
  8. package/dist/client.js +23 -1
  9. package/dist/custom.d.ts +5 -5
  10. package/dist/custom.js +128 -84
  11. package/dist/custom.js.map +1 -1
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.js +24 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/schemas.d.ts +1935 -963
  16. package/dist/schemas.js +141 -1
  17. package/openapi-sdk.json +31 -9
  18. package/openapi.json +10449 -8118
  19. package/openapi.yaml +2274 -634
  20. package/package.json +1 -1
  21. package/spec/components/schemas/alert-rules.yaml +434 -10
  22. package/spec/components/schemas/alerts.yaml +9 -7
  23. package/spec/components/schemas/common.yaml +2 -2
  24. package/spec/components/schemas/connectors.yaml +69 -6
  25. package/spec/components/schemas/events.yaml +20 -9
  26. package/spec/components/schemas/keys.yaml +39 -0
  27. package/spec/components/schemas/metrics.yaml +131 -251
  28. package/spec/components/schemas/ops.yaml +471 -29
  29. package/spec/components/schemas/projects.yaml +18 -0
  30. package/spec/components/schemas/search.yaml +1 -0
  31. package/spec/components/schemas/tags.yaml +91 -0
  32. package/spec/openapi.yaml +56 -0
  33. package/spec/paths/alerts.yaml +5 -3
  34. package/spec/paths/i18n.yaml +2 -1
  35. package/spec/paths/keys.yaml +79 -0
  36. package/spec/paths/metrics.yaml +26 -17
  37. package/spec/paths/ops.yaml +514 -11
  38. package/spec/paths/tags.yaml +270 -0
  39. package/dist/chunk-DW33MG4B.js.map +0 -1
  40. package/dist/chunk-RTN572TI.js.map +0 -1
package/dist/schemas.js CHANGED
@@ -11,13 +11,30 @@ import {
11
11
  zAddToGateWhitelistRequest,
12
12
  zAddToGateWhitelistResponse,
13
13
  zAlertApiRow,
14
+ zAlertCompositeSpec,
15
+ zAlertRuleNotify,
16
+ zAnswerOpsQuestionBody,
17
+ zAnswerOpsQuestionHeaders,
18
+ zAnswerOpsQuestionPath,
19
+ zAnswerOpsQuestionRequest,
20
+ zAnswerOpsQuestionResponse,
14
21
  zApproveEventBody,
15
22
  zApproveEventHeaders,
16
23
  zApproveEventPath,
17
24
  zApproveEventRequest,
18
25
  zApproveEventResponse,
19
26
  zApproveEventResponse2,
27
+ zAskOpsQuestionInput,
28
+ zAskOpsQuestionsBody,
29
+ zAskOpsQuestionsHeaders,
30
+ zAskOpsQuestionsPath,
31
+ zAskOpsQuestionsRequest,
32
+ zAskOpsQuestionsResponse,
33
+ zAskOpsQuestionsResponse2,
20
34
  zAttributeType,
35
+ zCancelOpsQuestionHeaders,
36
+ zCancelOpsQuestionPath,
37
+ zCancelOpsQuestionResponse,
21
38
  zClaudeTriggerConfig,
22
39
  zConfigName,
23
40
  zConnectorData,
@@ -25,6 +42,7 @@ import {
25
42
  zConnectorProvider,
26
43
  zConnectorRecord,
27
44
  zCopilotTriggerConfig,
45
+ zCopilotTriggerRepo,
28
46
  zCreateAlertRuleBody,
29
47
  zCreateAlertRuleHeaders,
30
48
  zCreateAlertRuleRequest,
@@ -120,6 +138,11 @@ import {
120
138
  zCreateOpsItemRequest,
121
139
  zCreateOpsItemResponse,
122
140
  zCreateOpsItemResponse2,
141
+ zCreateOpsQaNoteBody,
142
+ zCreateOpsQaNoteHeaders,
143
+ zCreateOpsQaNotePath,
144
+ zCreateOpsQaNoteRequest,
145
+ zCreateOpsQaNoteResponse,
123
146
  zCreatePublicBugBody,
124
147
  zCreatePublicBugRequest,
125
148
  zCreatePublicBugResponse,
@@ -137,6 +160,7 @@ import {
137
160
  zCreateUniverseResponse,
138
161
  zCreateUniverseResponse2,
139
162
  zCursorTriggerConfig,
163
+ zCursorTriggerRepo,
140
164
  zDeleteAlertRuleHeaders,
141
165
  zDeleteAlertRulePath,
142
166
  zDeleteAlertRuleResponse,
@@ -209,6 +233,7 @@ import {
209
233
  zEnableGatePath,
210
234
  zEnableGateResponse,
211
235
  zEnableGateResponse2,
236
+ zEntityTagsResponse,
212
237
  zEnv,
213
238
  zError,
214
239
  zErrorCode,
@@ -253,6 +278,9 @@ import {
253
278
  zGetCurrentProjectHeaders,
254
279
  zGetCurrentProjectResponse,
255
280
  zGetCurrentProjectResponse2,
281
+ zGetEntityTagsHeaders,
282
+ zGetEntityTagsPath,
283
+ zGetEntityTagsResponse,
256
284
  zGetErrorHeaders,
257
285
  zGetErrorPath,
258
286
  zGetErrorResponse,
@@ -421,9 +449,23 @@ import {
421
449
  zListOpsItemsQuery,
422
450
  zListOpsItemsResponse,
423
451
  zListOpsItemsResponse2,
452
+ zListOpsQaNotesHeaders,
453
+ zListOpsQaNotesPath,
454
+ zListOpsQaNotesQuery,
455
+ zListOpsQaNotesResponse,
456
+ zListOpsQaNotesResponse2,
457
+ zListOpsQuestionsHeaders,
458
+ zListOpsQuestionsPath,
459
+ zListOpsQuestionsQuery,
460
+ zListOpsQuestionsResponse,
461
+ zListOpsQuestionsResponse2,
424
462
  zListSlackChannelsHeaders,
425
463
  zListSlackChannelsResponse,
426
464
  zListSlackChannelsResponse2,
465
+ zListTagsHeaders,
466
+ zListTagsQuery,
467
+ zListTagsResponse,
468
+ zListTagsResponse2,
427
469
  zListUniversesHeaders,
428
470
  zListUniversesQuery,
429
471
  zListUniversesResponse,
@@ -432,6 +474,8 @@ import {
432
474
  zMeasurePlanStep,
433
475
  zMetricDefaultMinEffectOfInterest,
434
476
  zMetricDirection,
477
+ zMetricDisplayConfig,
478
+ zMetricDisplayName,
435
479
  zMetricDisplayUnit,
436
480
  zMetricEventName,
437
481
  zMetricName,
@@ -463,6 +507,14 @@ import {
463
507
  zOpsItemRelated,
464
508
  zOpsItemStatus,
465
509
  zOpsMeasurePlanContext,
510
+ zOpsQaNote,
511
+ zOpsQaNoteKind,
512
+ zOpsQaNoteVerdict,
513
+ zOpsQuestion,
514
+ zOpsQuestionAnswer,
515
+ zOpsQuestionDelivery,
516
+ zOpsQuestionOption,
517
+ zOpsQuestionStatus,
466
518
  zOpsRun,
467
519
  zOpsRunAction,
468
520
  zOpsRunActionOrNull,
@@ -516,6 +568,11 @@ import {
516
568
  zSearchResourcesQuery,
517
569
  zSearchResourcesResponse,
518
570
  zSearchResponse,
571
+ zSetEntityTagsBody,
572
+ zSetEntityTagsHeaders,
573
+ zSetEntityTagsPath,
574
+ zSetEntityTagsRequest,
575
+ zSetEntityTagsResponse,
519
576
  zSetExperimentMetricsBody,
520
577
  zSetExperimentMetricsHeaders,
521
578
  zSetExperimentMetricsPath,
@@ -551,6 +608,9 @@ import {
551
608
  zSetKillswitchValueResponse,
552
609
  zSetKillswitchValueResponse2,
553
610
  zSlackConnectorData,
611
+ zTag,
612
+ zTagName,
613
+ zTaggableEntityType,
554
614
  zTestConnectorHeaders,
555
615
  zTestConnectorPath,
556
616
  zTestConnectorResponse,
@@ -612,6 +672,11 @@ import {
612
672
  zUpdateConnectorResponse2,
613
673
  zUpdateCopilotTriggerRequest,
614
674
  zUpdateCursorTriggerRequest,
675
+ zUpdateEntityTagsBody,
676
+ zUpdateEntityTagsHeaders,
677
+ zUpdateEntityTagsPath,
678
+ zUpdateEntityTagsRequest,
679
+ zUpdateEntityTagsResponse,
615
680
  zUpdateErrorStatusBody,
616
681
  zUpdateErrorStatusHeaders,
617
682
  zUpdateErrorStatusPath,
@@ -654,6 +719,11 @@ import {
654
719
  zUpdateI18nKeyResponse,
655
720
  zUpdateI18nKeyResponse2,
656
721
  zUpdateJulesTriggerRequest,
722
+ zUpdateKeyBody,
723
+ zUpdateKeyHeaders,
724
+ zUpdateKeyPath,
725
+ zUpdateKeyRequest,
726
+ zUpdateKeyResponse,
657
727
  zUpdateKillswitchBody,
658
728
  zUpdateKillswitchHeaders,
659
729
  zUpdateKillswitchPath,
@@ -711,7 +781,7 @@ import {
711
781
  zUpsertProjectRequest,
712
782
  zUpsertProjectResponse,
713
783
  zUpsertProjectResponse2
714
- } from "./chunk-DW33MG4B.js";
784
+ } from "./chunk-Z3CY5Y44.js";
715
785
  export {
716
786
  zAckOpsItemBody,
717
787
  zAckOpsItemHeaders,
@@ -725,13 +795,30 @@ export {
725
795
  zAddToGateWhitelistRequest,
726
796
  zAddToGateWhitelistResponse,
727
797
  zAlertApiRow,
798
+ zAlertCompositeSpec,
799
+ zAlertRuleNotify,
800
+ zAnswerOpsQuestionBody,
801
+ zAnswerOpsQuestionHeaders,
802
+ zAnswerOpsQuestionPath,
803
+ zAnswerOpsQuestionRequest,
804
+ zAnswerOpsQuestionResponse,
728
805
  zApproveEventBody,
729
806
  zApproveEventHeaders,
730
807
  zApproveEventPath,
731
808
  zApproveEventRequest,
732
809
  zApproveEventResponse,
733
810
  zApproveEventResponse2,
811
+ zAskOpsQuestionInput,
812
+ zAskOpsQuestionsBody,
813
+ zAskOpsQuestionsHeaders,
814
+ zAskOpsQuestionsPath,
815
+ zAskOpsQuestionsRequest,
816
+ zAskOpsQuestionsResponse,
817
+ zAskOpsQuestionsResponse2,
734
818
  zAttributeType,
819
+ zCancelOpsQuestionHeaders,
820
+ zCancelOpsQuestionPath,
821
+ zCancelOpsQuestionResponse,
735
822
  zClaudeTriggerConfig,
736
823
  zConfigName,
737
824
  zConnectorData,
@@ -739,6 +826,7 @@ export {
739
826
  zConnectorProvider,
740
827
  zConnectorRecord,
741
828
  zCopilotTriggerConfig,
829
+ zCopilotTriggerRepo,
742
830
  zCreateAlertRuleBody,
743
831
  zCreateAlertRuleHeaders,
744
832
  zCreateAlertRuleRequest,
@@ -834,6 +922,11 @@ export {
834
922
  zCreateOpsItemRequest,
835
923
  zCreateOpsItemResponse,
836
924
  zCreateOpsItemResponse2,
925
+ zCreateOpsQaNoteBody,
926
+ zCreateOpsQaNoteHeaders,
927
+ zCreateOpsQaNotePath,
928
+ zCreateOpsQaNoteRequest,
929
+ zCreateOpsQaNoteResponse,
837
930
  zCreatePublicBugBody,
838
931
  zCreatePublicBugRequest,
839
932
  zCreatePublicBugResponse,
@@ -851,6 +944,7 @@ export {
851
944
  zCreateUniverseResponse,
852
945
  zCreateUniverseResponse2,
853
946
  zCursorTriggerConfig,
947
+ zCursorTriggerRepo,
854
948
  zDeleteAlertRuleHeaders,
855
949
  zDeleteAlertRulePath,
856
950
  zDeleteAlertRuleResponse,
@@ -923,6 +1017,7 @@ export {
923
1017
  zEnableGatePath,
924
1018
  zEnableGateResponse,
925
1019
  zEnableGateResponse2,
1020
+ zEntityTagsResponse,
926
1021
  zEnv,
927
1022
  zError,
928
1023
  zErrorCode,
@@ -967,6 +1062,9 @@ export {
967
1062
  zGetCurrentProjectHeaders,
968
1063
  zGetCurrentProjectResponse,
969
1064
  zGetCurrentProjectResponse2,
1065
+ zGetEntityTagsHeaders,
1066
+ zGetEntityTagsPath,
1067
+ zGetEntityTagsResponse,
970
1068
  zGetErrorHeaders,
971
1069
  zGetErrorPath,
972
1070
  zGetErrorResponse,
@@ -1135,9 +1233,23 @@ export {
1135
1233
  zListOpsItemsQuery,
1136
1234
  zListOpsItemsResponse,
1137
1235
  zListOpsItemsResponse2,
1236
+ zListOpsQaNotesHeaders,
1237
+ zListOpsQaNotesPath,
1238
+ zListOpsQaNotesQuery,
1239
+ zListOpsQaNotesResponse,
1240
+ zListOpsQaNotesResponse2,
1241
+ zListOpsQuestionsHeaders,
1242
+ zListOpsQuestionsPath,
1243
+ zListOpsQuestionsQuery,
1244
+ zListOpsQuestionsResponse,
1245
+ zListOpsQuestionsResponse2,
1138
1246
  zListSlackChannelsHeaders,
1139
1247
  zListSlackChannelsResponse,
1140
1248
  zListSlackChannelsResponse2,
1249
+ zListTagsHeaders,
1250
+ zListTagsQuery,
1251
+ zListTagsResponse,
1252
+ zListTagsResponse2,
1141
1253
  zListUniversesHeaders,
1142
1254
  zListUniversesQuery,
1143
1255
  zListUniversesResponse,
@@ -1146,6 +1258,8 @@ export {
1146
1258
  zMeasurePlanStep,
1147
1259
  zMetricDefaultMinEffectOfInterest,
1148
1260
  zMetricDirection,
1261
+ zMetricDisplayConfig,
1262
+ zMetricDisplayName,
1149
1263
  zMetricDisplayUnit,
1150
1264
  zMetricEventName,
1151
1265
  zMetricName,
@@ -1177,6 +1291,14 @@ export {
1177
1291
  zOpsItemRelated,
1178
1292
  zOpsItemStatus,
1179
1293
  zOpsMeasurePlanContext,
1294
+ zOpsQaNote,
1295
+ zOpsQaNoteKind,
1296
+ zOpsQaNoteVerdict,
1297
+ zOpsQuestion,
1298
+ zOpsQuestionAnswer,
1299
+ zOpsQuestionDelivery,
1300
+ zOpsQuestionOption,
1301
+ zOpsQuestionStatus,
1180
1302
  zOpsRun,
1181
1303
  zOpsRunAction,
1182
1304
  zOpsRunActionOrNull,
@@ -1230,6 +1352,11 @@ export {
1230
1352
  zSearchResourcesQuery,
1231
1353
  zSearchResourcesResponse,
1232
1354
  zSearchResponse,
1355
+ zSetEntityTagsBody,
1356
+ zSetEntityTagsHeaders,
1357
+ zSetEntityTagsPath,
1358
+ zSetEntityTagsRequest,
1359
+ zSetEntityTagsResponse,
1233
1360
  zSetExperimentMetricsBody,
1234
1361
  zSetExperimentMetricsHeaders,
1235
1362
  zSetExperimentMetricsPath,
@@ -1265,6 +1392,9 @@ export {
1265
1392
  zSetKillswitchValueResponse,
1266
1393
  zSetKillswitchValueResponse2,
1267
1394
  zSlackConnectorData,
1395
+ zTag,
1396
+ zTagName,
1397
+ zTaggableEntityType,
1268
1398
  zTestConnectorHeaders,
1269
1399
  zTestConnectorPath,
1270
1400
  zTestConnectorResponse,
@@ -1326,6 +1456,11 @@ export {
1326
1456
  zUpdateConnectorResponse2,
1327
1457
  zUpdateCopilotTriggerRequest,
1328
1458
  zUpdateCursorTriggerRequest,
1459
+ zUpdateEntityTagsBody,
1460
+ zUpdateEntityTagsHeaders,
1461
+ zUpdateEntityTagsPath,
1462
+ zUpdateEntityTagsRequest,
1463
+ zUpdateEntityTagsResponse,
1329
1464
  zUpdateErrorStatusBody,
1330
1465
  zUpdateErrorStatusHeaders,
1331
1466
  zUpdateErrorStatusPath,
@@ -1368,6 +1503,11 @@ export {
1368
1503
  zUpdateI18nKeyResponse,
1369
1504
  zUpdateI18nKeyResponse2,
1370
1505
  zUpdateJulesTriggerRequest,
1506
+ zUpdateKeyBody,
1507
+ zUpdateKeyHeaders,
1508
+ zUpdateKeyPath,
1509
+ zUpdateKeyRequest,
1510
+ zUpdateKeyResponse,
1371
1511
  zUpdateKillswitchBody,
1372
1512
  zUpdateKillswitchHeaders,
1373
1513
  zUpdateKillswitchPath,
package/openapi-sdk.json CHANGED
@@ -47,7 +47,7 @@
47
47
  "post": {
48
48
  "operationId": "createPublicBug",
49
49
  "summary": "File a bug",
50
- "description": "Files one bug onto a project's queue, awaiting human approval. This is the **public** intake: it authenticates with a *client* SDK key rather than an admin key, so it can be called from a CLI, an installer script, a devtools overlay, or any shipped code — the same places a client key already lives.\n\nThree gates decide whether a ticket is filed, and nothing else the caller sends can widen them:\n\n1. the key is a `client` key carrying the `tickets:public_create` scope,\n2. the key's project has public ticket creation enabled, and\n3. the item is filed as `pending_approval` — parked out of the work queue until a human promotes it in the dashboard.\n\nThe 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.\n\nThis endpoint is served by the Shipeasy **edge worker** (`api.shipeasy.ai`), not the admin API — see `servers` below.\n\n**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\": \"…\" }`.",
50
+ "description": "Files one bug onto a project's queue, awaiting human approval. This is the **public** intake: it authenticates with a *client* SDK key rather than an admin key, so it can be called from a CLI, an installer script, a devtools overlay, or any shipped code — the same places a client key already lives.\n\nThree gates decide whether a ticket is filed, and nothing else the caller sends can widen them:\n\n1. the key is a `client` key carrying the `tickets:public_create` scope,\n2. the key's project has public ticket creation enabled, and\n3. the item is filed as `pending_approval` — parked out of the work queue until a human promotes it in the dashboard.\n\nThe 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.\n\nSend 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.\n\nThis endpoint is served by the Shipeasy **edge worker** (`api.shipeasy.ai`), not the admin API — see `servers` below.\n\n**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\": \"…\" }`.",
51
51
  "tags": [
52
52
  "Ops"
53
53
  ],
@@ -160,7 +160,7 @@
160
160
  "post": {
161
161
  "operationId": "createPublicFeatureRequest",
162
162
  "summary": "File a feature request",
163
- "description": "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.\n\nThe 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.\n\nThis endpoint is served by the Shipeasy **edge worker** (`api.shipeasy.ai`), not the admin API — see `servers` below.\n\n**Use case:** An in-product \"request a feature\" form posts what the user asked for — `{ \"title\": \"Dark mode\", \"useCase\": \"Reduce eye strain at night\" }`.",
163
+ "description": "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.\n\nThe 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.\n\nThis endpoint is served by the Shipeasy **edge worker** (`api.shipeasy.ai`), not the admin API — see `servers` below.\n\n**Use case:** An in-product \"request a feature\" form posts what the user asked for — `{ \"title\": \"Dark mode\", \"useCase\": \"Reduce eye strain at night\" }`.",
164
164
  "tags": [
165
165
  "Ops"
166
166
  ],
@@ -816,6 +816,12 @@
816
816
  ],
817
817
  "description": "Lifecycle status of a queue item. The working flow is `open` → `in_progress` → `ready_for_qa` → `resolved` (or `wont_fix`, terminal from any earlier stage). `blocked` marks an item that can't progress until an external dependency clears — a working state a human sets and clears. `ready_for_qa` is what a developer sets once a fix lands; `resolved` is the QA sign-off, normally flipped in the dashboard after verification — set it directly from code only when the fix has been verified end-to-end. `investigating_by_ai` is a system-owned display state — set when the AI agent (Jarvis) picks an item up to investigate, never chosen by a human — so it is shown but not offered as a manual choice. `pending_approval` is the one human-gated holding state: it parks an item OUT of the work queue until a human promotes it to `open` in the dashboard, so `GET /api/admin/ops` excludes it under `status=all`/default and returns it only when requested as an exact `status`. It covers untriaged inbound that must never be auto-implemented — connector requests filed from a customer's connectors panel, and questions funnelled in from the \"Stuck in onboarding?\" assistant — where approving means flipping the status to `open`. Two earlier values were removed in favour of this single gate: `triage` (the onboarding-help bucket, now `pending_approval`) and `triaged` (a redundant \"looked at but not started\" step, now plain `open`)."
818
818
  },
819
+ "TagName": {
820
+ "type": "string",
821
+ "minLength": 1,
822
+ "maxLength": 64,
823
+ "description": "A tag name. Trimmed; matched case-insensitively against the project's existing tags."
824
+ },
819
825
  "NotificationTarget": {
820
826
  "anyOf": [
821
827
  {
@@ -935,11 +941,12 @@
935
941
  },
936
942
  "tags": {
937
943
  "type": "array",
944
+ "maxItems": 50,
938
945
  "items": {
939
- "type": "string"
946
+ "$ref": "#/components/schemas/TagName"
940
947
  },
941
948
  "default": [],
942
- "description": "Tag names to attach at creation (get-or-created by name, deduped case-insensitively)."
949
+ "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."
943
950
  },
944
951
  "reporterEmail": {
945
952
  "anyOf": [
@@ -1001,6 +1008,11 @@
1001
1008
  ],
1002
1009
  "description": "Arbitrary capture context, or `null`."
1003
1010
  },
1011
+ "dedupKey": {
1012
+ "type": "string",
1013
+ "maxLength": 200,
1014
+ "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."
1015
+ },
1004
1016
  "notify": {
1005
1017
  "anyOf": [
1006
1018
  {
@@ -1017,7 +1029,7 @@
1017
1029
  "title"
1018
1030
  ],
1019
1031
  "additionalProperties": false,
1020
- "description": "Body for `POST /ops/bug`. The same bug fields as `CreateBugRequest`, minus the `type` discriminator — the path already says what is being filed."
1032
+ "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`."
1021
1033
  },
1022
1034
  "CreatePublicTicketResponse": {
1023
1035
  "type": "object",
@@ -1033,13 +1045,17 @@
1033
1045
  "deduped": {
1034
1046
  "type": "boolean",
1035
1047
  "description": "`true` when an open ticket already tracked this report and nothing was filed (HTTP 200). Absent on a fresh file (HTTP 201)."
1048
+ },
1049
+ "updated": {
1050
+ "type": "boolean",
1051
+ "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."
1036
1052
  }
1037
1053
  },
1038
1054
  "required": [
1039
1055
  "number"
1040
1056
  ],
1041
1057
  "additionalProperties": false,
1042
- "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`."
1058
+ "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."
1043
1059
  },
1044
1060
  "ErrorCode": {
1045
1061
  "type": "string",
@@ -1199,11 +1215,12 @@
1199
1215
  },
1200
1216
  "tags": {
1201
1217
  "type": "array",
1218
+ "maxItems": 50,
1202
1219
  "items": {
1203
- "type": "string"
1220
+ "$ref": "#/components/schemas/TagName"
1204
1221
  },
1205
1222
  "default": [],
1206
- "description": "Tag names to attach at creation (get-or-created by name, deduped case-insensitively)."
1223
+ "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."
1207
1224
  },
1208
1225
  "reporterEmail": {
1209
1226
  "anyOf": [
@@ -1253,6 +1270,11 @@
1253
1270
  ],
1254
1271
  "description": "Arbitrary capture context, or `null`."
1255
1272
  },
1273
+ "dedupKey": {
1274
+ "type": "string",
1275
+ "maxLength": 200,
1276
+ "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."
1277
+ },
1256
1278
  "notify": {
1257
1279
  "anyOf": [
1258
1280
  {
@@ -1269,7 +1291,7 @@
1269
1291
  "title"
1270
1292
  ],
1271
1293
  "additionalProperties": false,
1272
- "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."
1294
+ "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`."
1273
1295
  },
1274
1296
  "ResourceId": {
1275
1297
  "type": "string",