@shipeasy/openapi 2.3.0 → 2.5.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 (46) hide show
  1. package/dist/{chunk-PRN4AEAM.js → chunk-DBTSD3W5.js} +1085 -261
  2. package/dist/chunk-DBTSD3W5.js.map +1 -0
  3. package/dist/{chunk-LYNWK55D.js → chunk-RDMD5XQT.js} +171 -1
  4. package/dist/chunk-RDMD5XQT.js.map +1 -0
  5. package/dist/{client-DO5HTb_L.d.ts → client-ObcuFHaV.d.ts} +5605 -2734
  6. package/dist/client.d.ts +1 -1
  7. package/dist/client.js +47 -1
  8. package/dist/custom.d.ts +9 -4
  9. package/dist/custom.js +57 -9
  10. package/dist/custom.js.map +1 -1
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.js +48 -2
  13. package/dist/index.js.map +1 -1
  14. package/dist/schemas.d.ts +3171 -485
  15. package/dist/schemas.js +229 -1
  16. package/openapi.json +13264 -8071
  17. package/openapi.yaml +5108 -1550
  18. package/package.json +1 -1
  19. package/spec/components/errors.yaml +3 -0
  20. package/spec/components/schemas/alerts.yaml +138 -0
  21. package/spec/components/schemas/attributes.yaml +53 -3
  22. package/spec/components/schemas/common.yaml +10 -0
  23. package/spec/components/schemas/configs.yaml +91 -3
  24. package/spec/components/schemas/connectors.yaml +5 -1
  25. package/spec/components/schemas/errors-api.yaml +51 -4
  26. package/spec/components/schemas/experiments.yaml +347 -87
  27. package/spec/components/schemas/gates.yaml +350 -277
  28. package/spec/components/schemas/i18n.yaml +169 -40
  29. package/spec/components/schemas/killswitches.yaml +36 -0
  30. package/spec/components/schemas/metrics.yaml +199 -7
  31. package/spec/components/schemas/ops.yaml +961 -29
  32. package/spec/components/schemas/projects.yaml +129 -3
  33. package/spec/openapi.yaml +58 -0
  34. package/spec/paths/alerts.yaml +184 -0
  35. package/spec/paths/attributes.yaml +23 -5
  36. package/spec/paths/configs.yaml +98 -21
  37. package/spec/paths/errors.yaml +16 -0
  38. package/spec/paths/experiments.yaml +236 -16
  39. package/spec/paths/gates.yaml +137 -0
  40. package/spec/paths/i18n.yaml +290 -6
  41. package/spec/paths/killswitches.yaml +6 -0
  42. package/spec/paths/metrics.yaml +186 -0
  43. package/spec/paths/ops.yaml +382 -0
  44. package/spec/paths/projects.yaml +60 -0
  45. package/dist/chunk-LYNWK55D.js.map +0 -1
  46. package/dist/chunk-PRN4AEAM.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipeasy/openapi",
3
- "version": "2.3.0",
3
+ "version": "2.5.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",
@@ -28,6 +28,8 @@ ErrorCode:
28
28
  # Metrics
29
29
  - METRIC_NOT_FOUND
30
30
  - METRIC_UNKNOWN_ID
31
+ # Ops
32
+ - AGENT_NOT_CONNECTED
31
33
  x-enum-descriptions:
32
34
  BAD_REQUEST: Malformed request (bad JSON, missing project scope).
33
35
  UNAUTHORIZED: Missing or invalid admin SDK key.
@@ -53,6 +55,7 @@ ErrorCode:
53
55
  EXPERIMENT_IMMUTABLE_FIELD: A field that is immutable while the experiment is running was modified.
54
56
  METRIC_NOT_FOUND: The referenced metric does not exist or is not visible to the caller.
55
57
  METRIC_UNKNOWN_ID: The supplied metric id is malformed or not recognised.
58
+ AGENT_NOT_CONNECTED: The named AI agent type has no connected trigger connector in this project — list the available agents (`ops agents list` / `GET /api/admin/agent-profiles`) and use one of those, or connect the agent under Settings → Triggers.
56
59
  Error:
