@shipeasy/openapi 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-RTN572TI.js → chunk-75Z4SQOM.js} +75 -1
  3. package/dist/chunk-75Z4SQOM.js.map +1 -0
  4. package/dist/{chunk-DW33MG4B.js → chunk-ZYK74ZIW.js} +426 -121
  5. package/dist/chunk-ZYK74ZIW.js.map +1 -0
  6. package/dist/{client-BPVn4hMC.d.ts → client-DAGqRpF1.d.ts} +1362 -238
  7. package/dist/client.d.ts +1 -1
  8. package/dist/client.js +19 -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 +20 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/schemas.d.ts +1648 -907
  16. package/dist/schemas.js +113 -1
  17. package/openapi-sdk.json +31 -9
  18. package/openapi.json +4040 -2083
  19. package/openapi.yaml +1775 -408
  20. package/package.json +1 -1
  21. package/spec/components/schemas/alert-rules.yaml +405 -7
  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 +30 -0
  27. package/spec/components/schemas/metrics.yaml +131 -251
  28. package/spec/components/schemas/ops.yaml +377 -29
  29. package/spec/components/schemas/projects.yaml +18 -0
  30. package/spec/components/schemas/tags.yaml +91 -0
  31. package/spec/openapi.yaml +43 -0
  32. package/spec/paths/alerts.yaml +5 -3
  33. package/spec/paths/i18n.yaml +2 -1
  34. package/spec/paths/keys.yaml +79 -0
  35. package/spec/paths/metrics.yaml +26 -17
  36. package/spec/paths/ops.yaml +388 -11
  37. package/spec/paths/tags.yaml +270 -0
  38. package/dist/chunk-DW33MG4B.js.map +0 -1
  39. package/dist/chunk-RTN572TI.js.map +0 -1
