{
  "openapi": "3.1.0",
  "info": {
    "title": "Sentinel DB 360 — Public API",
    "version": "0.3.1",
    "summary": "Curated public-facing endpoints for developer evaluation",
    "description": "Read-only snapshot of selected production endpoints. Internal admin, write, and destructive operations are intentionally omitted. Full API (24 routers, ~200+ endpoints) is available to licensed deployments via interactive Swagger at `/docs` on the running backend.\n\n**Versioning:** v2 endpoints are stable. Auth uses cookie `sd360_session` (HttpOnly) or `Authorization: Bearer <jwt>` header. License endpoints are public (offline verify).\n\n**Source repo:** github.com/dmcteknoloji/sentineldb360 (private, license required)",
    "contact": {
      "name": "DMC Bilgi Teknolojileri",
      "url": "https://sentineldb360.com",
      "email": "iletisim@dmcteknoloji.com"
    },
    "license": {
      "name": "Commercial license (per-instance)",
      "url": "https://sentineldb360.com/terms"
    }
  },
  "servers": [
    { "url": "https://your-deployment.example.com", "description": "Self-hosted (on-prem / VM)" },
    { "url": "https://saas.sentineldb360.com", "description": "SaaS (multi-tenant, ARCH-003 ownership scoped)" }
  ],
  "tags": [
    { "name": "Health", "description": "Liveness and readiness checks" },
    { "name": "Auth", "description": "JWT (HS256, 24h default) — cookie `sd360_session` or Bearer header" },
    { "name": "Sources", "description": "Database instance CRUD (MSSQL, PostgreSQL, MySQL, MongoDB)" },
    { "name": "Metrics", "description": "Time-series metrics from `metrics_ts` collection" },
    { "name": "Health Check", "description": "Per-engine A-F health scorecard (6 categories)" },
    { "name": "Capacity", "description": "Linear regression + 95% PI projections (storage, CPU, memory, connections)" },
    { "name": "Blocking", "description": "Blocking chain analysis with Sankey-ready output" },
    { "name": "Insights", "description": "AI-powered (LiteLLM / Ollama) findings and recommendations" },
    { "name": "License", "description": "Offline-first Ed25519 JWT license verification (JetBrains pattern)" },
    { "name": "Trial", "description": "14-day trial provisioning (Cloudflare Turnstile gated)" }
  ],
  "paths": {
    "/api/health": {
      "get": {
        "tags": ["Health"],
        "summary": "Liveness probe",
        "description": "Returns service status, version, and uptime. Useful for load balancer health checks.",
        "responses": {
          "200": {
            "description": "Service healthy",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/HealthResponse" },
                "example": { "status": "ok", "version": "0.3.1", "uptime_seconds": 184293, "mongodb": "connected" }
              }
            }
          }
        }
      }
    },
    "/api/auth/login": {
      "post": {
        "tags": ["Auth"],
        "summary": "Login with email + password",
        "description": "Returns JWT in HttpOnly cookie `sd360_session` (TTL: `ACCESS_TOKEN_TTL_SEC`, default 900s). Bcrypt password verification. Default role on bootstrap: `viewer`. Roles: `ADMIN`, `EDITOR`, `VIEWER`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/LoginRequest" },
              "example": { "email": "user@example.com", "password": "***" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Login successful — cookie set",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginResponse" } } }
          },
          "401": { "description": "Invalid credentials" },
          "423": { "description": "Account locked (failed login threshold)" }
        }
      }
    },
    "/api/auth/me": {
      "get": {
        "tags": ["Auth"],
        "summary": "Current user info",
        "security": [{ "cookieAuth": [] }, { "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "User profile",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } }
          },
          "401": { "description": "Not authenticated" }
        }
      }
    },
    "/api/v2/sources": {
      "get": {
        "tags": ["Sources"],
        "summary": "List configured database instances",
        "description": "Returns all sources visible to the authenticated user. Multi-tenant: ARCH-003 ownership filter applied automatically (`org_id` enforced via `$jsonSchema`).",
        "security": [{ "cookieAuth": [] }],
        "parameters": [
          { "name": "type", "in": "query", "description": "Filter by RDBMS type", "schema": { "$ref": "#/components/schemas/RDBMSType" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 100, "maximum": 500 } }
        ],
        "responses": {
          "200": {
            "description": "Source list",
            "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Source" } } } }
          }
        }
      }
    },
    "/api/v2/sources/{source_id}": {
      "get": {
        "tags": ["Sources"],
        "summary": "Get a single source",
        "security": [{ "cookieAuth": [] }],
        "parameters": [
          { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": { "description": "Source details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Source" } } } },
          "403": { "description": "Not owner of this source (ARCH-003)" },
          "404": { "description": "Source not found" }
        }
      }
    },
    "/api/v2/metrics/{source_id}/timeseries": {
      "get": {
        "tags": ["Metrics"],
        "summary": "Time-series metrics",
        "description": "Returns metric points from the `metrics_ts` collection. Aggregation buckets: 5m / 15m / 1h / 1d. Default window: last 24h (env: `METRIC_HISTORY_HOURS`).",
        "security": [{ "cookieAuth": [] }],
        "parameters": [
          { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
          { "name": "metric", "in": "query", "required": true, "schema": { "type": "string", "example": "cpu_percent" } },
          { "name": "from", "in": "query", "description": "ISO 8601 timestamp", "schema": { "type": "string", "format": "date-time" } },
          { "name": "to", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "bucket", "in": "query", "schema": { "type": "string", "enum": ["5m", "15m", "1h", "1d"], "default": "5m" } }
        ],
        "responses": {
          "200": {
            "description": "Time series points",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimeSeriesResponse" } } }
          }
        }
      }
    },
    "/api/v2/health-check/{source_id}/summary": {
      "get": {
        "tags": ["Health Check"],
        "summary": "A-F scorecard summary",
        "description": "Returns engine-specific health scorecard with 6 categories: Performance, Storage, Security, Availability, Backup, Configuration. Letter grades: 90+=A · 75+=B · 60+=C · 40+=D · <40=F.",
        "security": [{ "cookieAuth": [] }],
        "parameters": [
          { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": { "description": "Scorecard", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthCheckSummary" } } } }
        }
      }
    },
    "/api/v2/capacity/{source_id}/storage": {
      "get": {
        "tags": ["Capacity"],
        "summary": "Storage growth projection",
        "description": "Linear regression with 95% prediction interval over the last N days. Returns days-to-full estimate and recommended action. Min sample: 14 days of metric history.",
        "security": [{ "cookieAuth": [] }],
        "parameters": [
          { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
          { "name": "horizon_days", "in": "query", "schema": { "type": "integer", "default": 90, "minimum": 7, "maximum": 365 } }
        ],
        "responses": {
          "200": { "description": "Projection", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CapacityProjection" } } } }
        }
      }
    },
    "/api/v2/blocking/{source_id}/chains": {
      "get": {
        "tags": ["Blocking"],
        "summary": "Active blocking chains",
        "description": "Returns currently active blocking chains with head SPID, blocked sessions, wait time, and Sankey-ready edges. Threshold env: `BLOCKING_WARNING_THRESHOLD_MS`.",
        "security": [{ "cookieAuth": [] }],
        "parameters": [
          { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
          { "name": "min_wait_ms", "in": "query", "schema": { "type": "integer", "default": 5000 } }
        ],
        "responses": {
          "200": { "description": "Blocking chains", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlockingChainsResponse" } } } }
        }
      }
    },
    "/api/v2/insights/{source_id}": {
      "get": {
        "tags": ["Insights"],
        "summary": "AI insights and findings",
        "description": "Returns LiteLLM-generated insights (default Azure OpenAI gpt-4o-mini, falls back to rule-based advisor). Language follows `AI_LANG` env (default: `tr`).",
        "security": [{ "cookieAuth": [] }],
        "parameters": [
          { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
          { "name": "severity", "in": "query", "schema": { "type": "string", "enum": ["low", "medium", "high", "critical"] } }
        ],
        "responses": {
          "200": { "description": "Findings", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Finding" } } } } }
        }
      }
    },
    "/api/license/verify": {
      "post": {
        "tags": ["License"],
        "summary": "Verify license token (offline)",
        "description": "Public endpoint. Verifies Ed25519 JWT against embedded public key. No network round-trip to DMC infrastructure required at runtime — JetBrains pattern. Returns validity, days remaining, and feature flags.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/LicenseVerifyRequest" },
              "example": { "token": "eyJhbGciOiJFZERTQSI..." }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification result",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LicenseVerifyResponse" } } }
          }
        }
      }
    },
    "/api/license/public-key": {
      "get": {
        "tags": ["License"],
        "summary": "License public key (Ed25519, PEM)",
        "description": "Public endpoint. Returns the Ed25519 public key in PEM format for offline JWT verification by client-side tools (e.g. `tools/issue_license.py verify`).",
        "responses": {
          "200": {
            "description": "PEM-encoded public key",
            "content": {
              "application/x-pem-file": { "schema": { "type": "string" }, "example": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA...\n-----END PUBLIC KEY-----\n" }
            }
          }
        }
      }
    },
    "/api/trial": {
      "post": {
        "tags": ["Trial"],
        "summary": "Request 14-day trial license",
        "description": "Public endpoint. Cloudflare Turnstile gated + honeypot + duplicate-email check (`TRIAL_MAX_PER_EMAIL`, default 2). Persists request to Cosmos `trial_requests` with `pending` status — admin must approve via `tools/approve_trial.py`. Successful approval delivers Ed25519 JWT (TRIAL tier: 14 days, max 50 instances, all 17 features enabled).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/TrialRequest" }
            }
          }
        },
        "responses": {
          "202": { "description": "Request accepted, awaiting admin approval", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TrialResponse" } } } },
          "400": { "description": "Validation error (Turnstile / honeypot / duplicate)" },
          "429": { "description": "Rate limited" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "cookieAuth": { "type": "apiKey", "in": "cookie", "name": "sd360_session", "description": "JWT (HS256) signed with `JWT_SECRET`. Set via `/api/auth/login`. HttpOnly, SameSite=Lax." },
      "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT", "description": "Fallback when cookie unavailable (CLI, third-party clients)." }
    },
    "schemas": {
      "HealthResponse": {
        "type": "object",
        "required": ["status", "version"],
        "properties": {
          "status": { "type": "string", "enum": ["ok", "degraded", "down"] },
          "version": { "type": "string", "example": "0.3.1" },
          "uptime_seconds": { "type": "integer" },
          "mongodb": { "type": "string", "enum": ["connected", "disconnected"] }
        }
      },
      "LoginRequest": {
        "type": "object",
        "required": ["email", "password"],
        "properties": {
          "email": { "type": "string", "format": "email" },
          "password": { "type": "string", "format": "password", "minLength": 8 }
        }
      },
      "LoginResponse": {
        "type": "object",
        "properties": {
          "user": { "$ref": "#/components/schemas/User" },
          "expires_at": { "type": "string", "format": "date-time" }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "email": { "type": "string", "format": "email" },
          "role": { "type": "string", "enum": ["ADMIN", "EDITOR", "VIEWER"] },
          "is_active": { "type": "boolean" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "RDBMSType": { "type": "string", "enum": ["MSSQL", "PostgreSQL", "MySQL", "MongoDB"] },
      "Source": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string", "example": "prod-mssql-01" },
          "type": { "$ref": "#/components/schemas/RDBMSType" },
          "host": { "type": "string", "example": "10.0.0.42" },
          "port": { "type": "integer", "example": 1433 },
          "database": { "type": "string", "example": "ProductionDB" },
          "tags": { "type": "array", "items": { "type": "string" } },
          "is_active": { "type": "boolean" }
        }
      },
      "TimeSeriesPoint": {
        "type": "object",
        "properties": {
          "ts": { "type": "string", "format": "date-time" },
          "value": { "type": "number" }
        }
      },
      "TimeSeriesResponse": {
        "type": "object",
        "properties": {
          "metric": { "type": "string" },
          "bucket": { "type": "string" },
          "points": { "type": "array", "items": { "$ref": "#/components/schemas/TimeSeriesPoint" } }
        }
      },
      "HealthCheckSummary": {
        "type": "object",
        "properties": {
          "source_id": { "type": "string", "format": "uuid" },
          "overall_grade": { "type": "string", "enum": ["A", "B", "C", "D", "F"] },
          "overall_score": { "type": "number", "minimum": 0, "maximum": 100 },
          "categories": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": { "type": "string", "enum": ["performance", "storage", "security", "availability", "backup", "configuration"] },
                "grade": { "type": "string", "enum": ["A", "B", "C", "D", "F"] },
                "score": { "type": "number" },
                "issues_count": { "type": "integer" }
              }
            }
          }
        }
      },
      "CapacityProjection": {
        "type": "object",
        "properties": {
          "metric": { "type": "string", "example": "storage_used_gb" },
          "current_value": { "type": "number" },
          "slope_per_day": { "type": "number" },
          "days_to_threshold": { "type": "integer", "nullable": true },
          "threshold_pct": { "type": "number", "example": 90 },
          "ci_lower_95": { "type": "number" },
          "ci_upper_95": { "type": "number" },
          "recommendation": { "type": "string" }
        }
      },
      "BlockingChainsResponse": {
        "type": "object",
        "properties": {
          "source_id": { "type": "string", "format": "uuid" },
          "captured_at": { "type": "string", "format": "date-time" },
          "chains": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "head_spid": { "type": "integer" },
                "head_sql_text_hash": { "type": "string" },
                "blocked_count": { "type": "integer" },
                "max_wait_ms": { "type": "integer" },
                "edges": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "from_spid": { "type": "integer" },
                      "to_spid": { "type": "integer" },
                      "wait_ms": { "type": "integer" }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "Finding": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "severity": { "type": "string", "enum": ["low", "medium", "high", "critical"] },
          "category": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": "string" },
          "recommendation": { "type": "string" },
          "ai_generated": { "type": "boolean" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "LicenseVerifyRequest": {
        "type": "object",
        "required": ["token"],
        "properties": { "token": { "type": "string", "description": "Ed25519-signed JWT" } }
      },
      "LicenseVerifyResponse": {
        "type": "object",
        "properties": {
          "valid": { "type": "boolean" },
          "tier": { "type": "string", "enum": ["TRIAL", "STARTER", "PRO", "ENTERPRISE"] },
          "days_left": { "type": "integer" },
          "max_instances": { "type": "integer" },
          "features": { "type": "array", "items": { "type": "string" } },
          "expires_at": { "type": "string", "format": "date-time" },
          "error": { "type": "string", "nullable": true }
        }
      },
      "TrialRequest": {
        "type": "object",
        "required": ["full_name", "email", "company", "instance_count_band", "engines", "turnstile_token"],
        "properties": {
          "full_name": { "type": "string", "minLength": 2 },
          "email": { "type": "string", "format": "email" },
          "company": { "type": "string" },
          "phone": { "type": "string", "nullable": true },
          "instance_count_band": { "type": "string", "enum": ["1-5", "5-20", "20-50", "50+"] },
          "engines": { "type": "array", "items": { "$ref": "#/components/schemas/RDBMSType" } },
          "use_case": { "type": "string", "nullable": true },
          "turnstile_token": { "type": "string" },
          "honeypot": { "type": "string", "nullable": true, "description": "Must remain empty — silent reject if filled" }
        }
      },
      "TrialResponse": {
        "type": "object",
        "properties": {
          "request_id": { "type": "string", "format": "uuid" },
          "status": { "type": "string", "enum": ["pending"] },
          "message": { "type": "string" }
        }
      }
    }
  },
  "x-snapshot-info": {
    "generated_at": "2026-05-08",
    "snapshot_of_version": "0.3.1",
    "endpoints_total_in_production": "200+",
    "endpoints_curated_here": 12,
    "note": "This is a developer-evaluation snapshot. Live deployments expose the full API at /docs (Swagger UI) and /redoc."
  }
}
