{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/getvigilia-com/json-schema/getvigilia-com-incident-detail-schema.json",
  "title": "IncidentDetail",
  "x-generated": "2026-11-10",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/getvigilia-com-openapi.json#/components/schemas/IncidentDetail",
  "allOf": [
    {
      "$ref": "#/$defs/Incident"
    },
    {
      "type": "object",
      "properties": {
        "builder": {
          "type": "string"
        },
        "confidence": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "fixPrompt": {
          "type": "string",
          "description": "A paste-ready prompt for the app's builder, or for any coding agent."
        },
        "evidence": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "type": {
              "type": "string"
            },
            "message": {
              "type": "string"
            },
            "normalizedMessage": {
              "type": "string"
            },
            "page": {
              "type": [
                "string",
                "null"
              ],
              "description": "Where the visitor was — not necessarily where the fault is."
            },
            "pagePattern": {
              "type": "string"
            },
            "source": {
              "type": [
                "string",
                "null"
              ],
              "description": "Script, or for a failed request the endpoint that failed."
            },
            "line": {
              "type": [
                "integer",
                "null"
              ]
            },
            "column": {
              "type": [
                "integer",
                "null"
              ]
            },
            "httpStatus": {
              "type": [
                "integer",
                "null"
              ]
            },
            "stack": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "sourceStack": {
              "type": [
                "array",
                "null"
              ],
              "items": {
                "type": "string"
              },
              "description": "The top frames in the app's original code, resolved through its published source maps (e.g. `at src/pages/Checkout.tsx:42:7` with a few lines of source). Null when the app publishes no source maps."
            },
            "breadcrumbs": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "at": {
                    "type": "integer"
                  },
                  "type": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  }
                }
              }
            },
            "userAgent": {
              "type": [
                "string",
                "null"
              ]
            },
            "environment": {
              "type": "string",
              "enum": [
                "production",
                "development"
              ]
            },
            "count": {
              "type": "integer"
            },
            "sessions": {
              "type": "integer"
            },
            "firstSeenAt": {
              "type": "integer"
            },
            "lastSeenAt": {
              "type": "integer"
            }
          }
        }
      }
    }
  ],
  "$defs": {
    "Incident": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "appId": {
          "type": "string"
        },
        "kind": {
          "type": "string",
          "enum": [
            "error",
            "downtime",
            "health"
          ],
          "description": "error: errors from real visitors, diagnosed. downtime: the uptime checker. health: a recurring check of the app itself (secret keys in its public code, its certificate)."
        },
        "check": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "secrets",
            "certificate",
            "domain",
            "speed",
            null
          ],
          "description": "Health incidents: which check raised it. `speed`: the app answers several times slower than its usual."
        },
        "details": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Health incidents: the specifics, e.g. each exposed key, masked, and where it was found. Empty otherwise."
        },
        "endpoint": {
          "type": [
            "object",
            "null"
          ],
          "description": "Downtime incidents about one of the app's extra check URLs (a page such as checkout, or an API), rather than the whole app. Null otherwise.",
          "properties": {
            "url": {
              "type": "string"
            },
            "label": {
              "type": [
                "string",
                "null"
              ],
              "description": "The owner's name for it, e.g. Checkout."
            }
          },
          "required": [
            "url",
            "label"
          ]
        },
        "sentry": {
          "type": [
            "object",
            "null"
          ],
          "description": "The Sentry issue this incident explains, when it came through the Sentry bridge (Team). Null otherwise.",
          "properties": {
            "url": {
              "type": "string"
            }
          },
          "required": [
            "url"
          ]
        },
        "issue": {
          "type": [
            "object",
            "null"
          ],
          "description": "The issue opened for this incident in GitHub Issues, Linear or Jira (Team plan), by hand or automatically. Null when there is none.",
          "properties": {
            "tracker": {
              "type": "string",
              "enum": [
                "github",
                "linear",
                "jira"
              ]
            },
            "url": {
              "type": "string"
            },
            "key": {
              "type": "string",
              "description": "#123, ENG-45, SHOP-7"
            }
          },
          "required": [
            "tracker",
            "url",
            "key"
          ]
        },
        "related": {
          "type": [
            "object",
            "null"
          ],
          "description": "The same problem seen from the other side: for a request that failed with a 5xx in visitors' browsers, the server error behind it (side: server); for a server error, the failed request visitors saw (side: browser). Null when there is none.",
          "properties": {
            "side": {
              "type": "string",
              "enum": [
                "server",
                "browser"
              ]
            },
            "incidentId": {
              "type": [
                "string",
                "null"
              ]
            },
            "title": {
              "type": "string"
            },
            "count": {
              "type": "integer"
            }
          },
          "required": [
            "side",
            "incidentId",
            "title",
            "count"
          ]
        },
        "severity": {
          "type": "string",
          "enum": [
            "critical",
            "high",
            "medium",
            "low"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "open",
            "resolved",
            "ignored"
          ]
        },
        "title": {
          "type": "string"
        },
        "summary": {
          "type": "string",
          "description": "What broke, in plain language."
        },
        "userImpact": {
          "type": "string",
          "description": "Who is affected and how."
        },
        "occurrences": {
          "type": [
            "integer",
            "null"
          ]
        },
        "sessions": {
          "type": [
            "integer",
            "null"
          ]
        },
        "isRegression": {
          "type": "boolean",
          "description": "It was marked fixed and came back."
        },
        "createdAt": {
          "type": "integer"
        },
        "updatedAt": {
          "type": "integer"
        },
        "resolvedAt": {
          "type": [
            "integer",
            "null"
          ]
        },
        "fix": {
          "type": "object",
          "properties": {
            "watch": {
              "type": [
                "string",
                "null"
              ],
              "enum": [
                "watching",
                "verified",
                "not_enough_traffic",
                "unverified",
                null
              ],
              "description": "`watching` until there is a verdict. `verified`: the error stayed away through enough traffic that it would very likely have shown again. `not_enough_traffic`: watched for 7 days without enough traffic to say either way. `unverified` is the same outcome as recorded before October 2026."
            },
            "verifiedAt": {
              "type": [
                "integer",
                "null"
              ]
            },
            "evidence": {
              "type": [
                "object",
                "null"
              ],
              "description": "The traffic behind the verdict, or behind the wait so far. Null until the watch is first examined, 24 hours after the incident is resolved.",
              "properties": {
                "expectedErrors": {
                  "type": "number",
                  "description": "How many times the error would have shown up since the fix, had the fix done nothing: its rate per visit in the week before the fix, times the visits since. A fix is confirmed at 3 or more."
                },
                "visits": {
                  "type": "integer",
                  "description": "Production page loads since the incident was resolved."
                },
                "baselineHits": {
                  "type": "integer",
                  "description": "Sessions the error hit in the 7 days before the incident was resolved."
                },
                "baselineVisits": {
                  "type": "integer",
                  "description": "Production page loads in those 7 days."
                },
                "measured": {
                  "type": "boolean",
                  "description": "False when traffic for this error cannot be counted yet (errors from the app's backend). Its fix then cannot be confirmed."
                },
                "countedAt": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "dashboardUrl": {
          "type": "string"
        },
        "afterDeploy": {
          "type": [
            "object",
            "null"
          ],
          "description": "The deploy this problem first appeared after, within a day. Timing, not blame.",
          "properties": {
            "at": {
              "type": "integer"
            },
            "label": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        },
        "providerOutage": {
          "type": [
            "object",
            "null"
          ],
          "description": "A platform the app depends on (Supabase, Vercel, OpenAI…) was reporting its own incident when this began, from its public status page. There may be nothing to fix in the app. `resolvedAt` is set once the provider marks it resolved; if the problem continues after that, the cause is likely the app's.",
          "properties": {
            "provider": {
              "type": "string"
            },
            "incident": {
              "type": "string",
              "description": "The provider's own title for its incident."
            },
            "level": {
              "type": "string",
              "enum": [
                "outage",
                "degraded"
              ]
            },
            "url": {
              "type": "string",
              "description": "The provider's status page for this incident."
            },
            "startedAt": {
              "type": "integer"
            },
            "resolvedAt": {
              "type": [
                "integer",
                "null"
              ]
            }
          }
        }
      }
    }
  }
}