{
  "openapi": "3.1.1",
  "info": {
    "title": "KenoKoch.de API",
    "description": "Öffentliche Endpunkte der Bewerbungsseite von Keno Koch – ASP.NET Core Minimal APIs. Jedes Modul des modularen Monolithen bringt seine eigenen Endpunkte mit.",
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://kenokoch.de/"
    }
  ],
  "paths": {
    "/api/modules": {
      "get": {
        "tags": [
          "Plattform"
        ],
        "summary": "Module des modularen Monolithen",
        "description": "Alle registrierten Module mit Datenbankschema, Migrationen, Events und Endpunkten – ermittelt zur Laufzeit.",
        "operationId": "GetModules",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ModuleInfo"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/runtime": {
      "get": {
        "tags": [
          "Plattform"
        ],
        "summary": "Laufzeit- und Hosting-Informationen",
        "description": "Azure-Region, .NET-Version, Speicher, Datenbank-Latenz und Build-Informationen.",
        "operationId": "GetRuntime",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RuntimeSnapshot"
                }
              }
            }
          }
        }
      }
    },
    "/api/profile": {
      "get": {
        "tags": [
          "Profil"
        ],
        "summary": "Lebenslauf als JSON",
        "description": "Liefert den kompletten Lebenslauf inklusive Stationen, Skills und Sprachen.",
        "operationId": "GetProfile",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileData"
                }
              }
            }
          }
        }
      }
    },
    "/api/profile/skills": {
      "get": {
        "tags": [
          "Profil"
        ],
        "summary": "Skills nach Kategorien",
        "operationId": "GetSkills",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SkillGroup"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/guestbook": {
      "get": {
        "tags": [
          "Gästebuch"
        ],
        "summary": "Freigegebene Gästebucheinträge",
        "description": "Liefert die neuesten freigegebenen Einträge aus Azure SQL (Parameter take: 1–50).",
        "operationId": "GetGuestbookEntries",
        "parameters": [
          {
            "name": "take",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GuestbookApiResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/stats": {
      "get": {
        "tags": [
          "Besucher & Echtzeit"
        ],
        "summary": "Live-Besucherstatistik",
        "description": "Besucher online (Blazor-Circuits), Seitenaufrufe heute und gesamt, Verlauf der letzten 14 Tage.",
        "operationId": "GetStats",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatsApiResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/plc/status": {
      "get": {
        "tags": [
          "SPS-Simulator"
        ],
        "summary": "Laufende Besucher-SPSen",
        "operationId": "GetPlcStatus",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlcStatusResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/plc/program": {
      "get": {
        "tags": [
          "SPS-Simulator"
        ],
        "summary": "SCL-Quelltext des Funktionsbausteins FB_TankControl",
        "operationId": "GetPlcProgram",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BuildDetails": {
        "required": [
          "version",
          "commit",
          "builtAt"
        ],
        "type": "object",
        "properties": {
          "version": {
            "type": "string"
          },
          "commit": {
            "type": [
              "null",
              "string"
            ]
          },
          "builtAt": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          }
        }
      },
      "DailyCount": {
        "required": [
          "date",
          "count"
        ],
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          }
        }
      },
      "DatabaseInfo": {
        "required": [
          "status",
          "message",
          "latencyMilliseconds",
          "engine",
          "serviceObjective",
          "serverVersion",
          "databaseName",
          "authentication"
        ],
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "message": {
            "type": [
              "null",
              "string"
            ]
          },
          "latencyMilliseconds": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "engine": {
            "type": [
              "null",
              "string"
            ]
          },
          "serviceObjective": {
            "type": [
              "null",
              "string"
            ]
          },
          "serverVersion": {
            "type": [
              "null",
              "string"
            ]
          },
          "databaseName": {
            "type": [
              "null",
              "string"
            ]
          },
          "authentication": {
            "type": "string"
          }
        }
      },
      "EducationEntry": {
        "required": [
          "period",
          "title",
          "institution"
        ],
        "type": "object",
        "properties": {
          "period": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "institution": {
            "type": "string"
          },
          "details": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ExperienceEntry": {
        "required": [
          "period",
          "role",
          "company",
          "summary"
        ],
        "type": "object",
        "properties": {
          "period": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "location": {
            "type": [
              "null",
              "string"
            ]
          },
          "kind": {
            "type": "string"
          },
          "current": {
            "type": "boolean"
          },
          "summary": {
            "type": "string"
          },
          "achievements": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tech": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "GuestbookApiEntry": {
        "required": [
          "name",
          "company",
          "role",
          "message",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "company": {
            "type": [
              "null",
              "string"
            ]
          },
          "role": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "GuestbookApiResponse": {
        "required": [
          "total",
          "entries",
          "queryMilliseconds"
        ],
        "type": "object",
        "properties": {
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "entries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GuestbookApiEntry"
            }
          },
          "queryMilliseconds": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          }
        }
      },
      "HostingInfo": {
        "required": [
          "platform",
          "isAzure",
          "region",
          "siteName",
          "instanceId",
          "plan"
        ],
        "type": "object",
        "properties": {
          "platform": {
            "type": "string"
          },
          "isAzure": {
            "type": "boolean"
          },
          "region": {
            "type": [
              "null",
              "string"
            ]
          },
          "siteName": {
            "type": [
              "null",
              "string"
            ]
          },
          "instanceId": {
            "type": [
              "null",
              "string"
            ]
          },
          "plan": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "LanguageSkill": {
        "required": [
          "name",
          "level"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "level": {
            "type": "string"
          }
        }
      },
      "ModuleEndpointInfo": {
        "required": [
          "method",
          "route",
          "summary"
        ],
        "type": "object",
        "properties": {
          "method": {
            "type": "string"
          },
          "route": {
            "type": "string"
          },
          "summary": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ModuleInfo": {
        "required": [
          "name",
          "displayName",
          "description",
          "assembly",
          "version",
          "databaseSchema",
          "migrations",
          "publishedEvents",
          "handledEvents",
          "endpoints",
          "componentCount",
          "dependencies"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "assembly": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "databaseSchema": {
            "type": [
              "null",
              "string"
            ]
          },
          "migrations": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "publishedEvents": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "handledEvents": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "endpoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModuleEndpointInfo"
            }
          },
          "componentCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "dependencies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "PageCount": {
        "required": [
          "path",
          "count"
        ],
        "type": "object",
        "properties": {
          "path": {
            "type": "string"
          },
          "count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          }
        }
      },
      "PlcStatusResponse": {
        "required": [
          "activeSessions",
          "maxSessions",
          "cycleTimeMilliseconds"
        ],
        "type": "object",
        "properties": {
          "activeSessions": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "maxSessions": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "cycleTimeMilliseconds": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          }
        }
      },
      "ProcessInfo": {
        "required": [
          "operatingSystem",
          "framework",
          "architecture",
          "processorCount",
          "uptime",
          "workingSetBytes",
          "managedHeapBytes",
          "gen0Collections",
          "gen1Collections",
          "gen2Collections",
          "threadPoolThreads",
          "cpuPercent",
          "environment"
        ],
        "type": "object",
        "properties": {
          "operatingSystem": {
            "type": "string"
          },
          "framework": {
            "type": "string"
          },
          "architecture": {
            "type": "string"
          },
          "processorCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "uptime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "workingSetBytes": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "managedHeapBytes": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "gen0Collections": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "gen1Collections": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "gen2Collections": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "threadPoolThreads": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "cpuPercent": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "environment": {
            "type": "string"
          }
        }
      },
      "ProfileData": {
        "required": [
          "name",
          "firstName",
          "headline",
          "tagline",
          "location",
          "email"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "firstName": {
            "type": "string"
          },
          "headline": {
            "type": "string"
          },
          "tagline": {
            "type": "string"
          },
          "availability": {
            "type": [
              "null",
              "string"
            ]
          },
          "location": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "links": {
            "$ref": "#/components/schemas/ProfileLinks"
          },
          "cvUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "about": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "facts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProfileFact"
            }
          },
          "highlights": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProfileHighlight"
            }
          },
          "experience": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExperienceEntry"
            }
          },
          "education": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EducationEntry"
            }
          },
          "skillGroups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillGroup"
            }
          },
          "languages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LanguageSkill"
            }
          }
        }
      },
      "ProfileFact": {
        "required": [
          "icon",
          "label",
          "value"
        ],
        "type": "object",
        "properties": {
          "icon": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "value": {
            "type": "string"
          }
        }
      },
      "ProfileHighlight": {
        "required": [
          "icon",
          "title",
          "text"
        ],
        "type": "object",
        "properties": {
          "icon": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "text": {
            "type": "string"
          }
        }
      },
      "ProfileLinks": {
        "type": "object",
        "properties": {
          "gitHub": {
            "type": [
              "null",
              "string"
            ]
          },
          "linkedIn": {
            "type": [
              "null",
              "string"
            ]
          },
          "xing": {
            "type": [
              "null",
              "string"
            ]
          },
          "repository": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "RuntimeSnapshot": {
        "required": [
          "hosting",
          "process",
          "database",
          "build",
          "telemetryEnabled",
          "timestamp"
        ],
        "type": "object",
        "properties": {
          "hosting": {
            "$ref": "#/components/schemas/HostingInfo"
          },
          "process": {
            "$ref": "#/components/schemas/ProcessInfo"
          },
          "database": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/DatabaseInfo"
              }
            ]
          },
          "build": {
            "$ref": "#/components/schemas/BuildDetails"
          },
          "telemetryEnabled": {
            "type": "boolean"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SkillGroup": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "icon": {
            "type": "string"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "skills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillItem"
            }
          }
        }
      },
      "SkillItem": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "focus": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "StatsApiResponse": {
        "required": [
          "onlineNow",
          "peakToday",
          "pageViewsToday",
          "pageViewsTotal",
          "last14Days",
          "topPages",
          "plcStarts",
          "guestbookEntries",
          "database",
          "generatedAt"
        ],
        "type": "object",
        "properties": {
          "onlineNow": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "peakToday": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "pageViewsToday": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "pageViewsTotal": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "last14Days": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/DailyCount"
            }
          },
          "topPages": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/PageCount"
            }
          },
          "plcStarts": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "guestbookEntries": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "database": {
            "type": "string"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Plattform"
    },
    {
      "name": "Profil"
    },
    {
      "name": "Gästebuch"
    },
    {
      "name": "Besucher & Echtzeit"
    },
    {
      "name": "SPS-Simulator"
    }
  ]
}