@shipeasy/openapi 2.5.0 → 3.1.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/openapi.json CHANGED
@@ -124,12 +124,12 @@
124
124
  },
125
125
  {
126
126
  "name": "i18n",
127
- "description": "String Manager (i18n): the worker-safe REST surface — locale profiles, the\ninsert-only key push, single-key overwrite, chunk publish, and the read-only\nkey/draft listings.\n\nThe fs/AST parts (scan, validate, install-loader, codemod) are NOT part of\nthis API — they stay in the fs-having CLI/MCP."
127
+ "description": "String Manager (i18n): the worker-safe REST surface — locale profiles, the\ninsert-only key push, single-key overwrite, profile publish, and the read-only\nkey/draft listings.\n\nThe fs/AST parts (scan, validate, install-loader, codemod) are NOT part of\nthis API — they stay in the fs-having CLI/MCP."
128
128
  },
129
129
  {
130
130
  "name": "Profiles",
131
131
  "parent": "i18n",
132
- "description": "Locale profiles (e.g. `en:prod`) — create, list, and publish a profile's chunks to the CDN."
132
+ "description": "Locale profiles (e.g. `en:prod`) — create, list, and publish a profile to the CDN."
133
133
  },
134
134
  {
135
135
  "name": "Keys",
@@ -6939,7 +6939,7 @@
6939
6939
  "name": "status",
6940
6940
  "in": "query",
6941
6941
  "required": false,
6942
- "description": "Filter by lifecycle status, or `all`. The human-gated holding states (`pending_approval`, `triage`) are excluded from `all`/default and returned only when requested as the exact status.",
6942
+ "description": "Filter by lifecycle status, or `all`. The human-gated holding state (`pending_approval`) is excluded from `all`/default and returned only when requested as the exact status.",
6943
6943
  "schema": {
6944
6944
  "anyOf": [
6945
6945
  {
@@ -9099,7 +9099,7 @@
9099
9099
  "get": {
9100
9100
  "operationId": "listI18nProfiles",
9101
9101
  "summary": "List i18n profiles",
9102
- "description": "Returns every locale profile in the project (e.g. `en:prod`, `fr:prod`).\n\n**Use case:** Discover which locale profiles exist before pushing keys or publishing a chunk.",
9102
+ "description": "Returns every locale profile in the project (e.g. `en:prod`, `fr:prod`).\n\n**Use case:** Discover which locale profiles exist before pushing keys or publishing.",
9103
9103
  "tags": [
9104
9104
  "Profiles"
9105
9105
  ],
@@ -9348,8 +9348,8 @@
9348
9348
  },
9349
9349
  "post": {
9350
9350
  "operationId": "pushI18nKeys",
9351
- "summary": "Push new i18n keys (insert-only)",
9352
- "description": "Add NEW keys to a profile. Insert-only — existing keys are left untouched (overwrite one with `updateI18nKey`).\n\n**Use case:** Seed newly-extracted keys without clobbering translations already in the profile.",
9351
+ "summary": "Push i18n keys (insert-only, or `force` to overwrite)",
9352
+ "description": "Add NEW keys to a profile. Insert-only by default — existing keys are left untouched and reported back as `skipped`.\n\nPass `force: true` to overwrite the existing ones in bulk with the submitted values: they come back as `updated` instead of `skipped`. Without `force` the only overwrite paths are `updateI18nKey` (one key) and the devtools-only `upsertI18nKeys`.\n\n**Use case:** Seed newly-extracted keys without clobbering translations already in the profile — or re-push a whole source-language file with `force` after the copy changed.",
9353
9353
  "tags": [
9354
9354
  "Keys"
9355
9355
  ],
@@ -9379,7 +9379,7 @@
9379
9379
  },
9380
9380
  "responses": {
9381
9381
  "201": {
9382
- "description": "Push new i18n keys (insert-only)",
9382
+ "description": "Push i18n keys (insert-only, or `force` to overwrite)",
9383
9383
  "content": {
9384
9384
  "application/json": {
9385
9385
  "schema": {
@@ -9390,8 +9390,10 @@
9390
9390
  "checkout.cta"
9391
9391
  ],
9392
9392
  "skipped": [],
9393
+ "updated": [],
9393
9394
  "pushed_count": 1,
9394
- "skipped_count": 0
9395
+ "skipped_count": 0,
9396
+ "updated_count": 0
9395
9397
  }
9396
9398
  }
9397
9399
  }
@@ -9466,8 +9468,7 @@
9466
9468
  "$ref": "#/components/schemas/UpsertI18nKeysResponse"
9467
9469
  },
9468
9470
  "example": {
9469
- "upserted": 1,
9470
- "chunk": "default"
9471
+ "upserted": 1
9471
9472
  }
9472
9473
  }
9473
9474
  }
@@ -10136,7 +10137,7 @@
10136
10137
  "post": {
10137
10138
  "operationId": "publishI18nProfile",
10138
10139
  "summary": "Publish a profile live",
10139
- "description": "Publish a profile to the CDN — rebuild its KV snapshot + purge the edge. Publishing is PROFILE-WIDE: the whole profile is snapshotted into one KV blob, so the optional `chunk` in the body is an audit label only (it does not scope what ships).\n\n**Use case:** Ship the latest translations live after pushing/updating keys.",
10140
+ "description": "Publish a profile to the CDN — rebuild its KV snapshot + purge the edge. Publishing is PROFILE-WIDE: the whole profile is snapshotted into one KV blob, so the body takes no options.\n\n**Use case:** Ship the latest translations live after pushing/updating keys.",
10140
10141
  "tags": [
10141
10142
  "Profiles"
10142
10143
  ],
@@ -10155,21 +10156,19 @@
10155
10156
  }
10156
10157
  ],
10157
10158
  "requestBody": {
10158
- "required": true,
10159
+ "required": false,
10159
10160
  "content": {
10160
10161
  "application/json": {
10161
10162
  "schema": {
10162
10163
  "$ref": "#/components/schemas/PublishI18nProfileRequest"
10163
10164
  },
10164
- "example": {
10165
- "chunk": "default"
10166
- }
10165
+ "example": {}
10167
10166
  }
10168
10167
  }
10169
10168
  },
10170
10169
  "responses": {
10171
10170
  "200": {
10172
- "description": "Publish a profile chunk",
10171
+ "description": "Publish a profile",
10173
10172
  "content": {
10174
10173
  "application/json": {
10175
10174
  "schema": {
@@ -19273,8 +19272,6 @@
19273
19272
  "enum": [
19274
19273
  "open",
19275
19274
  "pending_approval",
19276
- "triage",
19277
- "triaged",
19278
19275
  "investigating_by_ai",
19279
19276
  "in_progress",
19280
19277
  "blocked",
@@ -19282,7 +19279,7 @@
19282
19279
  "resolved",
19283
19280
  "wont_fix"
19284
19281
  ],
19285
- "description": "Lifecycle status of a queue item. The working flow is `open` → `triaged` → `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. Two human-gated holding states park an item OUT of the work queue until a human promotes it to `open` in the dashboard, so `GET /api/admin/ops` excludes them under `status=all`/default and returns them only when requested as an exact `status`: `pending_approval` is the pre-open approval gate for untriaged inbound (e.g. connector requests filed from a customer's connectors panel) so it never gets auto-implemented — approving = flipping the status to `open`; `triage` is the onboarding-help bucket — questions/errors submitted to the \"Stuck in onboarding?\" assistant are funnelled into the platform project as `triage` rows so the team can see where people get stuck and follow up, keeping onboarding chatter out of the work queue until a human moves real items to `open`."
19282
+ "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`)."
19286
19283
  },
19287
19284
  "OpsItemPriority": {
19288
19285
  "type": "string",
@@ -19298,17 +19295,16 @@
19298
19295
  "type": "string",
19299
19296
  "enum": [
19300
19297
  "pr_ready",
19298
+ "pr_merged",
19301
19299
  "investigated",
19302
19300
  "detected",
19303
19301
  "question",
19304
19302
  "ready_for_qa",
19305
19303
  "pending_approval",
19306
- "needs_triage",
19307
19304
  "working",
19308
- "triaged_low",
19309
19305
  "backlog"
19310
19306
  ],
19311
- "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 `needs_triage`/`backlog` (by priority) or `investigated`/`detected` for auto-filed error/alert tickets. `triaged_low` marks a low-signal item AI has looked at but that nothing is moving. Absent on rows filed before the field existed — consumers should treat a missing value as \"derive from the other fields\"."
19307
+ "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` or `investigated`/`detected` for auto-filed error/alert tickets. `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. `pr_merged` is derived client-side by scanning the linked pull request on GitHub, so it is accepted on write but not currently emitted by the API. Absent on rows filed before the field existed — consumers should treat a missing value as \"derive from the other fields\"."
19312
19308
  },
19313
19309
  "OpsBrowserContext": {
19314
19310
  "type": "object",
@@ -23611,21 +23607,6 @@
23611
23607
  }
23612
23608
  ]
23613
23609
  },
23614
- "chunkId": {
23615
- "description": "Owning chunk (authoring grouping) id.",
23616
- "type": "string"
23617
- },
23618
- "chunkName": {
23619
- "description": "Name of the owning chunk (authoring grouping), or `null` when it cannot be resolved.",
23620
- "anyOf": [
23621
- {
23622
- "type": "string"
23623
- },
23624
- {
23625
- "type": "null"
23626
- }
23627
- ]
23628
- },
23629
23610
  "updatedAt": {
23630
23611
  "description": "ISO-8601 timestamp of the last edit.",
23631
23612
  "type": "string"
@@ -23643,8 +23624,6 @@
23643
23624
  "variables",
23644
23625
  "profileId",
23645
23626
  "profileName",
23646
- "chunkId",
23647
- "chunkName",
23648
23627
  "updatedAt",
23649
23628
  "updatedBy"
23650
23629
  ],
@@ -23673,13 +23652,6 @@
23673
23652
  "format": "uuid",
23674
23653
  "description": "Target profile id to upsert keys into."
23675
23654
  },
23676
- "chunk": {
23677
- "description": "Logical grouping the keys are filed under. Defaults to `default`.",
23678
- "type": "string",
23679
- "minLength": 1,
23680
- "maxLength": 64,
23681
- "default": "default"
23682
- },
23683
23655
  "keys": {
23684
23656
  "type": "array",
23685
23657
  "minItems": 1,
@@ -23734,15 +23706,10 @@
23734
23706
  "upserted": {
23735
23707
  "type": "number",
23736
23708
  "description": "Number of keys written (inserted or overwritten)."
23737
- },
23738
- "chunk": {
23739
- "type": "string",
23740
- "description": "The chunk the keys were filed under."
23741
23709
  }
23742
23710
  },
23743
23711
  "required": [
23744
- "upserted",
23745
- "chunk"
23712
+ "upserted"
23746
23713
  ],
23747
23714
  "additionalProperties": false,
23748
23715
  "description": "Result of a bulk key upsert. The affected profile's KV snapshot is rebuilt (and the CDN purged) before this returns."
@@ -23755,13 +23722,6 @@
23755
23722
  "format": "uuid",
23756
23723
  "description": "Target profile id to add keys to."
23757
23724
  },
23758
- "chunk": {
23759
- "description": "Logical grouping the new keys are filed under. Defaults to `default`.",
23760
- "type": "string",
23761
- "minLength": 1,
23762
- "maxLength": 64,
23763
- "default": "default"
23764
- },
23765
23725
  "keys": {
23766
23726
  "type": "array",
23767
23727
  "minItems": 1,
@@ -23800,7 +23760,12 @@
23800
23760
  ],
23801
23761
  "additionalProperties": false
23802
23762
  },