57
60
  type: object
58
61
  description: Uniform error envelope returned by every admin endpoint on a non-2xx status. `error` is the human-readable message; `code` is the stable machine code (present whenever the failure maps to a catalogued `ErrorCode`); `detail` carries extra context (validation paths, conflicting field); `fields` maps each failing input field to its own message; `instructions` is optional actionable guidance for resolving the error; `schema` echoes back the expected JSON Schema when a value failed schema validation.
@@ -0,0 +1,138 @@
1
+ AlertApiRow:
2
+ type: object
3
+ description: |-
4
+ One FIRED alert — a condition the platform observed and raised, not the rule that defines it (alert *rules* are the `/api/admin/alert-rules` resource). Alerts are never filed by hand: the UI (killswitch flips) and the worker (analysis consumer + alerts cron) raise them, keyed by `(source, dedupeKey)` so re-raising refreshes the active row and a clearing condition auto-resolves it.
5
+
6
+ Every field is always present on the wire; nullable fields are `null`, never absent.
7
+ properties:
8
+ id:
9
+ type: string
10
+ description: Stable opaque alert id.
11
+ source:
12
+ type: string
13
+ enum:
14
+ - metric_rule
15
+ - killswitch_armed
16
+ - experiment_srm
17
+ - experiment_peek
18
+ - guardrail
19
+ description: Which platform subsystem raised the alert — a metric-threshold rule crossing (`metric_rule`), an armed kill switch (`killswitch_armed`), a sample-ratio mismatch or peeking guard on an experiment (`experiment_srm` / `experiment_peek`), or a guardrail-metric breach (`guardrail`).
20
+ ruleId:
21
+ description: >-
22
+ Id of the alert rule that raised it (`ar_…`), for `source: metric_rule`.
23
+ `null` for alerts raised outside the rules engine.
24
+ anyOf:
25
+ - type: string
26
+ - type: "null"
27
+ severity:
28
+ type: string
29
+ enum:
30
+ - danger
31
+ - warn
32
+ - info
33
+ description: How loud the alert is — `danger` pages, `warn` is the default, `info` is FYI-only.
34
+ dedupeKey:
35
+ type: string
36
+ description: Idempotency + reconcile key within `(project, source)` — re-raising the same condition refreshes the existing active row instead of stacking duplicates, and the condition clearing flips that row to `resolved`.
37
+ title:
38
+ type: string
39
+ description: Short human-readable headline (what fired).
40
+ detail:
41
+ type: string
42
+ description: Longer human-readable explanation — the observed condition, thresholds, and context.
43
+ href:
44
+ description: Dashboard-relative link to the surface that explains the alert (e.g. the experiment or kill switch page), or `null` if there is no single destination.
45
+ anyOf:
46
+ - type: string
47
+ - type: "null"
48
+ observedValue:
49
+ description: The numeric value that tripped the condition (e.g. the metric aggregate a rule compared against its threshold), or `null` when the source has no scalar observation.
50
+ anyOf:
51
+ - type: number
52
+ - type: "null"
53
+ status:
54
+ type: string
55
+ enum:
56
+ - active
57
+ - resolved
58
+ - dismissed
59
+ description: Lifecycle state. `active` means the condition currently 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.
60
+ createdAt:
61
+ type: string
62
+ description: ISO-8601 timestamp the alert was first raised.
63
+ resolvedAt:
64
+ description: ISO-8601 timestamp the alert flipped to `resolved`, or `null` while it hasn't.
65
+ anyOf:
66
+ - type: string
67
+ - type: "null"
68
+ dismissedAt:
69
+ description: ISO-8601 timestamp the alert was dismissed, or `null` while it hasn't been.
70
+ anyOf:
71
+ - type: string
72
+ - type: "null"
73
+ assigneeId:
74
+ description: PERSON owner of the triage — a `users.id` (soft reference, same value space as a feedback item's `assigneeId`), or `null` if unassigned. Set from the ops cockpit's Owner column; independent of the agent half.
75
+ anyOf:
76
+ - type: string
77
+ - type: "null"
78
+ assigneeConnectorId:
79
+ description: AGENT owner — the id of a connected trigger connector (`connectors.id`), or `null`. Mutually exclusive with `assigneeAgent`.
80
+ anyOf:
81
+ - type: string
82
+ - type: "null"
83
+ assigneeAgent:
84
+ description: AGENT owner — a built-in hosted Shipeasy agent (`"jarvis"`, Enterprise-gated), or `null`. Mutually exclusive with `assigneeConnectorId`.
85
+ anyOf:
86
+ - type: string
87
+ - type: "null"
88
+ required:
89
+ - id
90
+ - source
91
+ - ruleId
92
+ - severity
93
+ - dedupeKey
94
+ - title
95
+ - detail
96
+ - href
97
+ - observedValue
98
+ - status
99
+ - createdAt
100
+ - resolvedAt
101
+ - dismissedAt
102
+ - assigneeId
103
+ - assigneeConnectorId
104
+ - assigneeAgent
105
+ additionalProperties: false
106
+ ListAlertsResponse:
107
+ type: array
108
+ description: A bare JSON array of fired alerts, ordered by `createdAt` descending. There is no pagination envelope.
109
+ items:
110
+ $ref: "#/AlertApiRow"
111
+ UpdateAlertRequest:
112
+ type: object
113
+ description: |-
114
+ Body for `PATCH /api/admin/alerts/{id}` — the triage writes the ops cockpit needs on a fired alert. All fields optional, at least one required; only the fields present are changed.
115
+
116
+ Flipping `status` stamps the matching timestamp (`resolvedAt` on `resolved`, `dismissedAt` on `dismissed`; both cleared on `active`). The person owner (`assigneeId`) and the agent owner (`agent`) are independent halves — setting one never touches the other.
117
+ properties:
118
+ status:
119
+ type: string
120
+ enum:
121
+ - active
122
+ - resolved
123
+ - dismissed
124
+ description: New lifecycle state. `resolved` / `dismissed` stamp their timestamp; `active` re-opens and clears both.
125
+ assigneeId:
126
+ description: PERSON owner — a `users.id`, or `null` to clear the assignment.
127
+ anyOf:
128
+ - type: string
129
+ - type: "null"
130
+ agent:
131
+ description: AGENT owner — a connected trigger connector's id (`connectors.id`), the built-in `"jarvis"` (Enterprise plan only — rejected with `403` otherwise), or `null` to clear. Stored in `assigneeConnectorId` or `assigneeAgent` depending on the value; the two are mutually exclusive.
132
+ anyOf:
133
+ - type: string
134
+ - type: "null"
135
+ minProperties: 1
136
+ additionalProperties: false
137
+ UpdateAlertResponse:
138
+ $ref: "#/AlertApiRow"
@@ -3,17 +3,67 @@ ListAttributesResponse:
3
3
  items:
4
4
  type: object
5
5
  properties:
6
+ id:
7
+ type: string
8
+ description: Stable opaque attribute id.
6
9
  name:
7
10
  type: string
8
11
  description: Attribute key as seen in evaluation context (e.g. `plan`, `country`).
9
12
  type:
10
- description: Inferred value type (`string`, `number`, `boolean`, …) when known.
13
+ $ref: "#/AttributeType"
14
+ enumValues:
15
+ description: Allowed values for `enum` attributes, else `null`.
16
+ anyOf:
17
+ - type: array
18
+ items:
19
+ type: string
20
+ - type: "null"
21
+ required:
22
+ type: integer
23
+ enum:
24
+ - 0
25
+ - 1
26
+ description: Whether the attribute must be present on the evaluation context (D1 stores the flag as `0`/`1`).
27
+ description:
28
+ description: Human note shown in the dashboard, or `null`.
29
+ anyOf:
30
+ - type: string
31
+ - type: "null"
32
+ sdkPath:
33
+ description: Dotted path the SDK reads the value from, or `null`.
34
+ anyOf:
35
+ - type: string
36
+ - type: "null"
37
+ createdAt:
38
+ type: string
39
+ description: ISO-8601 creation timestamp.
40
+ source:
11
41
  type: string
42
+ enum:
43
+ - auto
44
+ - manual
45
+ description: How the attribute came to exist — `auto` (inferred by the `/sdk/evaluate` sampler) or `manual` (declared via the UI/API).
46
+ lastSeenAt:
47
+ description: ISO-8601 timestamp of the most recent SDK sample that carried this attribute, or `null` when never sampled.
48
+ anyOf:
49
+ - type: string
50
+ - type: "null"
51
+ deprecated:
52
+ type: integer
53
+ enum:
54
+ - 0
55
+ - 1
56
+ description: "`1` when an auto-discovered attribute has stopped appearing in samples. Deprecated attributes stay listed; pickers may hide or de-rank them."
12
57
  required:
58
+ - id
13
59
  - name
60
+ - type
61
+ # Deliberately left open — the endpoint returns the raw attribute row, which
62
+ # still carries undocumented internal columns; tighten to `false` only once
63
+ # the handler projects an explicit allow-list.
14
64
  additionalProperties: {}
15
- description: One auto-inferred targeting attribute.
16
- description: Every auto-inferred targeting attribute in the project.
65
+ description: One declared or auto-inferred targeting attribute row.
66
+ description: Every targeting attribute in the project (declared and auto-inferred).
17
67
  AttributeType:
18
68
  type: string
19
69
  enum:
@@ -49,6 +49,16 @@ NotificationTarget:
49
49
  additionalProperties: false
50
50
  - type: "null"
51
51
  description: Delivery target for a notification; `null` = use the project default.
52
+ OkResponse:
53
+ type: object
54
+ properties:
55
+ ok:
56
+ type: boolean
57
+ const: true
58
+ description: Always `true` — the operation succeeded (errors use the error envelope instead).
59
+ required: [ok]
60
+ additionalProperties: false
61
+ description: Generic success acknowledgement for operations with no meaningful payload.
52
62
  PageQuery:
53
63
  type: object
54
64
  properties:
@@ -17,10 +17,25 @@ ListConfigsResponse:
17
17
  anyOf:
18
18
  - type: string
19
19
  - type: "null"
20
+ folder:
21
+ description: Folder segment used for dashboard organisation, or `null` when the config lives at the root.
22
+ anyOf:
23
+ - type: string
24
+ - type: "null"
20
25
  schema:
21
26
  type: object
22
27
  additionalProperties: {}
23
28
  description: JSON Schema (draft 2020-12) describing the shape of the config value. Top-level `type` must be `'object'`; every published value is validated against this schema.
29
+ creatorEmail:
30
+ description: Resolved email of the creator (`created_by` → `users.email`), or `null` when unknown. List-only enrichment — present on `GET /api/admin/configs` rows, absent from the by-id detail — so it is optional, never required.
31
+ anyOf:
32
+ - type: string
33
+ - type: "null"
34
+ createdAt:
35
+ description: ISO-8601 creation timestamp, or `null` on legacy rows. List-only enrichment — present on `GET /api/admin/configs` rows, absent from the by-id detail — so it is optional, never required.
36
+ anyOf:
37
+ - type: string
38
+ - type: "null"
24
39
  updatedAt:
25
40
  type: string
26
41
  description: ISO-8601 timestamp of last mutation.
@@ -80,6 +95,7 @@ ListConfigsResponse:
80
95
  - id
81
96
  - name
82
97
  - description
98
+ - folder
83
99
  - schema
84
100
  - updatedAt
85
101
  - envs
@@ -107,10 +123,25 @@ GetConfigResponse:
107
123
  anyOf:
108
124
  - type: string
109
125
  - type: "null"
126
+ folder:
127
+ description: Folder segment used for dashboard organisation, or `null` when the config lives at the root.
128
+ anyOf:
129
+ - type: string
130
+ - type: "null"
110
131
  schema:
111
132
  type: object
112
133
  additionalProperties: {}
113
134
  description: JSON Schema (draft 2020-12) describing the shape of the config value. Top-level `type` must be `'object'`; every published value is validated against this schema.
135
+ creatorEmail:
136
+ description: Resolved email of the creator (`created_by` → `users.email`), or `null` when unknown. List-only enrichment — present on `GET /api/admin/configs` rows, absent from this by-id detail — so it is optional, never required.
137
+ anyOf:
138
+ - type: string
139
+ - type: "null"
140
+ createdAt:
141
+ description: ISO-8601 creation timestamp, or `null` on legacy rows. List-only enrichment — present on `GET /api/admin/configs` rows, absent from this by-id detail — so it is optional, never required.
142
+ anyOf:
143
+ - type: string
144
+ - type: "null"
114
145
  updatedAt:
115
146
  type: string
116
147
  description: ISO-8601 timestamp of last mutation.
@@ -170,6 +201,7 @@ GetConfigResponse:
170
201
  - id
171
202
  - name
172
203
  - description
204
+ - folder
173
205
  - schema
174
206
  - updatedAt
175
207
  - envs
@@ -191,12 +223,26 @@ CreateConfigRequest:
191
223
  additionalProperties: {}
192
224
  description: JSON Schema (draft 2020-12) describing the shape of the config value. Top-level `type` must be `'object'`; every published value is validated against this schema.
193
225
  value:
226
+ type: object
227
+ additionalProperties: {}
194
228
  description: "Initial config value. Either a single JSON object applied to every env, or a `{ env: value }` map seeding per-env values. Must match `schema`. Defaults to `{}` on every env when omitted."
229
+ dev:
230
+ type: object
231
+ additionalProperties: {}
232
+ description: "Seed the **dev** env's initial value (version 1), overriding `value` for dev. Published immediately. Must match `schema`."
233
+ staging:
234
+ type: object
235
+ additionalProperties: {}
236
+ description: "Seed the **staging** env's initial value (version 1), overriding `value` for staging. Published immediately. Must match `schema`."
237
+ prod:
238
+ type: object
239
+ additionalProperties: {}
240
+ description: "Seed the **prod** env's initial value (version 1), overriding `value` for prod. Published immediately. Must match `schema`."
195
241
  required:
196
242
  - name
197
243
  - schema
198
244
  additionalProperties: false
199
- description: Body for `POST /api/admin/configs`. `name` + `schema` required.
245
+ description: "Body for `POST /api/admin/configs`. `name` + `schema` required. Per-env `dev`/`staging`/`prod` values are published to that env at version 1 (overriding `value`)."
200
246
  CreateConfigResponse:
201
247
  type: object
202
248
  properties:
@@ -219,11 +265,25 @@ UpdateConfigRequest:
219
265
  type: object
220
266
  additionalProperties: {}
221
267
  value:
222
- description: Flat value applied to **every** env. Publishes a new version per env. To target one env, use `PUT /{id}/drafts` then `POST /{id}/publish`.
268
+ type: object
269
+ additionalProperties: {}
270
+ description: Flat value applied to **every** env. Publishes a new version per env. To publish one env only, pass that env's key (`dev`/`staging`/`prod`) instead.
271
+ dev:
272
+ type: object
273
+ additionalProperties: {}
274
+ description: "Publish a new version to the **dev** env only, immediately (no draft). Overrides `value` for dev. Must match the effective schema."
275
+ staging:
276
+ type: object
277
+ additionalProperties: {}
278
+ description: "Publish a new version to the **staging** env only, immediately (no draft). Overrides `value` for staging. Must match the effective schema."
279
+ prod:
280
+ type: object
281
+ additionalProperties: {}
282
+ description: "Publish a new version to the **prod** env only, immediately (no draft). Overrides `value` for prod. Must match the effective schema."
223
283
  folder:
224
284
  $ref: ./common.yaml#/Folder
225
285
  additionalProperties: false
226
- description: Body for `PATCH /api/admin/configs/{id}`. Partial — only supplied fields change. `value` republishes on every env.
286
+ description: "Body for `PATCH /api/admin/configs/{id}`. Partial — only supplied fields change. `value` republishes on every env; per-env `dev`/`staging`/`prod` publish a new version to just that env."
227
287
  UpdateConfigResponse:
228
288
  type: object
229
289
  properties:
@@ -268,6 +328,8 @@ SaveConfigDraftRequest:
268
328
  env:
269
329
  $ref: ./common.yaml#/Env
270
330
  value:
331
+ type: object
332
+ additionalProperties: {}
271
333
  description: Draft value to stage on `env`. Validated against the config's current schema.
272
334
  required:
273
335
  - env
@@ -369,3 +431,29 @@ ListConfigActivityResponse:
369
431
  - createdAt
370
432
  additionalProperties: false
371
433
  description: Recent audit rows for one config, newest first.
434
+ ListConfigVersionsResponse:
435
+ type: array
436
+ items:
437
+ type: object
438
+ properties:
439
+ version:
440
+ type: integer
441
+ minimum: 1
442
+ maximum: 9007199254740991
443
+ description: Published version number on the requested env (monotonically increasing per env).
444
+ value:
445
+ description: The full JSON value that was published at this version.
446
+ publishedAt:
447
+ type: string
448
+ description: ISO-8601 publish timestamp.
449
+ publishedBy:
450
+ type: string
451
+ description: Email/id of the actor who published this version.
452
+ required:
453
+ - version
454
+ - value
455
+ - publishedAt
456
+ - publishedBy
457
+ additionalProperties: false
458
+ description: One published version of the config's value on the requested env.
459
+ description: Full published-value history for one (config, env), newest first. The config's schema is config-level and not versioned — this is value history only.
@@ -47,6 +47,9 @@ ConnectorRecord:
47
47
  - type: string
48
48
  - type: "null"
49
49
  description: "Display label for the connected account / target (e.g. the OAuth account email, or a trigger's idempotency key such as its repo url or routine id). `null` until the connector is authenticated/configured."
50
+ hasCredentials:
51
+ type: boolean
52
+ description: "Whether an encrypted credentials cipher is stored for this connector (`true` once OAuth/token setup completed). The cipher itself is never serialised — this boolean is the only signal. `false` for a fresh OAuth stub or a tokenless trigger."
50
53
  lastError:
51
54
  anyOf:
52
55
  - type: string
@@ -77,13 +80,14 @@ ConnectorRecord:
77
80
  - events
78
81
  - config
79
82
  - accountLabel
83
+ - hasCredentials
80
84
  - lastError
81
85
  - lastAttemptAt
82
86
  - lastSuccessAt
83
87
  - createdAt
84
88
  - updatedAt
85
89
  additionalProperties: false
86
- description: "A connector row. The encrypted credentials cipher backing the connector is intentionally never serialised."
90
+ description: "A connector row. The encrypted credentials cipher backing the connector is intentionally never serialised — `hasCredentials` reports only whether one is stored."
87
91
  ListConnectorsResponse:
88
92
  type: array
89
93
  items:
@@ -3,7 +3,7 @@ ErrorRecord:
3
3
  description: |-
4
4
  A tracked production error — one row per distinct issue, keyed by `fingerprint`. Rows are never created by hand: an ingestion path (worker log drain / the `see()` SDK reporter) folds each occurrence into the matching row, bumping `count` and `lastSeenAt`. The admin surface only lists them, reads one, and flips `status`.
5
5
 
6
- Field names are camelCase (the D1 row projected through Drizzle). Many columns are nullable because the reporting source may not supply them.
6
+ Field names are camelCase (the D1 row projected through Drizzle). Every row column is always present on the wire; many are *nullable* because the reporting source may not supply them — `null`, never absent. Only `occurrences` is conditional (detail reads only).
7
7
  properties:
8
8
  id:
9
9
  type: string
@@ -121,25 +121,62 @@ ErrorRecord:
121
121
  updatedAt:
122
122
  type: string
123
123
  description: ISO-8601 timestamp of the last mutation (e.g. a status flip).
124
+ assigneeId:
125
+ description: PERSON owner of the triage — a `users.id` (soft reference, same value space as a feedback item's `assigneeId`), or `null` if unassigned. Set from the ops cockpit's Owner column; independent of the agent half.
126
+ anyOf:
127
+ - type: string
128
+ - type: "null"
129
+ assigneeConnectorId:
130
+ description: AGENT owner — the id of a connected trigger connector (`connectors.id`), or `null`. Mutually exclusive with `assigneeAgent`.
131
+ anyOf:
132
+ - type: string
133
+ - type: "null"
134
+ assigneeAgent:
135
+ description: AGENT owner — a built-in hosted Shipeasy agent (`"jarvis"`, Enterprise-gated), or `null`. Mutually exclusive with `assigneeConnectorId`.
136
+ anyOf:
137
+ - type: string
138
+ - type: "null"
124
139
  required:
125
140
  - id
126
141
  - projectId
127
142
  - fingerprint
143
+ - causedByFingerprint
128
144
  - message
145
+ - errorType
146
+ - stack
147
+ - source
148
+ - url
149
+ - seenUrls
150
+ - subject
151
+ - outcome
152
+ - side
153
+ - env
154
+ - kind
155
+ - lastExtrasJson
156
+ - sdkVersion
129
157
  - count
130
158
  - status
131
159
  - firstSeenAt
132
160
  - lastSeenAt
133
161
  - createdAt
134
162
  - updatedAt
163
+ - assigneeId
164
+ - assigneeConnectorId
165
+ - assigneeAgent
135
166
  additionalProperties: false
136
167
  ErrorOccurrence:
137
168
  type: object
138
- description: One sampled instance behind a tracked error — the minimal per-occurrence payload (what varies between instances; everything else lives on the parent `ErrorRecord`).
169
+ description: One sampled instance behind a tracked error — the minimal per-occurrence payload (what varies between instances; everything else lives on the parent `ErrorRecord`). Every column is always present on the wire; nullable columns are `null`, never absent.
139
170
  properties:
140
171
  id:
141
172
  type: string
142
173
  description: Stable opaque occurrence id.
174
+ projectId:
175
+ type: string
176
+ description: Project this occurrence belongs to. Always echoes the parent error's `projectId` — redundant on this nested read (a projection candidate), kept because the raw row is returned as-is today.
177
+ errorId:
178
+ type: string
179
+ description: Id of the parent tracked error (`err_…`). Always echoes the enclosing `ErrorRecord.id` — redundant on this nested read (a projection candidate), kept because the raw row is returned as-is today.
143
180
  message:
144
181
  type: string
145
182
  description: This instance's raw message (unlike the fingerprint, never normalized).
@@ -182,7 +219,15 @@ ErrorOccurrence:
182
219
  description: ISO-8601 timestamp this instance was ingested.
183
220
  required:
184
221
  - id
222
+ - projectId
223
+ - errorId
185
224
  - message
225
+ - stack
226
+ - url
227
+ - env
228
+ - side
229
+ - sdkVersion
230
+ - extrasJson
186
231
  - sampleRate
187
232
  - seenAt
188
233
  additionalProperties: false
@@ -214,8 +259,10 @@ FileErrorTicketResponse:
214
259
  type: string
215
260
  description: Feedback ticket id.
216
261
  number:
217
- type: integer
218
- description: Human-facing per-project ticket number.
262
+ description: Human-facing per-project ticket number. `null` only on the idempotent dedupe path when the pre-existing ticket is a legacy row created before per-project numbering.
263
+ anyOf:
264
+ - type: integer
265
+ - type: "null"
219
266
  required:
220
267
  - id
221
268
  - number