{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://javascriptobfuscator.com/Docs/ai-wire-format.schema.json",
  "title": "JSO AI endpoints wire format",
  "description": "Request and response envelopes for the four /v1/ai/* endpoints: preset-suggest, compat-check, explain-error, usage. The wire format is identical in preview mode and LLM-backed mode — only the values of `provider`, `tokensIn`, `tokensOut`, and the internal `source` field change. Validate parsed responses against this schema in your client; if validation breaks, the API changed and your code should fail loudly rather than silently misinterpret.",
  "$defs": {
    "ErrorEnvelope": {
      "type": "object",
      "description": "All /v1/ai/* endpoints reply with this shape on failure, always at HTTP 200 — read `ok` to branch.",
      "required": ["ok", "error", "message"],
      "additionalProperties": false,
      "properties": {
        "ok":      { "type": "boolean", "const": false },
        "error":   { "type": "string", "enum": ["input_invalid", "method_not_allowed", "quota_exhausted", "auth_failed", "upstream_unavailable", "rate_limited"] },
        "message": { "type": "string" }
      }
    },
    "Confidence": { "type": "string", "enum": ["high", "medium", "low"] },
    "Severity":   { "type": "string", "enum": ["error", "warning", "info"] },
    "Tier":       { "type": "string", "enum": ["FreeTrial", "Basic", "Corporate", "Enterprise"] },
    "Provider":   { "type": "string", "enum": ["rule-based", "claude", "openai", "rule-based-fallback", "preview"] },

    "PresetSuggestRequest": {
      "type": "object",
      "required": ["APIKey", "APIPwd", "description"],
      "additionalProperties": true,
      "properties": {
        "APIKey":      { "type": "string", "minLength": 1, "description": "Base64-encoded API key." },
        "APIPwd":      { "type": "string", "minLength": 1, "description": "Base64-encoded API password." },
        "description": { "type": "string", "minLength": 1, "maxLength": 4096, "description": "Natural-language description of the app to be protected. Hard cap 4 KB." }
      }
    },
    "PresetSuggestResponse": {
      "type": "object",
      "required": ["ok", "previewMode", "suggestion", "provider", "tokensIn", "tokensOut"],
      "additionalProperties": false,
      "properties": {
        "ok":          { "type": "boolean", "const": true },
        "previewMode": { "type": "boolean" },
        "provider":    { "$ref": "#/$defs/Provider" },
        "tokensIn":    { "type": "integer", "minimum": 0 },
        "tokensOut":   { "type": "integer", "minimum": 0 },
        "suggestion": {
          "type": "object",
          "required": ["previewMode", "source", "config", "signals"],
          "additionalProperties": true,
          "properties": {
            "previewMode": { "type": "boolean" },
            "source":      { "type": "string" },
            "config":      { "type": "object", "description": "Suggested jso.config.json fragment. additionalProperties is open — the LLM may include keys the rule-based version doesn't." },
            "signals":     { "type": "array", "items": { "type": "string" }, "description": "Short reasoning bullets the assistant used to derive the config." }
          }
        }
      }
    },

    "CompatCheckRequest": {
      "type": "object",
      "required": ["APIKey", "APIPwd", "source"],
      "additionalProperties": true,
      "properties": {
        "APIKey":    { "type": "string", "minLength": 1 },
        "APIPwd":    { "type": "string", "minLength": 1 },
        "source":    { "type": "string", "minLength": 1, "maxLength": 524288, "description": "JS source to scan. Hard cap 512 KB." },
        "framework": { "type": "string", "description": "Optional framework hint: 'react', 'vue', 'angular', 'svelte', 'plain'." }
      }
    },
    "CompatCheckFinding": {
      "type": "object",
      "required": ["category", "severity", "line", "column", "message", "suggestedFix"],
      "additionalProperties": true,
      "properties": {
        "category":     { "type": "string" },
        "severity":     { "$ref": "#/$defs/Severity" },
        "line":         { "type": "integer", "minimum": 0 },
        "column":       { "type": "integer", "minimum": 0 },
        "snippet":      { "type": "string" },
        "message":      { "type": "string" },
        "suggestedFix": { "type": "string" }
      }
    },
    "CompatCheckResponse": {
      "type": "object",
      "required": ["ok", "previewMode", "report", "provider", "tokensIn", "tokensOut"],
      "additionalProperties": false,
      "properties": {
        "ok":          { "type": "boolean", "const": true },
        "previewMode": { "type": "boolean" },
        "provider":    { "$ref": "#/$defs/Provider" },
        "tokensIn":    { "type": "integer", "minimum": 0 },
        "tokensOut":   { "type": "integer", "minimum": 0 },
        "report": {
          "type": "object",
          "required": ["previewMode", "source", "summary", "findings"],
          "additionalProperties": true,
          "properties": {
            "previewMode": { "type": "boolean" },
            "source":      { "type": "string" },
            "summary": {
              "type": "object",
              "required": ["errors", "warnings", "infos"],
              "properties": {
                "errors":   { "type": "integer", "minimum": 0 },
                "warnings": { "type": "integer", "minimum": 0 },
                "infos":    { "type": "integer", "minimum": 0 }
              }
            },
            "findings": { "type": "array", "items": { "$ref": "#/$defs/CompatCheckFinding" } }
          }
        }
      }
    },

    "ExplainErrorRequest": {
      "type": "object",
      "required": ["APIKey", "APIPwd", "error"],
      "additionalProperties": true,
      "properties": {
        "APIKey": { "type": "string", "minLength": 1 },
        "APIPwd": { "type": "string", "minLength": 1 },
        "error":  { "type": "string", "minLength": 1, "maxLength": 65536, "description": "Runtime error message. Hard cap 64 KB." },
        "config": { "type": "string", "maxLength": 32768, "description": "Optional jso.config snippet for additional context. Hard cap 32 KB." }
      }
    },
    "ExplainErrorResponse": {
      "type": "object",
      "required": ["ok", "previewMode", "explanation", "provider", "tokensIn", "tokensOut"],
      "additionalProperties": false,
      "properties": {
        "ok":          { "type": "boolean", "const": true },
        "previewMode": { "type": "boolean" },
        "provider":    { "$ref": "#/$defs/Provider" },
        "tokensIn":    { "type": "integer", "minimum": 0 },
        "tokensOut":   { "type": "integer", "minimum": 0 },
        "explanation": {
          "type": "object",
          "required": ["previewMode", "source", "cause", "transform", "confidence", "explanation", "fix", "docsUrl"],
          "additionalProperties": true,
          "properties": {
            "previewMode": { "type": "boolean" },
            "source":      { "type": "string" },
            "cause":       { "type": "string", "description": "Short tag, e.g. 'name-mangling', 'member-rename', 'eval-disabled-csp'." },
            "transform":   { "type": "string", "description": "Human-readable JSO transform name." },
            "confidence":  { "$ref": "#/$defs/Confidence" },
            "explanation": { "type": "string" },
            "fix":         { "type": "string" },
            "docsUrl":     { "type": "string", "format": "uri-reference" }
          }
        }
      }
    },

    "UsageRequest": {
      "type": "object",
      "required": ["APIKey", "APIPwd"],
      "additionalProperties": true,
      "properties": {
        "APIKey": { "type": "string", "minLength": 1 },
        "APIPwd": { "type": "string", "minLength": 1 }
      }
    },
    "UsageResponse": {
      "type": "object",
      "required": ["ok", "previewMode", "tier", "billingMonth", "actionsUsed", "actionsCap", "actionsRemaining", "tokensUsed", "tokensCap", "tokensRemaining", "approxCostCents", "costCapCents", "costRemainingCents", "quotaRejections", "asOfUtc"],
      "additionalProperties": false,
      "properties": {
        "ok":                 { "type": "boolean", "const": true },
        "previewMode":        { "type": "boolean", "description": "true when the AI schema is not yet provisioned OR auth has not landed -- the response is FreeTrial-default-shape but counters reflect actual usage as soon as both are wired." },
        "tier":               { "$ref": "#/$defs/Tier" },
        "billingMonth":       { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "First day of the UTC billing month: YYYY-MM-DD." },
        "actionsUsed":        { "type": "integer", "minimum": 0 },
        "actionsCap":         { "type": "integer", "minimum": 0 },
        "actionsRemaining":   { "type": "integer", "minimum": 0, "description": "Pre-computed Max(0, actionsCap - actionsUsed). Reported as 0 when cap is 0 (unlimited tier or pre-provisioned account); clients reading actionsRemaining=0 with cap=0 should display 'unlimited', not 'exhausted'." },
        "tokensUsed":         { "type": "integer", "minimum": 0 },
        "tokensCap":          { "type": "integer", "minimum": 0 },
        "tokensRemaining":    { "type": "integer", "minimum": 0 },
        "approxCostCents":    { "type": "integer", "minimum": 0 },
        "costCapCents":       { "type": "integer", "minimum": 0 },
        "costRemainingCents": { "type": "integer", "minimum": 0 },
        "quotaRejections":    { "type": "integer", "minimum": 0 },
        "asOfUtc":            { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$", "description": "ISO 8601 UTC, second precision." }
      }
    },

    "CheckoutCreateRequest": {
      "type": "object",
      "description": "Body for /v1/ai/checkout-create.ashx. APIKey is optional when the request rides on an authenticated dashboard session cookie.",
      "required": ["tier"],
      "additionalProperties": true,
      "properties": {
        "APIKey":    { "type": "string", "minLength": 1 },
        "APIPwd":    { "type": "string", "minLength": 1 },
        "tier":      { "type": "string", "enum": ["Basic", "Corporate", "Enterprise"] },
        "returnUrl": { "type": "string", "format": "uri", "description": "Where Stripe redirects after successful payment. Defaults to /dashboard/AIUsage.aspx?subscribed=1." }
      }
    },
    "CheckoutCreateResponse": {
      "type": "object",
      "required": ["ok", "url", "sessionId"],
      "additionalProperties": false,
      "properties": {
        "ok":        { "type": "boolean", "const": true },
        "url":       { "type": "string", "format": "uri", "description": "Stripe Checkout Session URL the browser should redirect to." },
        "sessionId": { "type": "string", "description": "Stripe Session ID (cs_test_... / cs_live_...) for client-side tracking." }
      }
    },

    "PortalCreateRequest": {
      "type": "object",
      "description": "Body for /v1/ai/portal-create.ashx. APIKey is optional when the request rides on an authenticated dashboard session cookie.",
      "required": [],
      "additionalProperties": true,
      "properties": {
        "APIKey":    { "type": "string", "minLength": 1 },
        "APIPwd":    { "type": "string", "minLength": 1 },
        "returnUrl": { "type": "string", "format": "uri" }
      }
    },
    "PortalCreateResponse": {
      "type": "object",
      "required": ["ok", "url"],
      "additionalProperties": false,
      "properties": {
        "ok":  { "type": "boolean", "const": true },
        "url": { "type": "string", "format": "uri", "description": "Stripe Customer Portal session URL." }
      }
    }
  }
}