23803
- "description": "Keys to add. Insert-only — existing keys are reported back as `skipped`."
23763
+ "description": "Keys to add. Insert-only by default — existing keys are reported back as `skipped` (set `force` to overwrite them instead)."
23764
+ },
23765
+ "force": {
23766
+ "type": "boolean",
23767
+ "default": false,
23768
+ "description": "Overwrite keys that already exist with the submitted value instead of skipping them. Overwritten keys come back as `updated`. Off by default so a routine push can never clobber live translations."
23804
23769
  }
23805
23770
  },
23806
23771
  "required": [
@@ -23808,7 +23773,7 @@
23808
23773
  "keys"
23809
23774
  ],
23810
23775
  "additionalProperties": false,
23811
- "description": "Body for `POST /api/admin/i18n/keys`. Insert-only: keys that already exist are never overwritten — use `PUT /keys/{id}` to change a value."
23776
+ "description": "Body for `POST /api/admin/i18n/keys`. Insert-only by default: keys that already exist are never overwritten — pass `force: true` to overwrite them in bulk, or use `PUT /keys/{id}` to change one value."
23812
23777
  },
23813
23778
  "PushI18nKeysResponse": {
23814
23779
  "type": "object",
@@ -23825,7 +23790,14 @@
23825
23790
  "items": {
23826
23791
  "type": "string"
23827
23792
  },
23828
- "description": "Key names that already existed and were left untouched."
23793
+ "description": "Key names that already existed and were left untouched. Always empty when `force` was set — those key names come back under `updated` instead."
23794
+ },
23795
+ "updated": {
23796
+ "type": "array",
23797
+ "items": {
23798
+ "type": "string"
23799
+ },
23800
+ "description": "Key names that already existed and were overwritten with the submitted value. Only ever non-empty when the push set `force`."
23829
23801
  },
