{
  "openapi": "3.0.3",
  "info": {
    "title": "sec-scan API",
    "description": "API for the sec-scan PHP security scanner. Analyze PHP files for vulnerabilities using AI-powered two-phase analysis.\n\nAuthenticate with a Bearer token (`sc_` prefix) generated from the dashboard.",
    "version": "1.0.0",
    "contact": {
      "name": "ScaleCommerce GmbH",
      "url": "https://scale.sc",
      "email": "support@scale.sc"
    }
  },
  "servers": [
    {
      "url": "/",
      "description": "Current server"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Scanning",
      "description": "Core scanning endpoints - lookup cached results and submit files for analysis"
    }
  ],
  "paths": {
    "/api/files/lookup": {
      "post": {
        "tags": ["Scanning"],
        "summary": "Lookup cached results",
        "description": "Check if files have already been analyzed by submitting their SHA256 checksums. Returns cached results for known files and lists unknown checksums that need analysis.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["checksums"],
                "properties": {
                  "checksums": {
                    "type": "array",
                    "items": { "type": "string" },
                    "description": "Array of SHA256 checksums to look up",
                    "example": ["a1b2c3d4e5f6...", "f6e5d4c3b2a1..."]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lookup results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "object",
                      "additionalProperties": {
                        "$ref": "#/components/schemas/FileResult"
                      },
                      "description": "Map of checksum to analysis result for known files"
                    },
                    "unknown": {
                      "type": "array",
                      "items": { "type": "string" },
                      "description": "Checksums not yet analyzed"
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": {
            "description": "Lookup rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/files/analyze": {
      "post": {
        "tags": ["Scanning"],
        "summary": "Analyze files",
        "description": "Submit PHP files for two-phase AI security analysis. Phase 1 performs fast triage, Phase 2 runs deep analysis on suspicious files only. Results are cached globally by content hash.\n\nRate limits apply per token (default: 1000 analyses/day). Force re-analysis counts against the same analyze limit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["files"],
                "properties": {
                  "files": {
                    "type": "array",
                    "maxItems": 50,
                    "items": {
                      "type": "object",
                      "required": ["checksum", "path", "size", "content"],
                      "properties": {
                        "checksum": {
                          "type": "string",
                          "description": "SHA256 hash of file content"
                        },
                        "path": {
                          "type": "string",
                          "description": "File path (used for display)",
                          "example": "src/Controller/SearchController.php"
                        },
                        "size": {
                          "type": "integer",
                          "description": "File size in bytes"
                        },
                        "content": {
                          "type": "string",
                          "description": "PHP source code (max 500KB, truncated beyond)"
                        }
                      }
                    }
                  },
                  "framework": {
                    "type": "string",
                    "description": "PHP framework hint for better analysis accuracy",
                    "example": "OXID eShop 6.x",
                    "enum": ["OXID eShop 6", "OXID eShop 7", "Shopware 5", "Shopware 6", "Magento 1", "Magento 2", "WordPress/WooCommerce", "JTL-Shop 5", "PrestaShop", "Sylius", "Laravel", "Symfony"]
                  },
                  "force": {
                    "type": "boolean",
                    "default": false,
                    "description": "Force re-analysis even if already cached"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Analysis results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "object",
                      "additionalProperties": {
                        "$ref": "#/components/schemas/AnalyzeResult"
                      },
                      "description": "Map of checksum to analysis result"
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API token with `sc_` prefix. Generate one from the dashboard under API Tokens."
      }
    },
    "schemas": {
      "AnalyzeResult": {
        "type": "object",
        "description": "Result from the analyze endpoint (verdict only)",
        "properties": {
          "secure": {
            "type": "string",
            "enum": ["yes", "no", "warning", "error"],
            "description": "Whether the file is secure"
          },
          "risk": {
            "type": "string",
            "enum": ["low", "medium", "high", "critical"],
            "description": "Risk level (only meaningful when secure=no)"
          },
          "details": {
            "type": "string",
            "description": "Human-readable analysis details"
          }
        }
      },
      "FileResult": {
        "type": "object",
        "description": "Result from the lookup endpoint (verdict + metadata)",
        "properties": {
          "secure": {
            "type": "string",
            "enum": ["yes", "no", "warning", "error"],
            "description": "Whether the file is secure"
          },
          "risk": {
            "type": "string",
            "enum": ["low", "medium", "high", "critical"],
            "description": "Risk level (only meaningful when secure=no)"
          },
          "details": {
            "type": "string",
            "description": "Human-readable analysis details"
          },
          "fileSize": {
            "type": "integer",
            "description": "File size in bytes"
          },
          "firstSeenAt": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp of when the file was first seen"
          },
          "analyzedAt": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp of the most recent analysis"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "statusCode": { "type": "integer" },
          "message": { "type": "string" }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid authentication",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      }
    }
  }
}