package/dist/schemas.js CHANGED
@@ -11,13 +11,29 @@ import {
11
11
  zAddToGateWhitelistRequest,
12
12
  zAddToGateWhitelistResponse,
13
13
  zAlertApiRow,
14
+ zAlertCompositeSpec,
15
+ zAnswerOpsQuestionBody,
16
+ zAnswerOpsQuestionHeaders,
17
+ zAnswerOpsQuestionPath,
18
+ zAnswerOpsQuestionRequest,
19
+ zAnswerOpsQuestionResponse,
14
20
  zApproveEventBody,
15
21
  zApproveEventHeaders,
16
22
  zApproveEventPath,
17
23
  zApproveEventRequest,
18
24
  zApproveEventResponse,
19
25
  zApproveEventResponse2,
26
+ zAskOpsQuestionInput,
27
+ zAskOpsQuestionsBody,
28
+ zAskOpsQuestionsHeaders,
29
+ zAskOpsQuestionsPath,
30
+ zAskOpsQuestionsRequest,
31
+ zAskOpsQuestionsResponse,
32
+ zAskOpsQuestionsResponse2,
20
33
  zAttributeType,
34
+ zCancelOpsQuestionHeaders,
35
+ zCancelOpsQuestionPath,
36
+ zCancelOpsQuestionResponse,
21
37
  zClaudeTriggerConfig,
22
38
  zConfigName,
23
39
  zConnectorData,
@@ -25,6 +41,7 @@ import {
25
41
  zConnectorProvider,
26
42
  zConnectorRecord,
27
43
  zCopilotTriggerConfig,
44
+ zCopilotTriggerRepo,
28
45
  zCreateAlertRuleBody,
29
46
  zCreateAlertRuleHeaders,
30
47
  zCreateAlertRuleRequest,
@@ -137,6 +154,7 @@ import {
137
154
  zCreateUniverseResponse,
138
155
  zCreateUniverseResponse2,
139
156
  zCursorTriggerConfig,
157
+ zCursorTriggerRepo,
140
158
  zDeleteAlertRuleHeaders,
141
159
  zDeleteAlertRulePath,
142
160
  zDeleteAlertRuleResponse,
@@ -209,6 +227,7 @@ import {
209
227
  zEnableGatePath,
210
228
  zEnableGateResponse,
211
229
  zEnableGateResponse2,
230
+ zEntityTagsResponse,
212
231
  zEnv,
213
232
  zError,
214
233
  zErrorCode,
@@ -253,6 +272,9 @@ import {
253
272
  zGetCurrentProjectHeaders,
254
273
  zGetCurrentProjectResponse,
255
274
  zGetCurrentProjectResponse2,
275
+ zGetEntityTagsHeaders,
276
+ zGetEntityTagsPath,
277
+ zGetEntityTagsResponse,
256
278
  zGetErrorHeaders,
257
279
  zGetErrorPath,
258
280
  zGetErrorResponse,
@@ -421,9 +443,18 @@ import {
421
443
  zListOpsItemsQuery,
422
444
  zListOpsItemsResponse,
423
445
  zListOpsItemsResponse2,
446
+ zListOpsQuestionsHeaders,
447
+ zListOpsQuestionsPath,
448
+ zListOpsQuestionsQuery,
449
+ zListOpsQuestionsResponse,
450
+ zListOpsQuestionsResponse2,
424
451
  zListSlackChannelsHeaders,
425
452
  zListSlackChannelsResponse,
426
453
  zListSlackChannelsResponse2,
454
+ zListTagsHeaders,
455
+ zListTagsQuery,
456
+ zListTagsResponse,
457
+ zListTagsResponse2,
427
458
  zListUniversesHeaders,
428
459
  zListUniversesQuery,
429
460
  zListUniversesResponse,
@@ -432,6 +463,8 @@ import {
432
463
  zMeasurePlanStep,
433
464
  zMetricDefaultMinEffectOfInterest,
434
465
  zMetricDirection,
466
+ zMetricDisplayConfig,
467
+ zMetricDisplayName,
435
468
  zMetricDisplayUnit,
436
469
  zMetricEventName,
437
470
  zMetricName,
@@ -463,6 +496,11 @@ import {
463
496
  zOpsItemRelated,
464
497
  zOpsItemStatus,
465
498
  zOpsMeasurePlanContext,
499
+ zOpsQuestion,
500
+ zOpsQuestionAnswer,
501
+ zOpsQuestionDelivery,
502
+ zOpsQuestionOption,
503
+ zOpsQuestionStatus,
466
504
  zOpsRun,
467
505
  zOpsRunAction,
468
506
  zOpsRunActionOrNull,
@@ -516,6 +554,11 @@ import {
516
554
  zSearchResourcesQuery,
517
555
  zSearchResourcesResponse,
518
556
  zSearchResponse,
557
+ zSetEntityTagsBody,
558
+ zSetEntityTagsHeaders,
559
+ zSetEntityTagsPath,
560
+ zSetEntityTagsRequest,
561
+ zSetEntityTagsResponse,
519
562
  zSetExperimentMetricsBody,
520
563
  zSetExperimentMetricsHeaders,
521
564
  zSetExperimentMetricsPath,
@@ -551,6 +594,9 @@ import {
551
594
  zSetKillswitchValueResponse,
552
595
  zSetKillswitchValueResponse2,
553
596
  zSlackConnectorData,
597
+ zTag,
598
+ zTagName,
599
+ zTaggableEntityType,
554
600
  zTestConnectorHeaders,
555
601
  zTestConnectorPath,
556
602
  zTestConnectorResponse,
@@ -612,6 +658,11 @@ import {
612
658
  zUpdateConnectorResponse2,
613
659
  zUpdateCopilotTriggerRequest,
614
660
  zUpdateCursorTriggerRequest,
661
+ zUpdateEntityTagsBody,
662
+ zUpdateEntityTagsHeaders,
663
+ zUpdateEntityTagsPath,
664
+ zUpdateEntityTagsRequest,
665
+ zUpdateEntityTagsResponse,
615
666
  zUpdateErrorStatusBody,
616
667
  zUpdateErrorStatusHeaders,
617
668
  zUpdateErrorStatusPath,
@@ -654,6 +705,11 @@ import {
654
705
  zUpdateI18nKeyResponse,
655
706
  zUpdateI18nKeyResponse2,
656
707
  zUpdateJulesTriggerRequest,
708
+ zUpdateKeyBody,
709
+ zUpdateKeyHeaders,
710
+ zUpdateKeyPath,
711
+ zUpdateKeyRequest,
712
+ zUpdateKeyResponse,
657
713
  zUpdateKillswitchBody,
658
714
  zUpdateKillswitchHeaders,
659
715
  zUpdateKillswitchPath,
@@ -711,7 +767,7 @@ import {
711
767
  zUpsertProjectRequest,
712
768
  zUpsertProjectResponse,
713
769
  zUpsertProjectResponse2
714
- } from "./chunk-DW33MG4B.js";
770
+ } from "./chunk-ZYK74ZIW.js";
715
771
  export {
716
772
  zAckOpsItemBody,
717
773
  zAckOpsItemHeaders,
@@ -725,13 +781,29 @@ export {
725
781
  zAddToGateWhitelistRequest,
726
782
  zAddToGateWhitelistResponse,
727
783
  zAlertApiRow,
784
+ zAlertCompositeSpec,
785
+ zAnswerOpsQuestionBody,
786
+ zAnswerOpsQuestionHeaders,
787
+ zAnswerOpsQuestionPath,
788
+ zAnswerOpsQuestionRequest,
789
+ zAnswerOpsQuestionResponse,
728
790
  zApproveEventBody,
729
791
  zApproveEventHeaders,
730
792
  zApproveEventPath,
731
793
  zApproveEventRequest,
732
794
  zApproveEventResponse,
733
795
  zApproveEventResponse2,
796
+ zAskOpsQuestionInput,
797
+ zAskOpsQuestionsBody,
798
+ zAskOpsQuestionsHeaders,
799
+ zAskOpsQuestionsPath,
800
+ zAskOpsQuestionsRequest,
801
+ zAskOpsQuestionsResponse,
802
+ zAskOpsQuestionsResponse2,
734
803
  zAttributeType,
804
+ zCancelOpsQuestionHeaders,
805
+ zCancelOpsQuestionPath,
806
+ zCancelOpsQuestionResponse,
735
807
  zClaudeTriggerConfig,
736
808
  zConfigName,
737
809
  zConnectorData,
@@ -739,6 +811,7 @@ export {
739
811
  zConnectorProvider,
740
812
  zConnectorRecord,
741
813
  zCopilotTriggerConfig,
814
+ zCopilotTriggerRepo,
742
815
  zCreateAlertRuleBody,
743
816
  zCreateAlertRuleHeaders,
744
817
  zCreateAlertRuleRequest,
@@ -851,6 +924,7 @@ export {
851
924
  zCreateUniverseResponse,
852
925
  zCreateUniverseResponse2,
853
926
  zCursorTriggerConfig,
927
+ zCursorTriggerRepo,
854
928
  zDeleteAlertRuleHeaders,
855
929
  zDeleteAlertRulePath,
856
930
  zDeleteAlertRuleResponse,
@@ -923,6 +997,7 @@ export {
923
997
  zEnableGatePath,
924
998
  zEnableGateResponse,
925
999
  zEnableGateResponse2,
1000
+ zEntityTagsResponse,
926
1001
  zEnv,
927
1002
  zError,
928
1003
  zErrorCode,
@@ -967,6 +1042,9 @@ export {
967
1042
  zGetCurrentProjectHeaders,
968
1043
  zGetCurrentProjectResponse,
969
1044
  zGetCurrentProjectResponse2,
1045
+ zGetEntityTagsHeaders,
1046
+ zGetEntityTagsPath,
1047
+ zGetEntityTagsResponse,
970
1048
  zGetErrorHeaders,
971
1049
  zGetErrorPath,
972
1050
  zGetErrorResponse,
@@ -1135,9 +1213,18 @@ export {
1135
1213
  zListOpsItemsQuery,
1136
1214
  zListOpsItemsResponse,
1137
1215
  zListOpsItemsResponse2,
1216
+ zListOpsQuestionsHeaders,
1217
+ zListOpsQuestionsPath,
1218
+ zListOpsQuestionsQuery,
1219
+ zListOpsQuestionsResponse,
1220
+ zListOpsQuestionsResponse2,
1138
1221
  zListSlackChannelsHeaders,
1139
1222
  zListSlackChannelsResponse,
1140
1223
  zListSlackChannelsResponse2,
1224
+ zListTagsHeaders,
1225
+ zListTagsQuery,
1226
+ zListTagsResponse,
1227
+ zListTagsResponse2,
1141
1228
  zListUniversesHeaders,
1142
1229
  zListUniversesQuery,
1143
1230
  zListUniversesResponse,
@@ -1146,6 +1233,8 @@ export {
1146
1233
  zMeasurePlanStep,
1147
1234
  zMetricDefaultMinEffectOfInterest,
1148
1235
  zMetricDirection,
1236
+ zMetricDisplayConfig,
1237
+ zMetricDisplayName,
1149
1238
  zMetricDisplayUnit,
1150
1239
  zMetricEventName,
1151
1240
  zMetricName,
@@ -1177,6 +1266,11 @@ export {
1177
1266
  zOpsItemRelated,
1178
1267
  zOpsItemStatus,
1179
1268
  zOpsMeasurePlanContext,
1269
+ zOpsQuestion,
1270
+ zOpsQuestionAnswer,
1271
+ zOpsQuestionDelivery,
1272
+ zOpsQuestionOption,
1273
+ zOpsQuestionStatus,
1180
1274
  zOpsRun,
1181
1275
  zOpsRunAction,
1182
1276
  zOpsRunActionOrNull,
@@ -1230,6 +1324,11 @@ export {
1230
1324
  zSearchResourcesQuery,
1231
1325
  zSearchResourcesResponse,
1232
1326
  zSearchResponse,
1327
+ zSetEntityTagsBody,
1328
+ zSetEntityTagsHeaders,
1329
+ zSetEntityTagsPath,
1330
+ zSetEntityTagsRequest,
1331
+ zSetEntityTagsResponse,
1233
1332
  zSetExperimentMetricsBody,
1234
1333
  zSetExperimentMetricsHeaders,
1235
1334
  zSetExperimentMetricsPath,
@@ -1265,6 +1364,9 @@ export {
1265
1364
  zSetKillswitchValueResponse,
1266
1365
  zSetKillswitchValueResponse2,
1267
1366
  zSlackConnectorData,
1367
+ zTag,
1368
+ zTagName,
1369
+ zTaggableEntityType,
1268
1370
  zTestConnectorHeaders,
1269
1371
  zTestConnectorPath,
1270
1372
  zTestConnectorResponse,
@@ -1326,6 +1428,11 @@ export {
1326
1428
  zUpdateConnectorResponse2,
1327
1429
  zUpdateCopilotTriggerRequest,
1328
1430
  zUpdateCursorTriggerRequest,
1431
+ zUpdateEntityTagsBody,
1432
+ zUpdateEntityTagsHeaders,
1433
+ zUpdateEntityTagsPath,
1434
+ zUpdateEntityTagsRequest,
1435
+ zUpdateEntityTagsResponse,
1329
1436
  zUpdateErrorStatusBody,
1330
1437
  zUpdateErrorStatusHeaders,
1331
1438
  zUpdateErrorStatusPath,
@@ -1368,6 +1475,11 @@ export {
1368
1475
  zUpdateI18nKeyResponse,
1369
1476
  zUpdateI18nKeyResponse2,
1370
1477
  zUpdateJulesTriggerRequest,
1478
+ zUpdateKeyBody,
1479
+ zUpdateKeyHeaders,
1480
+ zUpdateKeyPath,
1481
+ zUpdateKeyRequest,
1482
+ zUpdateKeyResponse,
1371
1483
  zUpdateKillswitchBody,
1372
1484
  zUpdateKillswitchHeaders,
1373
1485
  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",