23830
23802
  "pushed_count": {
23831
23803
  "type": "number",
@@ -23835,19 +23807,21 @@
23835
23807
  "type": "number",
23836
23808
  "description": "Number of keys skipped (== `skipped.length`)."
23837
23809
  },
23838
- "chunk": {
23839
- "description": "The chunk the keys were filed under.",
23840
- "type": "string"
23810
+ "updated_count": {
23811
+ "type": "number",
23812
+ "description": "Number of existing keys overwritten (== `updated.length`)."
23841
23813
  }
23842
23814
  },
23843
23815
  "required": [
23844
23816
  "added",
23845
23817
  "skipped",
23818
+ "updated",
23846
23819
  "pushed_count",
23847
- "skipped_count"
23820
+ "skipped_count",
23821
+ "updated_count"
23848
23822
  ],
23849
23823
  "additionalProperties": false,
23850
- "description": "Result of an insert-only key push."
23824
+ "description": "Result of a key push — what was inserted, what was left alone, and (with `force`) what was overwritten."
23851
23825
  },
23852
23826
  "UpdateI18nKeyRequest": {
23853
23827
  "type": "object",
@@ -24121,14 +24095,9 @@
24121
24095
  },
24122
24096
  "PublishI18nProfileRequest": {
24123
24097
  "type": "object",
24124
- "properties": {
24125
- "chunk": {
24126
- "description": "Optional chunk label to stamp on the audit log. Publishing is profile-wide regardless — the whole profile is snapshotted into one KV blob.",
24127
- "type": "string"
24128
- }
24129
- },
24098
+ "properties": {},
24130
24099
  "additionalProperties": false,
24131
- "description": "Body for `POST /api/admin/i18n/profiles/{profileId}/publish`. The `chunk` is an audit label only."
24100
+ "description": "Body for `POST /api/admin/i18n/profiles/{profileId}/publish`. Publishing is profile-wide — the whole profile is snapshotted into one KV blob — so the body takes no options."
24132
24101
  },
24133
24102
  "PublishI18nProfileResponse": {
24134
24103
  "type": "object",
@@ -24142,17 +24111,6 @@
24142
24111
  "type": "string",
24143
24112
  "description": "Profile that was published."
24144
24113
  },
24145
- "chunk": {
24146
- "anyOf": [
24147
- {
24148
- "type": "string"
24149
- },
24150
- {
24151
- "type": "null"
24152
- }
24153
- ],
24154
- "description": "Audit chunk label, or `null` when none was given."
24155
- },
24156
24114
  "published_at": {
24157
24115
  "type": "string",
24158
24116
  "description": "ISO-8601 timestamp of the publish."
@@ -24190,7 +24148,6 @@
24190
24148
  "required": [
24191
24149
  "ok",
24192
24150
  "profile_id",
24193
- "chunk",
24194
24151
  "published_at",
24195
24152
  "version",
24196
24153
  "key_count",
package/openapi.yaml CHANGED
@@ -226,14 +226,14 @@ tags:
226
226
  - name: i18n
227
227
  description: |-
228
228
  String Manager (i18n): the worker-safe REST surface — locale profiles, the
229
- insert-only key push, single-key overwrite, chunk publish, and the read-only
229
+ insert-only key push, single-key overwrite, profile publish, and the read-only
230
230
  key/draft listings.
231
231
 
232
232
  The fs/AST parts (scan, validate, install-loader, codemod) are NOT part of
233
233
  this API — they stay in the fs-having CLI/MCP.
234
234
  - name: Profiles
235
235
  parent: i18n
236
- description: Locale profiles (e.g. `en:prod`) — create, list, and publish a profile's chunks to the CDN.
236
+ description: Locale profiles (e.g. `en:prod`) — create, list, and publish a profile to the CDN.
237
237
  - name: Keys
238
238
  parent: i18n
239
239
  description: Translation keys — the insert-only push, single-key overwrite, and key listing.
@@ -5078,7 +5078,7 @@ paths:
5078
5078
  - name: status
5079
5079
  in: query
5080
5080
  required: false
5081
- description: Filter by lifecycle status, or `all`. The human-gated holding states (`pending_approval`, `triage`) are excluded from `all`/default and returned only when requested as the exact status.
5081
+ description: Filter by lifecycle status, or `all`. The human-gated holding state (`pending_approval`) is excluded from `all`/default and returned only when requested as the exact status.
5082
5082
  schema:
5083
5083
  anyOf:
5084
5084
  - $ref: '#/components/schemas/OpsItemStatus'
@@ -6698,7 +6698,7 @@ paths:
6698
6698
  description: |-
6699
6699
  Returns every locale profile in the project (e.g. `en:prod`, `fr:prod`).
6700
6700
 
6701
- **Use case:** Discover which locale profiles exist before pushing keys or publishing a chunk.
6701
+ **Use case:** Discover which locale profiles exist before pushing keys or publishing.
6702
6702
  tags:
6703
6703
  - Profiles
6704
6704
  parameters:
@@ -6867,11 +6867,13 @@ paths:
6867
6867
  name: list
6868
6868
  post:
6869
6869
  operationId: pushI18nKeys
6870
- summary: Push new i18n keys (insert-only)
6870
+ summary: Push i18n keys (insert-only, or `force` to overwrite)
6871
6871
  description: |-
6872
- Add NEW keys to a profile. Insert-only — existing keys are left untouched (overwrite one with `updateI18nKey`).
6872
+ Add NEW keys to a profile. Insert-only by default — existing keys are left untouched and reported back as `skipped`.
6873
6873
 
6874
- **Use case:** Seed newly-extracted keys without clobbering translations already in the profile.
6874
+ Pass `force: true` to overwrite the existing ones in bulk with the submitted values: they come back as `updated` instead of `skipped`. Without `force` the only overwrite paths are `updateI18nKey` (one key) and the devtools-only `upsertI18nKeys`.
6875
+
6876
+ **Use case:** Seed newly-extracted keys without clobbering translations already in the profile — or re-push a whole source-language file with `force` after the copy changed.
6875
6877
  tags:
6876
6878
  - Keys
6877
6879
  parameters:
@@ -6889,7 +6891,7 @@ paths:
6889
6891
  value: Buy now
6890
6892
  responses:
6891
6893
  '201':
6892
- description: Push new i18n keys (insert-only)
6894
+ description: Push i18n keys (insert-only, or `force` to overwrite)
6893
6895
  content:
6894
6896
  application/json:
6895
6897
  schema:
@@ -6898,8 +6900,10 @@ paths:
6898
6900
  added:
6899
6901
  - checkout.cta
6900
6902
  skipped: []
6903
+ updated: []
6901
6904
  pushed_count: 1
6902
6905
  skipped_count: 0
6906
+ updated_count: 0
6903
6907
  '400':
6904
6908
  $ref: '#/components/responses/BadRequest'
6905
6909
  '401':
@@ -6953,7 +6957,6 @@ paths:
6953
6957
  $ref: '#/components/schemas/UpsertI18nKeysResponse'
6954
6958
  example:
6955
6959
  upserted: 1
6956
- chunk: default
6957
6960
  '400':
6958
6961
  $ref: '#/components/responses/BadRequest'
6959
6962
  '401':
@@ -7420,7 +7423,7 @@ paths:
7420
7423
  operationId: publishI18nProfile
7421
7424
  summary: Publish a profile live
7422
7425
  description: |-
7423
- Publish a profile to the CDN — rebuild its KV snapshot + purge the edge. Publishing is PROFILE-WIDE: the whole profile is snapshotted into one KV blob, so the optional `chunk` in the body is an audit label only (it does not scope what ships).
7426
+ Publish a profile to the CDN — rebuild its KV snapshot + purge the edge. Publishing is PROFILE-WIDE: the whole profile is snapshotted into one KV blob, so the body takes no options.
7424
7427
 
7425
7428
  **Use case:** Ship the latest translations live after pushing/updating keys.
7426
7429
  tags:
@@ -7434,16 +7437,15 @@ paths:
7434
7437
  schema:
7435
7438
  $ref: '#/components/schemas/ResourceId'
7436
7439
  requestBody:
7437
- required: true
7440
+ required: false
7438
7441
  content:
7439
7442
  application/json:
7440
7443
  schema:
7441
7444
  $ref: '#/components/schemas/PublishI18nProfileRequest'
7442
- example:
7443
- chunk: default
7445
+ example: {}
7444
7446
  responses:
7445
7447
  '200':
7446
- description: Publish a profile chunk
7448
+ description: Publish a profile
7447
7449
  content:
7448
7450
  application/json:
7449
7451
  schema:
@@ -13923,15 +13925,13 @@ components:
13923
13925
  enum:
13924
13926
  - open
13925
13927
  - pending_approval
13926
- - triage
13927
- - triaged
13928
13928
  - investigating_by_ai
13929
13929
  - in_progress
13930
13930
  - blocked
13931
13931
  - ready_for_qa
13932
13932
  - resolved
13933
13933
  - wont_fix
13934
- description: 'Lifecycle status of a queue item. The working flow is `open` → `triaged` → `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. Two human-gated holding states park an item OUT of the work queue until a human promotes it to `open` in the dashboard, so `GET /api/admin/ops` excludes them under `status=all`/default and returns them only when requested as an exact `status`: `pending_approval` is the pre-open approval gate for untriaged inbound (e.g. connector requests filed from a customer''s connectors panel) so it never gets auto-implemented — approving = flipping the status to `open`; `triage` is the onboarding-help bucket — questions/errors submitted to the "Stuck in onboarding?" assistant are funnelled into the platform project as `triage` rows so the team can see where people get stuck and follow up, keeping onboarding chatter out of the work queue until a human moves real items to `open`.'
13934
+ 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`).'
13935
13935
  OpsItemPriority:
13936
13936
  type: string
13937
13937
  enum:
@@ -13944,16 +13944,15 @@ components:
13944
13944
  type: string
13945
13945
  enum:
13946
13946
  - pr_ready
13947
+ - pr_merged
13947
13948
  - investigated
13948
13949
  - detected
13949
13950
  - question
13950
13951
  - ready_for_qa
13951
13952
  - pending_approval
13952
- - needs_triage
13953
13953
  - working
13954
- - triaged_low
13955
13954
  - backlog
13956
- 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 `needs_triage`/`backlog` (by priority) or `investigated`/`detected` for auto-filed error/alert tickets. `triaged_low` marks a low-signal item AI has looked at but that nothing is moving. Absent on rows filed before the field existed — consumers should treat a missing value as "derive from the other fields".'
13955
+ description: 'Where automation has taken an item in the investigation lifecycle — the signal the ops cockpit renders as "what AI did" plus the one action expected of the user. It is **written as a side-effect of the actions that already happen**, never authored on its own: linking a PR sets `pr_ready`, moving to `in_progress` sets `working`, `ready_for_qa` sets `ready_for_qa`, a system/assistant reply sets `question`, resolving clears it, and creation seeds `backlog` or `investigated`/`detected` for auto-filed error/alert tickets. `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. `pr_merged` is derived client-side by scanning the linked pull request on GitHub, so it is accepted on write but not currently emitted by the API. Absent on rows filed before the field existed — consumers should treat a missing value as "derive from the other fields".'
13957
13956
  OpsBrowserContext:
13958
13957
  type: object
13959
13958
  properties:
@@ -16730,14 +16729,6 @@ components:
16730
16729
  anyOf:
16731
16730
  - type: string
16732
16731
  - type: 'null'
16733
- chunkId:
16734
- description: Owning chunk (authoring grouping) id.
16735
- type: string
16736
- chunkName:
16737
- description: Name of the owning chunk (authoring grouping), or `null` when it cannot be resolved.
16738
- anyOf:
16739
- - type: string
16740
- - type: 'null'
16741
16732
  updatedAt:
16742
16733
  description: ISO-8601 timestamp of the last edit.
16743
16734
  type: string
@@ -16752,8 +16743,6 @@ components:
16752
16743
  - variables
16753
16744
  - profileId
16754
16745
  - profileName
16755
- - chunkId
16756
- - chunkName
16757
16746
  - updatedAt
16758
16747
  - updatedBy
16759
16748
  additionalProperties: false
@@ -16774,12 +16763,6 @@ components:
16774
16763
  type: string
16775
16764
  format: uuid
16776
16765
  description: Target profile id to upsert keys into.
16777
- chunk:
16778
- description: Logical grouping the keys are filed under. Defaults to `default`.
16779
- type: string
16780
- minLength: 1
16781
- maxLength: 64
16782
- default: default
16783
16766
  keys:
16784
16767
  type: array
16785
16768
  minItems: 1
@@ -16822,12 +16805,8 @@ components:
16822
16805
  upserted:
16823
16806
  type: number
16824
16807
  description: Number of keys written (inserted or overwritten).
16825
- chunk:
16826
- type: string
16827
- description: The chunk the keys were filed under.
16828
16808
  required:
16829
16809
  - upserted
16830
- - chunk
16831
16810
  additionalProperties: false
16832
16811
  description: Result of a bulk key upsert. The affected profile's KV snapshot is rebuilt (and the CDN purged) before this returns.
16833
16812
  PushI18nKeysRequest:
@@ -16837,12 +16816,6 @@ components:
16837
16816
  type: string
16838
16817
  format: uuid
16839
16818
  description: Target profile id to add keys to.
16840
- chunk:
16841
- description: Logical grouping the new keys are filed under. Defaults to `default`.
16842
- type: string
16843
- minLength: 1
16844
- maxLength: 64
16845
- default: default
16846
16819
  keys:
16847
16820
  type: array
16848
16821
  minItems: 1
@@ -16873,12 +16846,16 @@ components:
16873
16846
  - key
16874
16847
  - value
16875
16848
  additionalProperties: false
16876
- description: Keys to add. Insert-only — existing keys are reported back as `skipped`.
16849
+ description: Keys to add. Insert-only by default — existing keys are reported back as `skipped` (set `force` to overwrite them instead).
16850
+ force:
16851
+ type: boolean
16852
+ default: false
16853
+ description: Overwrite keys that already exist with the submitted value instead of skipping them. Overwritten keys come back as `updated`. Off by default so a routine push can never clobber live translations.
16877
16854
  required:
16878
16855
  - profile_id
16879
16856
  - keys
16880
16857
  additionalProperties: false
16881
- description: 'Body for `POST /api/admin/i18n/keys`. Insert-only: keys that already exist are never overwritten — use `PUT /keys/{id}` to change a value.'
16858
+ description: 'Body for `POST /api/admin/i18n/keys`. Insert-only by default: keys that already exist are never overwritten — pass `force: true` to overwrite them in bulk, or use `PUT /keys/{id}` to change one value.'
16882
16859
  PushI18nKeysResponse:
16883
16860
  type: object
16884
16861
  properties:
@@ -16891,23 +16868,30 @@ components:
16891
16868
  type: array
16892
16869
  items:
16893
16870
  type: string
16894
- description: Key names that already existed and were left untouched.
16871
+ description: Key names that already existed and were left untouched. Always empty when `force` was set — those key names come back under `updated` instead.
16872
+ updated:
16873
+ type: array
16874
+ items:
16875
+ type: string
16876
+ description: Key names that already existed and were overwritten with the submitted value. Only ever non-empty when the push set `force`.
16895
16877
  pushed_count:
16896
16878
  type: number
16897
16879
  description: Number of keys inserted (== `added.length`).
16898
16880
  skipped_count:
16899
16881
  type: number
16900
16882
  description: Number of keys skipped (== `skipped.length`).
16901
- chunk:
16902
- description: The chunk the keys were filed under.
16903
- type: string
16883
+ updated_count:
16884
+ type: number
16885
+ description: Number of existing keys overwritten (== `updated.length`).
16904
16886
  required:
16905
16887
  - added
16906
16888
  - skipped
16889
+ - updated
16907
16890
  - pushed_count
16908
16891
  - skipped_count
16892
+ - updated_count
16909
16893
  additionalProperties: false
16910
- description: Result of an insert-only key push.
16894
+ description: Result of a key push — what was inserted, what was left alone, and (with `force`) what was overwritten.
16911
16895
  UpdateI18nKeyRequest:
16912
16896
  type: object
16913
16897
  properties:
@@ -17102,12 +17086,9 @@ components:
17102
17086
  description: Body for `POST /api/admin/i18n/drafts/{draftId}/keys`. Upserts one staged key into an open draft — inserted when new, overwritten when it already exists. `{{var}}` placeholder names are auto-derived from the value.
17103
17087
  PublishI18nProfileRequest:
17104
17088
  type: object
17105
- properties:
17106
- chunk:
17107
- description: Optional chunk label to stamp on the audit log. Publishing is profile-wide regardless — the whole profile is snapshotted into one KV blob.
17108
- type: string
17089
+ properties: {}
17109
17090
  additionalProperties: false
17110
- description: Body for `POST /api/admin/i18n/profiles/{profileId}/publish`. The `chunk` is an audit label only.
17091
+ description: Body for `POST /api/admin/i18n/profiles/{profileId}/publish`. Publishing is profile-wide — the whole profile is snapshotted into one KV blob — so the body takes no options.
17111
17092
  PublishI18nProfileResponse:
17112
17093
  type: object
17113
17094
  properties:
@@ -17118,11 +17099,6 @@ components:
17118
17099
  profile_id:
17119
17100
  type: string
17120
17101
  description: Profile that was published.
17121
- chunk:
17122
- anyOf:
17123
- - type: string
17124
- - type: 'null'
17125
- description: Audit chunk label, or `null` when none was given.
17126
17102
  published_at:
17127
17103
  type: string
17128
17104
  description: ISO-8601 timestamp of the publish.
@@ -17151,7 +17127,6 @@ components:
17151
17127
  required:
17152
17128
  - ok
17153
17129
  - profile_id
17154
- - chunk
17155
17130
  - published_at
17156
17131
  - version
17157
17132
  - key_count
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipeasy/openapi",
3
- "version": "2.5.0",
3
+ "version": "3.1.0",
4
4
  "description": "Shipeasy admin OpenAPI 3.2 spec (hand-authored, single source of truth) + the generated TypeScript client, Zod schemas, and types. Consumed by @shipeasy/cli and @shipeasy/mcp.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",