{
  "openapi": "3.1.0",
  "info": {
    "title": "SageOx API",
    "version": "1.0.0",
    "description": "# API Reference\n\n## Overview\n\nSageOx is a platform that captures team knowledge from discussions, decisions, and work context into a Ledger (per-repo historical record) and Team Context (team-wide shared knowledge). The SageOx API provides programmatic access to manage repositories, recordings, notifications, and team data with high performance and reliability.\n\n## Base URLs\n\n| Environment | URL |\n|---|---|\n| Local Development | `http://localhost:3000` |\n| Test | `https://test.sageox.ai` |\n| Production | `https://sageox.ai` |\n\n## Authentication\n\nAll requests to the SageOx API require authentication via JWT tokens issued by the Better Auth service.\n\nInclude your token in the `Authorization` header:\n```\nAuthorization: Bearer <token>\n```\n\n**Initial Auth Flow (CLI)**\n- CLI initiates device flow to obtain initial credentials\n- Exchange device code for JWT token\n- Store token securely for subsequent API requests\n- Refresh token when expired\n\n**Authenticated Endpoints**\n- Pass JWT in `Authorization: Bearer <token>` header\n- Tokens contain user identity and team membership\n- Invalid or expired tokens return 401 Unauthorized\n\n## Response Format\n\n### Success\nStandard response format with optional pagination metadata:\n```json\n{\n  \"success\": true,\n  \"data\": { ... }\n}\n```\n\n### Error\nAll errors follow a consistent format:\n```json\n{\n  \"success\": false,\n  \"error\": \"Human-readable error description\"\n}\n```\n\n**Status Codes**\n- `400` — Bad Request: Invalid parameters or malformed request\n- `401` — Unauthorized: Missing or invalid authentication token\n- `403` — Forbidden: Insufficient permissions for this resource\n- `404` — Not Found: Resource does not exist\n- `409` — Conflict: Request conflicts with current state (e.g., duplicate)\n- `429` — Rate Limited: Too many requests; retry with backoff\n- `500` — Internal Error: Server error; contact support if persistent\n\n## Pagination\n\nList endpoints support cursor-based pagination via query parameters:\n\n**Query Parameters**\n- `limit` — Number of results per page (default: 20, max: 100)\n- `offset` — Number of results to skip (default: 0)\n\n**Response Metadata**\nList responses include pagination info:\n```json\n{\n  \"success\": true,\n  \"data\": [ ... ],\n  \"meta\": {\n    \"total\": 150,\n    \"limit\": 20,\n    \"offset\": 0,\n    \"hasMore\": true\n  }\n}\n```\n\n## ID Formats\n\nResources use standardized ID formats for easy identification:\n\n| Resource | Format | Length | Example |\n|---|---|---|---|\n| Team | `team_<cuid2>` | 10 chars | `team_abc1234567` |\n| User | `usr_<cuid2>` | 10 chars | `usr_xyz9876543` |\n| Repository | `repo_<uuidv7>` | 36 chars | `repo_01934f5a-8b9c-7def-abcd-0123456789ab` |\n| Recording | `rec_<uuidv7>` | 36 chars | `rec_01934f5a-8b9c-7def-abcd-0123456789ab` |\n| Image | `img_<uuidv7>` | 36 chars | `img_01934f5a-8b9c-7def-abcd-0123456789ab` |\n| Notification | `notif_<cuid2>` | 14 chars | `notif_ab1cd2ef3g` |\n\nUse these IDs for all API operations. IDs are unique across environments.\n\n## Rate Limiting\n\nThe API applies rate limiting to protect against abuse and ensure fair access:\n\n**Authenticated Endpoints**\n- Limited per user: depends on subscription tier\n- Quota resets hourly\n\n**Unauthenticated Endpoints**\n- Limited per IP address\n- More restrictive than authenticated limits\n\nWhen rate limited, the API returns `429 Too Many Requests`. Retry requests with exponential backoff:\n```\nwait = min(2^attempt * 100ms, 10s)\n```\n\n## Timestamps\n\nAll timestamps in API responses use RFC 3339 / ISO 8601 format in UTC:\n```\n2025-12-03T10:30:00Z\n```\n\nUse this format when providing timestamps in requests as well. The API rejects timestamps in other formats.\n\n## SDKs & Tools\n\n- **OpenAPI Spec** — Full schema available at `/api/openapi.json`\n- **Postman Collection** — Import from `/api/postman.json` for interactive exploration\n- **CLI** — Use `ox` CLI for command-line access\n",
    "contact": {
      "name": "SageOx Team"
    },
    "license": {
      "name": "MIT"
    }
  },
  "servers": [
    {
      "url": "http://localhost:3000",
      "description": "Devcontainer"
    },
    {
      "url": "https://test.sageox.ai",
      "description": "Test"
    },
    {
      "url": "https://sageox.ai",
      "description": "Production"
    }
  ],
  "paths": {
    "/live": {
      "get": {
        "operationId": "getLiveness",
        "summary": "Liveness probe",
        "description": "Returns basic service health status to indicate the service is running",
        "tags": [
          "Health"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Service is alive",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "timestamp"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ],
                      "example": "ok"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time",
                      "description": "ISO 8601 timestamp",
                      "example": "2025-12-03T18:45:30Z"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/ready": {
      "get": {
        "operationId": "getReadiness",
        "summary": "Readiness probe",
        "description": "Returns detailed service readiness status including dependency health checks",
        "tags": [
          "Health"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Service readiness status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ready",
                    "timestamp",
                    "checks"
                  ],
                  "properties": {
                    "ready": {
                      "type": "boolean",
                      "description": "Whether the service is ready to accept traffic",
                      "example": true
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time",
                      "description": "ISO 8601 timestamp",
                      "example": "2025-12-03T18:45:30Z"
                    },
                    "checks": {
                      "type": "object",
                      "required": [
                        "database"
                      ],
                      "properties": {
                        "database": {
                          "type": "string",
                          "description": "Database connectivity status",
                          "enum": [
                            "ok",
                            "error"
                          ],
                          "example": "ok"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service is not ready",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ready",
                    "timestamp",
                    "checks"
                  ],
                  "properties": {
                    "ready": {
                      "type": "boolean",
                      "example": false
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T18:45:30Z"
                    },
                    "checks": {
                      "type": "object",
                      "required": [
                        "database"
                      ],
                      "properties": {
                        "database": {
                          "type": "string",
                          "enum": [
                            "ok",
                            "error"
                          ],
                          "example": "error"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/logs/frontend": {
      "post": {
        "operationId": "postFrontendLogs",
        "summary": "Frontend log ingestion",
        "description": "Receives a batch of structured logs from the web frontend and forwards\nthem to the backend's slog pipeline tagged with `source=frontend`. Used\nby the BFF to capture client-side errors, console warnings, and lifecycle\nevents alongside server logs.\n",
        "tags": [
          "Logs"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "logs",
                  "timestamp"
                ],
                "properties": {
                  "logs": {
                    "type": "array",
                    "description": "Batch of frontend log entries.",
                    "items": {
                      "type": "object",
                      "required": [
                        "level",
                        "message",
                        "timestamp"
                      ],
                      "properties": {
                        "level": {
                          "type": "string",
                          "enum": [
                            "debug",
                            "info",
                            "warn",
                            "error"
                          ],
                          "description": "Log severity. Unknown values default to info on the server."
                        },
                        "message": {
                          "type": "string"
                        },
                        "timestamp": {
                          "type": "string",
                          "format": "date-time",
                          "description": "ISO 8601 timestamp captured at the client."
                        },
                        "context": {
                          "type": "string",
                          "description": "Optional logger name / module hint."
                        },
                        "meta": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "Free-form structured metadata merged into the server log line."
                        },
                        "url": {
                          "type": "string",
                          "description": "Page URL where the log was emitted."
                        },
                        "userAgent": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Wall-clock time the batch was sent."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Logs accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "received",
                    "timestamp"
                  ],
                  "properties": {
                    "received": {
                      "type": "integer",
                      "description": "Number of log entries received in this batch."
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request body"
          }
        }
      }
    },
    "/api/v1/auth/session": {
      "get": {
        "summary": "Get current session",
        "description": "Retrieves the current authenticated session and user information",
        "operationId": "getSession",
        "tags": [
          "Auth"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Session retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "session",
                    "user"
                  ],
                  "properties": {
                    "session": {
                      "type": "object",
                      "required": [
                        "id",
                        "expiresAt"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Session identifier",
                          "example": "01234567-89ab-cdef-0123-456789abcdef"
                        },
                        "expiresAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "Session expiration timestamp",
                          "example": "2025-12-03T18:00:00Z"
                        }
                      }
                    },
                    "user": {
                      "type": "object",
                      "required": [
                        "id",
                        "email"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "User identifier",
                          "example": "01234567-89ab-cdef-0123-456789abcdef"
                        },
                        "email": {
                          "type": "string",
                          "format": "email",
                          "description": "User email address",
                          "example": "user@example.com"
                        },
                        "name": {
                          "type": "string",
                          "nullable": true,
                          "description": "User display name",
                          "example": "John Doe"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/signout": {
      "post": {
        "summary": "Sign out",
        "description": "Terminates the current authenticated session",
        "operationId": "signOut",
        "tags": [
          "Auth"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully signed out",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "signedOut"
                  ],
                  "properties": {
                    "signedOut": {
                      "type": "boolean",
                      "description": "Indicates successful sign out",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications": {
      "get": {
        "summary": "List notifications",
        "description": "Retrieves paginated list of notifications for the authenticated user",
        "operationId": "getNotifications",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of notifications to return",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "example": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Number of notifications to skip for pagination",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "example": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Notifications retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "notifications",
                    "pagination"
                  ],
                  "properties": {
                    "notifications": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NotificationDTO"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/PaginationMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create notification",
        "description": "Creates a new notification for the authenticated user",
        "operationId": "createNotification",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "agentId",
                  "type",
                  "priority",
                  "title",
                  "message"
                ],
                "properties": {
                  "agentId": {
                    "type": "string",
                    "description": "ID of the agent creating the notification",
                    "example": "agent_5k6l7m8n9o0p1q2r"
                  },
                  "type": {
                    "type": "string",
                    "description": "Notification type",
                    "example": "info"
                  },
                  "priority": {
                    "type": "string",
                    "description": "Notification priority level",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "urgent"
                    ],
                    "example": "medium"
                  },
                  "title": {
                    "type": "string",
                    "description": "Notification title",
                    "example": "Task completed"
                  },
                  "message": {
                    "type": "string",
                    "description": "Notification message body",
                    "example": "Your task has been successfully completed"
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "additionalProperties": true,
                    "description": "Optional metadata associated with the notification"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Notification created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "notification"
                  ],
                  "properties": {
                    "notification": {
                      "$ref": "#/components/schemas/NotificationDTO"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/{id}": {
      "delete": {
        "summary": "Delete notification",
        "description": "Deletes a specific notification for the authenticated user",
        "operationId": "deleteNotification",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Notification ID",
            "required": true,
            "schema": {
              "type": "string",
              "example": "notif_9h8g7f6e5d4c3b2a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Notification deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "deleted"
                  ],
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "description": "Indicates successful deletion",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing or invalid notification ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Notification not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/{id}/read": {
      "put": {
        "summary": "Mark notification as read or unread",
        "description": "Updates the read status of a specific notification",
        "operationId": "updateNotificationRead",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Notification ID",
            "required": true,
            "schema": {
              "type": "string",
              "example": "notif_9h8g7f6e5d4c3b2a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "read"
                ],
                "properties": {
                  "read": {
                    "type": "boolean",
                    "description": "Read status to set",
                    "example": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Notification read status updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "updated"
                  ],
                  "properties": {
                    "updated": {
                      "type": "boolean",
                      "description": "Indicates successful update",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing or invalid parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Notification not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/stream": {
      "get": {
        "summary": "Server-Sent Events stream for real-time notifications",
        "description": "Establishes a persistent SSE connection to receive real-time notification updates",
        "operationId": "streamNotifications",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "SSE stream established successfully",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Server-Sent Events stream with JSON-encoded notification data",
                  "example": "data: {\"type\":\"connected\",\"message\":\"Connected to notification stream\"}\n\ndata: {\"id\":\"notif_9h8g7f6e5d4c3b2a\",\"userId\":\"user_2n3k4m5l6j7h8g9f\",\"agentId\":\"agent_5k6l7m8n9o0p1q2r\",\"type\":\"info\",\"priority\":\"medium\",\"title\":\"Task completed\",\"message\":\"Your task has been successfully completed\",\"read\":false,\"timestamp\":\"2025-12-03T10:30:00Z\"}\n\n:keepalive\n"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error - streaming not supported or connection failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/stats": {
      "get": {
        "summary": "Get notification statistics",
        "description": "Returns aggregated statistics about user notifications including totals, unread counts, and breakdowns by type and priority",
        "operationId": "getNotificationStats",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Notification statistics retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "unread"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total number of notifications",
                      "example": 15
                    },
                    "unread": {
                      "type": "integer",
                      "description": "Number of unread notifications",
                      "example": 3
                    },
                    "byType": {
                      "type": "object",
                      "description": "Notification counts grouped by type",
                      "additionalProperties": {
                        "type": "integer"
                      },
                      "example": {
                        "info": 8,
                        "warning": 5,
                        "error": 2
                      }
                    },
                    "byPriority": {
                      "type": "object",
                      "description": "Notification counts grouped by priority level",
                      "additionalProperties": {
                        "type": "integer"
                      },
                      "example": {
                        "low": 5,
                        "medium": 7,
                        "high": 2,
                        "urgent": 1
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/read-all": {
      "post": {
        "summary": "Mark all notifications as read",
        "description": "Marks all notifications for the authenticated user as read in a single operation",
        "operationId": "markAllNotificationsRead",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "All notifications marked as read successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "updated"
                  ],
                  "properties": {
                    "updated": {
                      "type": "boolean",
                      "description": "Indicates successful operation",
                      "example": true
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of notifications marked as read",
                      "example": 5
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/grouped": {
      "get": {
        "summary": "Get grouped notifications",
        "description": "Retrieves notifications grouped by type and source for compact display",
        "operationId": "getGroupedNotifications",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of notification groups to return",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Number of notification groups to skip for pagination",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "example": 0
            }
          },
          {
            "name": "lookback_hours",
            "in": "query",
            "description": "Number of hours to look back for notifications (default 168 for 7 days)",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 168,
              "example": 72
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Grouped notifications retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "type",
                          "count"
                        ],
                        "properties": {
                          "type": {
                            "type": "string",
                            "description": "Notification type",
                            "example": "task_completed"
                          },
                          "sourceType": {
                            "type": "string",
                            "description": "Source type for the notification group",
                            "example": "agent"
                          },
                          "sourceId": {
                            "type": "string",
                            "description": "Source ID",
                            "example": "agent_5k6l7m8n9o0p1q2r"
                          },
                          "count": {
                            "type": "integer",
                            "description": "Number of notifications in this group",
                            "example": 3
                          },
                          "lastNotification": {
                            "type": "string",
                            "description": "Most recent notification timestamp in the group",
                            "format": "date-time",
                            "example": "2025-12-03T10:30:00Z"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/PaginationMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/group-items": {
      "get": {
        "summary": "Get notification group items",
        "description": "Retrieves all individual notifications for a specific notification group (used for expanding/drilling into a group)",
        "operationId": "getNotificationGroupItems",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "description": "Notification type to fetch items for",
            "required": true,
            "schema": {
              "type": "string",
              "example": "task_completed"
            }
          },
          {
            "name": "source_type",
            "in": "query",
            "description": "Optional source type filter",
            "required": false,
            "schema": {
              "type": "string",
              "example": "agent"
            }
          },
          {
            "name": "source_id",
            "in": "query",
            "description": "Optional source ID filter",
            "required": false,
            "schema": {
              "type": "string",
              "example": "agent_5k6l7m8n9o0p1q2r"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of items to return",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50,
              "example": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Number of items to skip for pagination",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "example": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Notification group items retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "count"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NotificationDTO"
                      },
                      "description": "Array of notifications in the group"
                    },
                    "count": {
                      "type": "integer",
                      "description": "Total number of items in the group",
                      "example": 5
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing required type parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/bulk": {
      "delete": {
        "summary": "Bulk delete notifications",
        "description": "Deletes multiple notifications identified by their IDs in a single operation",
        "operationId": "bulkDeleteNotifications",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "notificationIds"
                ],
                "properties": {
                  "notificationIds": {
                    "type": "array",
                    "description": "Array of notification IDs to delete",
                    "items": {
                      "type": "string",
                      "example": "notif_9h8g7f6e5d4c3b2a"
                    },
                    "minItems": 1,
                    "example": [
                      "notif_9h8g7f6e5d4c3b2a",
                      "notif_8g7f6e5d4c3b2a1z",
                      "notif_7f6e5d4c3b2a1z0y"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Notifications deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "deleted"
                  ],
                  "properties": {
                    "deleted": {
                      "type": "integer",
                      "description": "Number of notifications deleted",
                      "example": 3
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid or empty notificationIds array",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/preferences": {
      "get": {
        "summary": "Get notification preferences",
        "description": "Retrieves comprehensive notification preferences for the authenticated user including per-channel and per-type settings",
        "operationId": "getNotificationPreferences",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Notification preferences retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "version",
                    "channels",
                    "types"
                  ],
                  "properties": {
                    "version": {
                      "type": "integer",
                      "description": "Preference schema version",
                      "example": 1
                    },
                    "channels": {
                      "type": "object",
                      "description": "Master channel preferences",
                      "required": [
                        "email",
                        "push",
                        "inApp"
                      ],
                      "properties": {
                        "email": {
                          "type": "boolean",
                          "description": "Email notifications enabled",
                          "example": true
                        },
                        "push": {
                          "type": "boolean",
                          "description": "Push notifications enabled",
                          "example": true
                        },
                        "inApp": {
                          "type": "boolean",
                          "description": "In-app notifications enabled",
                          "example": true
                        }
                      }
                    },
                    "types": {
                      "type": "object",
                      "description": "Per-type notification preferences",
                      "additionalProperties": {
                        "type": "object",
                        "required": [
                          "key",
                          "label",
                          "preferences"
                        ],
                        "properties": {
                          "key": {
                            "type": "string",
                            "description": "Notification type key",
                            "example": "task_completed"
                          },
                          "label": {
                            "type": "string",
                            "description": "Human-readable label",
                            "example": "Task Completed"
                          },
                          "description": {
                            "type": "string",
                            "description": "Description of the notification type",
                            "example": "Notifications when tasks are completed"
                          },
                          "category": {
                            "type": "string",
                            "description": "Category this type belongs to",
                            "example": "tasks"
                          },
                          "preferences": {
                            "type": "object",
                            "description": "Channel preferences for this type",
                            "properties": {
                              "email": {
                                "type": "boolean"
                              },
                              "push": {
                                "type": "boolean"
                              },
                              "inApp": {
                                "type": "boolean"
                              }
                            }
                          },
                          "alwaysOn": {
                            "type": "boolean",
                            "description": "Whether this notification type cannot be disabled",
                            "example": false
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update notification preferences",
        "description": "Updates notification preferences for channels and/or specific notification types",
        "operationId": "updateNotificationPreferences",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channels": {
                    "type": "object",
                    "description": "Master channel preferences to update",
                    "properties": {
                      "email": {
                        "type": "boolean",
                        "description": "Enable/disable email notifications"
                      },
                      "push": {
                        "type": "boolean",
                        "description": "Enable/disable push notifications"
                      },
                      "inApp": {
                        "type": "boolean",
                        "description": "Enable/disable in-app notifications"
                      }
                    }
                  },
                  "types": {
                    "type": "object",
                    "description": "Per-type preferences to update",
                    "additionalProperties": {
                      "type": "object",
                      "properties": {
                        "email": {
                          "type": "boolean"
                        },
                        "push": {
                          "type": "boolean"
                        },
                        "inApp": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "channels": {
                    "email": true,
                    "push": false,
                    "inApp": true
                  },
                  "types": {
                    "task_completed": {
                      "email": true,
                      "push": false
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Notification preferences updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "version",
                    "channels",
                    "types"
                  ],
                  "properties": {
                    "version": {
                      "type": "integer",
                      "description": "Preference schema version",
                      "example": 1
                    },
                    "channels": {
                      "type": "object",
                      "properties": {
                        "email": {
                          "type": "boolean"
                        },
                        "push": {
                          "type": "boolean"
                        },
                        "inApp": {
                          "type": "boolean"
                        }
                      }
                    },
                    "types": {
                      "type": "object",
                      "description": "Updated per-type preferences",
                      "additionalProperties": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid preference data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/preferences/master": {
      "get": {
        "summary": "Get master notification toggles",
        "description": "Returns the master enable/disable toggles for each notification channel",
        "operationId": "getMasterNotificationToggles",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Master toggles retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "email",
                    "push",
                    "inApp"
                  ],
                  "properties": {
                    "email": {
                      "type": "boolean",
                      "description": "Master toggle for email notifications",
                      "example": true
                    },
                    "push": {
                      "type": "boolean",
                      "description": "Master toggle for push notifications",
                      "example": true
                    },
                    "inApp": {
                      "type": "boolean",
                      "description": "Master toggle for in-app notifications",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update master notification toggles",
        "description": "Updates the master enable/disable toggles for notification channels. Only provided fields are updated.",
        "operationId": "updateMasterNotificationToggles",
        "tags": [
          "Notifications"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "boolean",
                    "description": "Enable/disable email notifications"
                  },
                  "push": {
                    "type": "boolean",
                    "description": "Enable/disable push notifications"
                  },
                  "inApp": {
                    "type": "boolean",
                    "description": "Enable/disable in-app notifications"
                  }
                },
                "example": {
                  "email": true,
                  "push": false
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Master toggles updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "email",
                    "push",
                    "inApp"
                  ],
                  "properties": {
                    "email": {
                      "type": "boolean",
                      "description": "Current email notifications state",
                      "example": true
                    },
                    "push": {
                      "type": "boolean",
                      "description": "Current push notifications state",
                      "example": false
                    },
                    "inApp": {
                      "type": "boolean",
                      "description": "Current in-app notifications state",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid toggle values",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/runs/prepare": {
      "post": {
        "operationId": "prepareRun",
        "summary": "Prepare a new terraform run",
        "description": "Initialize a run before streaming terraform apply events.\n\nThis endpoint creates a pending run that is ready to receive JSONL events from a terraform apply.\nOnce created, the CLI streams terraform output to `/api/v1/runs/{run_id}/events` and calls\n`/api/v1/runs/{run_id}/complete` when terraform finishes.\n\n**Required sequence:**\n1. Call `/runs/prepare` to create run\n2. Stream events via `/runs/{run_id}/events`\n3. Call `/runs/{run_id}/complete` with exit code\n\nSee [ADR-012](https://github.com/sageox/sageox/blob/main/docs/adr/012-run-event-processing.md) for architecture details.\n",
        "tags": [
          "runs"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "workspace_id",
                  "git_commit",
                  "terraform_version",
                  "plan_path"
                ],
                "properties": {
                  "workspace_id": {
                    "type": "string",
                    "description": "Workspace ID (ws_ prefix)",
                    "example": "ws_abc123def456"
                  },
                  "git_commit": {
                    "type": "string",
                    "description": "Git commit SHA for this run",
                    "example": "abc123deadbeef1234567890abcdef123456789"
                  },
                  "terraform_version": {
                    "type": "string",
                    "description": "Terraform version (e.g., \"1.9.5\")",
                    "example": "1.9.5"
                  },
                  "plan_path": {
                    "type": "string",
                    "description": "Path to plan.json in repository (relative to workspace)",
                    "example": "workspaces/acme-corp/prod/plan.json"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Run created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "run_id"
                  ],
                  "properties": {
                    "run_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "UUIDv7 identifier for the created run",
                      "example": "018c5e72-1b3a-7def-8abc-123456789012"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing required fields, invalid workspace_id format)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Missing required field: workspace_id"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized (invalid or missing authentication token)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Run already in progress for this workspace (conflict)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/runs/{run_id}/events": {
      "post": {
        "operationId": "streamRunEvents",
        "summary": "Stream terraform apply events",
        "description": "Stream terraform apply JSONL events. Connection stays open until terraform completes or disconnects.\n\n**Event Format:**\nSend terraform output as newline-delimited JSON (NDJSON). Each line is a single Terraform event.\n\nExample events:\n```\n{\"@level\":\"info\",\"type\":\"apply_start\",\"@timestamp\":\"2025-01-01T00:00:00Z\"}\n{\"@level\":\"info\",\"type\":\"apply_progress\",\"hook\":{\"resource\":{\"addr\":\"aws_s3_bucket.main\"},\"action\":\"create\"}}\n{\"@level\":\"info\",\"type\":\"apply_complete\",\"changes\":{\"add\":3,\"change\":0,\"remove\":0}}\n```\n\n**Connection Lifecycle:**\n- Backend validates run exists and is in `pending` or `running` status\n- First connection signals Temporal workflow `run_started`\n- Each event line updates `last_event_at` timestamp\n- Important events (progress, complete) update DB directly\n- Connection drop without calling `/complete` signals `connection_lost` to workflow\n- Reconnection within 2 minutes cancels the connection_lost timeout\n\n**Storage:**\n- Backend does NOT store raw events (would be high write volume)\n- CLI must locally write events to `apply.jsonl` file\n- CLI commits `apply.jsonl` to git after terraform exits\n- Backend queries important events from database, not stored JSONL\n\nSee [ADR-012](https://github.com/sageox/sageox/blob/main/docs/adr/012-run-event-processing.md) for full event specifications.\n",
        "tags": [
          "runs"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 run identifier from `/runs/prepare`",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "018c5e72-1b3a-7def-8abc-123456789012"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Newline-delimited JSON stream of terraform events",
          "content": {
            "application/x-ndjson": {
              "schema": {
                "type": "string",
                "description": "Terraform JSON output streamed as NDJSON (one JSON object per line).\nSee Terraform documentation for event schema.\n",
                "example": "{\"@level\":\"info\",\"type\":\"apply_start\",\"@timestamp\":\"2025-01-01T00:00:00Z\"}\n{\"@level\":\"info\",\"type\":\"apply_progress\",\"hook\":{\"resource\":{\"addr\":\"aws_s3_bucket.main\"},\"action\":\"create\"}}\n"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted - connection established and will remain open.\nBackend processes events as they arrive. Connection closes when:\n- Terraform process exits and CLI calls `/complete`\n- Network connection drops (triggers grace timer)\n- 30-minute inactivity timeout (no events received)\n- 4-hour absolute TTL exceeded\n"
          },
          "400": {
            "description": "Invalid JSONL format or malformed JSON in stream",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized (invalid or missing authentication token)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Run not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Run already completed or failed (cannot accept new events)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/runs/{run_id}/complete": {
      "post": {
        "operationId": "completeRun",
        "summary": "Complete a terraform run",
        "description": "Signal terraform apply has finished (success or failure).\n\n**CLI Sequence (before calling this endpoint):**\n1. Terraform apply exits (with exit code 0 or non-zero)\n2. CLI writes all events to local `apply.jsonl` file (via streaming from terraform)\n3. CLI commits `apply.jsonl` to git repository\n4. CLI pushes commit to remote\n5. CLI calls this endpoint with exit code and commit SHA\n\n**Important:** CLI MUST commit and push `apply.jsonl` even on failure.\nFailed runs need logs for debugging and analysis.\n\n**Backend Behavior:**\n- Stores `apply_commit` in run metadata for audit trail\n- Sets `apply_path` to `workspaces/{team}/{workspace}/apply.jsonl`\n- If exit_code=0: Sets status=`succeeded`, signals Temporal `run_completed`\n- If exit_code!=0: Sets status=`failed`, stores error message, signals Temporal `run_failed`\n\nSee [ADR-012](https://github.com/sageox/sageox/blob/main/docs/adr/012-run-event-processing.md) for workflow details.\n",
        "tags": [
          "runs"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 run identifier",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "018c5e72-1b3a-7def-8abc-123456789012"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "exit_code",
                  "apply_commit"
                ],
                "properties": {
                  "exit_code": {
                    "type": "integer",
                    "description": "Terraform exit code (0=success, non-zero=failure)",
                    "example": 0
                  },
                  "apply_commit": {
                    "type": "string",
                    "description": "Git commit SHA containing `apply.jsonl`",
                    "example": "abc123def456789abc123def456789abc123def4"
                  },
                  "error_message": {
                    "type": "string",
                    "description": "Error details if exit_code is non-zero (optional)",
                    "example": "Error: creating S3 bucket: AccessDenied"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Run completed successfully (no content in response)"
          },
          "400": {
            "description": "Invalid request (missing exit_code or apply_commit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Missing required field: exit_code"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized (invalid or missing authentication token)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Run not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Run already completed (conflict - cannot complete twice)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/runs/{run_id}": {
      "get": {
        "operationId": "getRun",
        "summary": "Get run status and resources",
        "description": "Retrieve run status and resource states. Frontend polls this endpoint to display progress.\n\n**Response includes:**\n- Run metadata (workspace, status, timestamps)\n- `metadata` object with resource counts, git commit, and timing info\n- `resources` array with per-resource status and duration\n\n**Frontend polling (from ADR-012):**\n```typescript\n// Poll every 2 seconds while running\nconst { data: run } = useQuery({\n  queryKey: ['run', runId],\n  queryFn: () => fetchRun(runId),\n  refetchInterval: (query) => {\n    const status = query.state.data?.status;\n    return status === 'running' || status === 'pending' ? 2000 : false;\n  },\n});\n```\n\n**Supported status values:**\n- `pending` - Run created, waiting for first event\n- `running` - Receiving events from CLI\n- `succeeded` - Terraform apply exit code 0\n- `failed` - Terraform apply exit code != 0\n- `timeout` - No events within 30 min, or total TTL (4 hours) exceeded\n- `disconnected` - CLI connection lost, didn't reconnect within 2-min grace period\n\n**Resource status values:**\n- `pending` - Waiting to execute\n- `running` - Currently executing\n- `succeeded` - Completed successfully\n- `failed` - Execution failed\n\nSee [ADR-012](https://github.com/sageox/sageox/blob/main/docs/adr/012-run-event-processing.md) for full schema.\n",
        "tags": [
          "runs"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 run identifier",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "018c5e72-1b3a-7def-8abc-123456789012"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Run details retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "workspace_id",
                    "status",
                    "plan_path",
                    "created_at",
                    "metadata",
                    "resources"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Run identifier",
                      "example": "018c5e72-1b3a-7def-8abc-123456789012"
                    },
                    "workspace_id": {
                      "type": "string",
                      "description": "Workspace identifier",
                      "example": "ws_abc123def456"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "running",
                        "succeeded",
                        "failed",
                        "timeout",
                        "disconnected"
                      ],
                      "description": "Current run status",
                      "example": "running"
                    },
                    "plan_path": {
                      "type": "string",
                      "description": "Path to plan.json in repository",
                      "example": "workspaces/acme-corp/prod/plan.json"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "When the run was created",
                      "example": "2025-01-01T00:00:00Z"
                    },
                    "completed_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "When the run completed (null if still running)",
                      "example": "2025-01-01T00:05:32Z"
                    },
                    "metadata": {
                      "type": "object",
                      "required": [
                        "git_commit",
                        "resource_count",
                        "resources_completed"
                      ],
                      "description": "Run metadata stored in JSONB",
                      "properties": {
                        "git_commit": {
                          "type": "string",
                          "description": "Git commit SHA at run start",
                          "example": "abc123deadbeef1234567890abcdef123456789"
                        },
                        "terraform_version": {
                          "type": "string",
                          "description": "Terraform version used",
                          "example": "1.9.5"
                        },
                        "resource_count": {
                          "type": "integer",
                          "description": "Total resources in the plan",
                          "example": 12
                        },
                        "resources_completed": {
                          "type": "integer",
                          "description": "Number of resources that have completed",
                          "example": 5
                        },
                        "last_event_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Timestamp of last event received",
                          "example": "2025-01-01T00:04:50Z"
                        },
                        "error_message": {
                          "type": "string",
                          "nullable": true,
                          "description": "Error message if run failed",
                          "example": null
                        },
                        "apply_commit": {
                          "type": "string",
                          "nullable": true,
                          "description": "Git commit SHA containing apply.jsonl",
                          "example": "def456abc123def456abc123def456abc123def4"
                        }
                      }
                    },
                    "resources": {
                      "type": "array",
                      "description": "Per-resource status and timing information",
                      "items": {
                        "type": "object",
                        "required": [
                          "address",
                          "resource_type",
                          "status"
                        ],
                        "properties": {
                          "address": {
                            "type": "string",
                            "description": "Terraform resource address",
                            "example": "aws_s3_bucket.main"
                          },
                          "resource_type": {
                            "type": "string",
                            "description": "Resource type for timing aggregation",
                            "example": "aws_s3_bucket"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "running",
                              "succeeded",
                              "failed"
                            ],
                            "description": "Resource execution status",
                            "example": "succeeded"
                          },
                          "started_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "When resource execution started",
                            "example": "2025-01-01T00:00:05Z"
                          },
                          "completed_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "When resource execution completed",
                            "example": "2025-01-01T00:00:10Z"
                          },
                          "duration_ms": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Execution duration in milliseconds",
                            "example": 2340
                          },
                          "metadata": {
                            "type": "object",
                            "description": "Resource metadata",
                            "properties": {
                              "name": {
                                "type": "string",
                                "description": "Resource name",
                                "example": "main"
                              },
                              "provider": {
                                "type": "string",
                                "description": "Cloud provider",
                                "example": "aws"
                              },
                              "category": {
                                "type": "string",
                                "enum": [
                                  "network",
                                  "compute",
                                  "storage",
                                  "security",
                                  "iam",
                                  "gpu",
                                  "dns",
                                  "cdn",
                                  "monitoring"
                                ],
                                "description": "Resource category for UI grouping",
                                "example": "storage"
                              },
                              "lifecycle": {
                                "type": "string",
                                "enum": [
                                  "create",
                                  "update",
                                  "delete",
                                  "replace",
                                  "no-op"
                                ],
                                "description": "Terraform lifecycle action",
                                "example": "create"
                              },
                              "run_index": {
                                "type": "integer",
                                "description": "Execution order",
                                "example": 0
                              },
                              "dependencies": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Resource addresses this depends on",
                                "example": [
                                  "aws_vpc.main"
                                ]
                              },
                              "error_message": {
                                "type": "string",
                                "nullable": true,
                                "description": "Error details if resource failed",
                                "example": null
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "id": "018c5e72-1b3a-7def-8abc-123456789012",
                  "workspace_id": "ws_abc123def456",
                  "status": "running",
                  "plan_path": "workspaces/acme-corp/prod/plan.json",
                  "created_at": "2025-01-01T00:00:00Z",
                  "completed_at": null,
                  "metadata": {
                    "git_commit": "abc123deadbeef1234567890abcdef123456789",
                    "terraform_version": "1.9.5",
                    "resource_count": 12,
                    "resources_completed": 5,
                    "last_event_at": "2025-01-01T00:04:50Z",
                    "error_message": null,
                    "apply_commit": null
                  },
                  "resources": [
                    {
                      "address": "aws_s3_bucket.main",
                      "resource_type": "aws_s3_bucket",
                      "status": "succeeded",
                      "started_at": "2025-01-01T00:00:05Z",
                      "completed_at": "2025-01-01T00:00:10Z",
                      "duration_ms": 2340,
                      "metadata": {
                        "name": "main",
                        "provider": "aws",
                        "category": "storage",
                        "lifecycle": "create",
                        "run_index": 0,
                        "dependencies": [],
                        "error_message": null
                      }
                    },
                    {
                      "address": "aws_vpc.main",
                      "resource_type": "aws_vpc",
                      "status": "running",
                      "started_at": "2025-01-01T00:00:12Z",
                      "completed_at": null,
                      "duration_ms": null,
                      "metadata": {
                        "name": "main",
                        "provider": "aws",
                        "category": "network",
                        "lifecycle": "create",
                        "run_index": 1,
                        "dependencies": [],
                        "error_message": null
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized (invalid or missing authentication token)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Run not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/env/{env_id}/run/init": {
      "post": {
        "operationId": "initRun",
        "summary": "Initialize new run (deprecated)",
        "description": "DEPRECATED: Use `POST /api/v1/runs/prepare` instead.\n\nCreates a new run for the specified environment with infrastructure files.\nThis endpoint is maintained for backwards compatibility only.\n",
        "tags": [
          "runs"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "env_id",
            "in": "path",
            "required": true,
            "description": "Environment identifier",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "description",
                  "infrastructure_files"
                ],
                "properties": {
                  "description": {
                    "type": "string",
                    "description": "Description of the run"
                  },
                  "infrastructure_files": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Map of infrastructure file names to their contents"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Run initialized successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "UUIDv7 identifier for the newly created run"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Environment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/env/{env_id}/run/{run_id}": {
      "post": {
        "operationId": "updateRun",
        "summary": "Update run with step data (deprecated)",
        "description": "DEPRECATED: Use `POST /api/v1/runs/{run_id}/events` for streaming instead.\n\nUpdates an existing run with data from a specific step.\nThis endpoint is maintained for backwards compatibility only.\n",
        "tags": [
          "runs"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "env_id",
            "in": "path",
            "required": true,
            "description": "Environment identifier",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "description": "Run identifier",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "step",
                  "data"
                ],
                "properties": {
                  "step": {
                    "type": "string",
                    "description": "Name or identifier of the step"
                  },
                  "data": {
                    "type": "object",
                    "description": "Step-specific data"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Run updated successfully (no content)"
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Environment or run not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/env/{env_id}/run/{run_id}/status": {
      "post": {
        "operationId": "completeRunLegacy",
        "summary": "Complete or fail run (deprecated)",
        "description": "DEPRECATED: Use `POST /api/v1/runs/{run_id}/complete` instead.\n\nMarks a run as completed or failed with an optional message.\nThis endpoint is maintained for backwards compatibility only.\n",
        "tags": [
          "runs"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "env_id",
            "in": "path",
            "required": true,
            "description": "Environment identifier",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "description": "Run identifier",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "status"
                ],
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "completed",
                      "failed"
                    ],
                    "description": "Final status of the run"
                  },
                  "message": {
                    "type": "string",
                    "description": "Optional message providing additional context"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Run status updated successfully (no content)"
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Environment or run not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "operationId": "listModels",
        "summary": "List available models",
        "description": "List all available LLM models that can be used for chat completions",
        "tags": [
          "LLM"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of available models",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data"
                  ],
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "list"
                      ],
                      "example": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "object",
                          "created",
                          "owned_by"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Model identifier",
                            "example": "gpt-4"
                          },
                          "object": {
                            "type": "string",
                            "enum": [
                              "model"
                            ],
                            "example": "model"
                          },
                          "created": {
                            "type": "integer",
                            "description": "Unix timestamp of when the model was created",
                            "example": 1677610602
                          },
                          "owned_by": {
                            "type": "string",
                            "description": "Organization that owns the model",
                            "example": "sageox"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIError"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/chat/completions": {
      "post": {
        "operationId": "createChatCompletion",
        "summary": "Create chat completion",
        "description": "Create a chat completion using OpenAI-compatible API format.\nSupports both streaming and non-streaming responses.\n\nFor streaming responses, set `stream: true` in the request body.\nThe response will be a text/event-stream with Server-Sent Events (SSE).\n",
        "tags": [
          "LLM"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "model",
                  "messages"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "description": "ID of the model to use",
                    "example": "gpt-4"
                  },
                  "messages": {
                    "type": "array",
                    "description": "List of messages in the conversation",
                    "minItems": 1,
                    "items": {
                      "type": "object",
                      "required": [
                        "role",
                        "content"
                      ],
                      "properties": {
                        "role": {
                          "type": "string",
                          "enum": [
                            "system",
                            "user",
                            "assistant"
                          ],
                          "description": "Role of the message author",
                          "example": "user"
                        },
                        "content": {
                          "type": "string",
                          "description": "Content of the message",
                          "example": "Hello, how are you?"
                        }
                      }
                    }
                  },
                  "stream": {
                    "type": "boolean",
                    "description": "Whether to stream the response using SSE",
                    "default": false,
                    "example": false
                  },
                  "temperature": {
                    "type": "number",
                    "description": "Sampling temperature between 0 and 2",
                    "minimum": 0,
                    "maximum": 2,
                    "default": 1,
                    "example": 0.7
                  },
                  "max_tokens": {
                    "type": "integer",
                    "description": "Maximum number of tokens to generate",
                    "minimum": 1,
                    "example": 1000
                  },
                  "top_p": {
                    "type": "number",
                    "description": "Nucleus sampling parameter",
                    "minimum": 0,
                    "maximum": 1,
                    "example": 1
                  },
                  "frequency_penalty": {
                    "type": "number",
                    "description": "Frequency penalty between -2.0 and 2.0",
                    "minimum": -2,
                    "maximum": 2,
                    "default": 0,
                    "example": 0
                  },
                  "presence_penalty": {
                    "type": "number",
                    "description": "Presence penalty between -2.0 and 2.0",
                    "minimum": -2,
                    "maximum": 2,
                    "default": 0,
                    "example": 0
                  },
                  "stop": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ],
                    "description": "Up to 4 sequences where the API will stop generating",
                    "example": [
                      "\\n"
                    ]
                  },
                  "n": {
                    "type": "integer",
                    "description": "Number of completions to generate",
                    "minimum": 1,
                    "maximum": 10,
                    "default": 1,
                    "example": 1
                  },
                  "user": {
                    "type": "string",
                    "description": "Unique identifier for the end-user",
                    "example": "user-12345"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chat completion response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "object",
                    "created",
                    "model",
                    "choices",
                    "usage"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Unique identifier for the completion",
                      "example": "chatcmpl-abc123"
                    },
                    "object": {
                      "type": "string",
                      "enum": [
                        "chat.completion"
                      ],
                      "example": "chat.completion"
                    },
                    "created": {
                      "type": "integer",
                      "description": "Unix timestamp of when the completion was created",
                      "example": 1677858242
                    },
                    "model": {
                      "type": "string",
                      "description": "Model used for the completion",
                      "example": "gpt-4"
                    },
                    "choices": {
                      "type": "array",
                      "description": "List of completion choices",
                      "items": {
                        "type": "object",
                        "required": [
                          "index",
                          "message",
                          "finish_reason"
                        ],
                        "properties": {
                          "index": {
                            "type": "integer",
                            "description": "Index of the choice",
                            "example": 0
                          },
                          "message": {
                            "type": "object",
                            "required": [
                              "role",
                              "content"
                            ],
                            "properties": {
                              "role": {
                                "type": "string",
                                "enum": [
                                  "assistant"
                                ],
                                "example": "assistant"
                              },
                              "content": {
                                "type": "string",
                                "description": "Generated message content",
                                "example": "Hello! I'm doing well, thank you for asking."
                              }
                            }
                          },
                          "finish_reason": {
                            "type": "string",
                            "enum": [
                              "stop",
                              "length",
                              "content_filter",
                              null
                            ],
                            "description": "Reason why the completion finished",
                            "example": "stop"
                          }
                        }
                      }
                    },
                    "usage": {
                      "type": "object",
                      "required": [
                        "prompt_tokens",
                        "completion_tokens",
                        "total_tokens"
                      ],
                      "properties": {
                        "prompt_tokens": {
                          "type": "integer",
                          "description": "Number of tokens in the prompt",
                          "example": 10
                        },
                        "completion_tokens": {
                          "type": "integer",
                          "description": "Number of tokens in the completion",
                          "example": 12
                        },
                        "total_tokens": {
                          "type": "integer",
                          "description": "Total number of tokens used",
                          "example": 22
                        }
                      }
                    }
                  }
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Server-Sent Events stream (when stream=true).\nEach event is a JSON object representing a chunk of the completion.\n\nFormat:\ndata: {\"id\":\"chatcmpl-abc123\",\"object\":\"chat.completion.chunk\",\"created\":1677858242,\"model\":\"gpt-4\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"Hello\"},\"finish_reason\":null}]}\n\nThe stream ends with:\ndata: [DONE]\n"
                },
                "example": "data: {\"id\":\"chatcmpl-abc123\",\"object\":\"chat.completion.chunk\",\"created\":1677858242,\"model\":\"gpt-4\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"chatcmpl-abc123\",\"object\":\"chat.completion.chunk\",\"created\":1677858242,\"model\":\"gpt-4\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Hello\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"chatcmpl-abc123\",\"object\":\"chat.completion.chunk\",\"created\":1677858242,\"model\":\"gpt-4\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"!\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"chatcmpl-abc123\",\"object\":\"chat.completion.chunk\",\"created\":1677858242,\"model\":\"gpt-4\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}]}\n\ndata: [DONE]\n"
              }
            }
          },
          "400": {
            "description": "Bad request - Invalid parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIError"
                },
                "example": {
                  "error": {
                    "message": "Invalid request body",
                    "type": "invalid_request_error",
                    "code": "invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIError"
                },
                "example": {
                  "error": {
                    "message": "Invalid authentication",
                    "type": "invalid_request_error",
                    "code": "invalid_api_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIError"
                },
                "example": {
                  "error": {
                    "message": "Rate limit exceeded",
                    "type": "rate_limit_error",
                    "code": "rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIError"
                },
                "example": {
                  "error": {
                    "message": "Internal server error",
                    "type": "server_error",
                    "code": "server_error"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/me": {
      "get": {
        "operationId": "getCurrentUser",
        "summary": "Get current user profile",
        "description": "Retrieves the authenticated user's profile including name, email, avatar,\ntier, ownership counts, and subscription status.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "User profile retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "email",
                    "emailVerified",
                    "tier",
                    "createdAt",
                    "updatedAt",
                    "ownedOrgsCount",
                    "ownedTeamsCount",
                    "newsletter_subscribed"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Unique user identifier",
                      "example": "usr_2n3k4m5l6j7h8g9f"
                    },
                    "name": {
                      "type": "string",
                      "description": "User's display name",
                      "example": "Alex Engineer"
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "description": "User's email address",
                      "example": "alex@example.com"
                    },
                    "emailVerified": {
                      "type": "boolean",
                      "description": "Whether email has been verified",
                      "example": true
                    },
                    "avatar_url": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL to user's avatar image",
                      "example": "https://storage.example.com/avatars/usr_2n3k4m5l6j7h8g9f/abc123.jpg"
                    },
                    "tier": {
                      "type": "string",
                      "description": "User's subscription tier",
                      "enum": [
                        "free",
                        "pro",
                        "enterprise"
                      ],
                      "example": "pro"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Account creation timestamp",
                      "example": "2025-01-15T10:30:00Z"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Profile last update timestamp",
                      "example": "2025-01-20T14:22:00Z"
                    },
                    "deletedAt": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Account deletion timestamp (null if not deleted)",
                      "example": null
                    },
                    "ownedOrgsCount": {
                      "type": "integer",
                      "description": "Number of organizations solely owned by user",
                      "example": 1
                    },
                    "ownedTeamsCount": {
                      "type": "integer",
                      "description": "Number of teams solely owned by user",
                      "example": 3
                    },
                    "newsletter_subscribed": {
                      "type": "boolean",
                      "description": "Whether user is subscribed to newsletter",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateCurrentUser",
        "summary": "Update user profile",
        "description": "Updates the authenticated user's profile. Only name and avatar_url can be\nmodified. Email changes require verification flow and are rejected here.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "User's new display name (1-255 characters)",
                    "example": "Alex Senior Engineer"
                  },
                  "avatar_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL to new avatar image",
                    "example": "https://storage.example.com/avatars/new-avatar.jpg"
                  }
                }
              },
              "examples": {
                "update_name": {
                  "summary": "Update name only",
                  "value": {
                    "name": "Alex Senior Engineer"
                  }
                },
                "update_avatar": {
                  "summary": "Update avatar only",
                  "value": {
                    "avatar_url": "https://storage.example.com/avatars/new-avatar.jpg"
                  }
                },
                "update_both": {
                  "summary": "Update name and avatar",
                  "value": {
                    "name": "Alex Senior Engineer",
                    "avatar_url": "https://storage.example.com/avatars/new-avatar.jpg"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Profile updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "email",
                    "emailVerified",
                    "tier",
                    "createdAt",
                    "updatedAt"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "usr_2n3k4m5l6j7h8g9f"
                    },
                    "name": {
                      "type": "string",
                      "example": "Alex Senior Engineer"
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "example": "alex@example.com"
                    },
                    "emailVerified": {
                      "type": "boolean",
                      "example": true
                    },
                    "avatar_url": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "example": "https://storage.example.com/avatars/new-avatar.jpg"
                    },
                    "tier": {
                      "type": "string",
                      "enum": [
                        "free",
                        "pro",
                        "enterprise"
                      ],
                      "example": "pro"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-01-15T10:30:00Z"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-01-20T15:45:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body or validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "empty_name": {
                    "value": {
                      "success": false,
                      "error": "name cannot be empty"
                    }
                  },
                  "email_rejected": {
                    "value": {
                      "success": false,
                      "error": "email cannot be changed directly, please use email verification flow"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteCurrentUser",
        "summary": "Initiate account deletion",
        "description": "Soft-deletes the user account with a 30-day grace period. User must not be\nthe sole owner of any teams or organizations. After deletion, the account can\nbe recovered by calling POST /api/v1/users/me/cancel-deletion within 30 days.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Account deletion initiated successfully (grace period started)"
          },
          "400": {
            "description": "Cannot delete account due to ownership constraints",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "has_teams": {
                    "value": {
                      "success": false,
                      "error": "cannot delete account while you are the sole owner of one or more teams"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/me/cancel-deletion": {
      "post": {
        "operationId": "cancelUserDeletion",
        "summary": "Cancel account deletion",
        "description": "Cancels a pending account deletion during the 30-day grace period.\nIf no deletion is pending, returns 400 Bad Request.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Deletion cancellation successful"
          },
          "400": {
            "description": "No pending deletion found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "no_pending_deletion": {
                    "value": {
                      "success": false,
                      "error": "no pending deletion found"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/me/export": {
      "get": {
        "operationId": "exportUserData",
        "summary": "Export user data (GDPR)",
        "description": "Exports all user data in JSON format for GDPR compliance. Returns a\ncomprehensive archive of the user's profile, preferences, and associated data.\nThe response includes a Content-Disposition header for download.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "User data export successful",
            "headers": {
              "Content-Disposition": {
                "description": "Download filename",
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=\"user-data-export-2025-01-20.json\""
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "profile"
                  ],
                  "properties": {
                    "profile": {
                      "type": "object",
                      "required": [
                        "id",
                        "email"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "example": "usr_2n3k4m5l6j7h8g9f"
                        },
                        "name": {
                          "type": "string",
                          "example": "Alex Engineer"
                        },
                        "email": {
                          "type": "string",
                          "format": "email",
                          "example": "alex@example.com"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "example": "2025-01-15T10:30:00Z"
                        }
                      }
                    },
                    "preferences": {
                      "type": "object",
                      "nullable": true,
                      "description": "User preferences and settings",
                      "additionalProperties": true
                    },
                    "teams": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "team_abc123xyz"
                          },
                          "name": {
                            "type": "string",
                            "example": "Engineering Team"
                          }
                        }
                      },
                      "description": "Teams the user belongs to"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/me/avatar": {
      "post": {
        "operationId": "uploadUserAvatar",
        "summary": "Upload user avatar",
        "description": "Uploads a user avatar image. Accepts JPEG, PNG, or WebP files up to 5MB.\nImage is automatically resized to 256x256 and stored. Returns the URL of\nthe stored avatar.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "avatar"
                ],
                "properties": {
                  "avatar": {
                    "type": "string",
                    "format": "binary",
                    "description": "Avatar image file (JPEG, PNG, or WebP, max 5MB)"
                  }
                }
              },
              "examples": {
                "avatar_upload": {
                  "value": {
                    "avatar": "(binary image data)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Avatar uploaded successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "avatar_url"
                  ],
                  "properties": {
                    "avatar_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "URL to the uploaded avatar",
                      "example": "https://storage.example.com/avatars/usr_2n3k4m5l6j7h8g9f/abc123def456.jpg"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid file or request error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_file": {
                    "value": {
                      "success": false,
                      "error": "avatar file is required"
                    }
                  },
                  "invalid_type": {
                    "value": {
                      "success": false,
                      "error": "invalid file type, only jpeg, png, and webp are allowed"
                    }
                  },
                  "too_large": {
                    "value": {
                      "success": false,
                      "error": "request body too large or invalid multipart form"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/me/adoptable-repos": {
      "get": {
        "operationId": "getAdoptableRepos",
        "summary": "List adoptable repositories",
        "description": "Returns repositories that were created with the user's email address but\nare not yet linked to their account. These are repositories potentially\ncreated before the user had a SageOx account. Note: Git email can be forged,\nso these are \"potential\" matches only - verify before claiming.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of adoptable repositories",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repos",
                    "warning"
                  ],
                  "properties": {
                    "repos": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "type",
                          "created_at"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Repository identifier",
                            "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                          },
                          "type": {
                            "type": "string",
                            "description": "VCS type",
                            "enum": [
                              "git"
                            ],
                            "example": "git"
                          },
                          "created_by_email": {
                            "type": "string",
                            "format": "email",
                            "nullable": true,
                            "description": "Email from git config when repo was initialized",
                            "example": "alex@example.com"
                          },
                          "created_by_name": {
                            "type": "string",
                            "nullable": true,
                            "description": "Name from git config when repo was initialized",
                            "example": "Alex Engineer"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Repository creation timestamp",
                            "example": "2025-01-10T09:15:00Z"
                          },
                          "team_ids": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Team IDs currently associated with this repo",
                            "example": [
                              "team_abc123xyz",
                              "team_def456uvw"
                            ]
                          }
                        }
                      }
                    },
                    "warning": {
                      "type": "string",
                      "description": "Warning about verifying claimed repositories",
                      "example": "These repos were created with your email address but are not yet linked to your account. Git email can be configured by anyone, so verify these are actually yours before claiming."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/me/newsletter/subscribe": {
      "post": {
        "operationId": "subscribeNewsletter",
        "summary": "Subscribe to newsletter",
        "description": "Subscribes the authenticated user to the SageOx newsletter.\nUpdates the user's newsletter subscription preference.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Newsletter subscription successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "newsletter_subscribed"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "newsletter_subscribed": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/me/newsletter": {
      "get": {
        "operationId": "getNewsletterStatus",
        "summary": "Get newsletter subscription status",
        "description": "Returns the authenticated user's newsletter subscription status.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Newsletter status retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "newsletter_subscribed"
                  ],
                  "properties": {
                    "newsletter_subscribed": {
                      "type": "boolean",
                      "description": "Whether user is subscribed to newsletter",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/me/onboarding": {
      "get": {
        "operationId": "getOnboardingStatus",
        "summary": "Get onboarding progress",
        "description": "Returns the authenticated user's onboarding step completion status.\nIndicates which key steps (team creation, repo initialization, recording)\nhave been completed.\n",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Onboarding status retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "has_team",
                    "has_repo",
                    "has_recording"
                  ],
                  "properties": {
                    "has_team": {
                      "type": "boolean",
                      "description": "Whether user has created a team",
                      "example": true
                    },
                    "has_repo": {
                      "type": "boolean",
                      "description": "Whether user has initialized a repository",
                      "example": true
                    },
                    "has_recording": {
                      "type": "boolean",
                      "description": "Whether user has created a recording",
                      "example": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys": {
      "post": {
        "operationId": "createAPIKey",
        "summary": "Create API key",
        "description": "Creates a new API key for the authenticated user. The full key is returned\nonly once and must be stored securely. The key can be used for API\nauthentication via Bearer token. Optionally specify an expiration period.\n",
        "tags": [
          "API Keys"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Human-readable name for the API key (1-255 characters)",
                    "example": "Production API Key"
                  },
                  "expires_in_days": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Optional expiration period in days from now",
                    "minimum": 1,
                    "example": 365
                  }
                }
              },
              "examples": {
                "with_expiration": {
                  "summary": "Create key with 365-day expiration",
                  "value": {
                    "name": "Production API Key",
                    "expires_in_days": 365
                  }
                },
                "no_expiration": {
                  "summary": "Create key with no expiration",
                  "value": {
                    "name": "Permanent API Key"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "name",
                    "key_prefix",
                    "created_at",
                    "key"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Unique API key identifier",
                      "example": "550e8400-e29b-41d4-a716-446655440000"
                    },
                    "name": {
                      "type": "string",
                      "description": "Key name",
                      "example": "Production API Key"
                    },
                    "key_prefix": {
                      "type": "string",
                      "description": "First 8 characters of the key (safe to log)",
                      "example": "mk_aB1cD2e"
                    },
                    "key": {
                      "type": "string",
                      "description": "Full API key (only returned on creation)",
                      "example": "mk_aB1cD2eF3gH4iJ5kL6mN7oP8qR9sTu"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Key creation timestamp",
                      "example": "2025-01-20T15:30:00Z"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Key expiration timestamp (null if no expiration)",
                      "example": "2026-01-20T15:30:00Z"
                    },
                    "last_used_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Last usage timestamp (null if never used)",
                      "example": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_name": {
                    "value": {
                      "success": false,
                      "error": "name is required"
                    }
                  },
                  "invalid_expiration": {
                    "value": {
                      "success": false,
                      "error": "expires_in_days must be positive"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listAPIKeys",
        "summary": "List API keys",
        "description": "Returns all active (non-revoked) API keys for the authenticated user.\nFull key values are never returned - only the prefix (first 8 chars) for\nidentification, creation date, and usage information.\n",
        "tags": [
          "API Keys"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "API keys retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "keys"
                  ],
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "name",
                          "key_prefix",
                          "created_at"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Unique API key identifier",
                            "example": "550e8400-e29b-41d4-a716-446655440000"
                          },
                          "name": {
                            "type": "string",
                            "description": "Key name",
                            "example": "Production API Key"
                          },
                          "key_prefix": {
                            "type": "string",
                            "description": "First 8 characters of the key",
                            "example": "mk_aB1cD2e"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Key creation timestamp",
                            "example": "2025-01-20T15:30:00Z"
                          },
                          "expires_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "Key expiration timestamp (null if no expiration)",
                            "example": "2026-01-20T15:30:00Z"
                          },
                          "last_used_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "Last usage timestamp",
                            "example": "2025-01-20T16:45:00Z"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{id}": {
      "delete": {
        "operationId": "revokeAPIKey",
        "summary": "Revoke API key",
        "description": "Revokes (soft-deletes) an API key. The key cannot be used for authentication\nafter revocation. Revocation is permanent and cannot be undone.\n",
        "tags": [
          "API Keys"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "API key UUID to revoke",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "550e8400-e29b-41d4-a716-446655440000"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "API key revoked successfully"
          },
          "400": {
            "description": "Invalid key ID format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_id": {
                    "value": {
                      "success": false,
                      "error": "invalid key id format"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not the owner of this key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_owner": {
                    "value": {
                      "success": false,
                      "error": "not the owner of this key"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "API key not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repo/init": {
      "post": {
        "operationId": "initRepo",
        "summary": "Initialize repository tracking",
        "description": "Registers a git repository with SageOx and creates an associated team.\n\n**Authentication:** Optional\n- **Authenticated:** User becomes owner of newly created team\n- **Unauthenticated:** Creates orphan team (can be claimed later)\n\nIdempotent: if repo_id already exists, returns existing repo/team info.\nUsers can request to merge teams via /api/v1/repo/merge.\n",
        "tags": [
          "Repository"
        ],
        "security": [
          {
            "BearerAuth": []
          },
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "repo_id",
                  "type",
                  "init_at"
                ],
                "properties": {
                  "repo_id": {
                    "type": "string",
                    "description": "Client-generated repo identifier (repo_<uuidv7>)",
                    "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                    "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                  },
                  "type": {
                    "type": "string",
                    "description": "VCS type (git supported, svn planned)",
                    "enum": [
                      "git"
                    ],
                    "example": "git"
                  },
                  "init_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Timestamp from .repo_<id> marker file",
                    "example": "2025-12-18T16:30:00Z"
                  },
                  "repo_salt": {
                    "type": "string",
                    "description": "Initial commit hash for salted remote hashing (optional, omitted in --offline mode)",
                    "example": "abc123def456789..."
                  },
                  "repo_remote_hashes": {
                    "type": "array",
                    "description": "SHA256(repo_salt + remote_url) for each git remote (optional, omitted in --offline mode)",
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "sha256:a1b2c3d4...",
                      "sha256:e5f6g7h8..."
                    ]
                  },
                  "is_public": {
                    "type": "boolean",
                    "description": "When true, prevents automatic merging with repos that have matching hashes (fork protection)",
                    "example": false
                  },
                  "created_by_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Git user.email from local config (optional, omitted in --offline mode)",
                    "example": "jane@example.com"
                  },
                  "created_by_name": {
                    "type": "string",
                    "description": "Git user.name from local config (optional, omitted in --offline mode)",
                    "example": "Jane Dev"
                  }
                }
              },
              "examples": {
                "full": {
                  "summary": "Full request with all optional fields",
                  "value": {
                    "repo_id": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                    "type": "git",
                    "init_at": "2025-12-18T16:30:00Z",
                    "repo_salt": "abc123def456789...",
                    "repo_remote_hashes": [
                      "sha256:a1b2c3d4..."
                    ],
                    "is_public": false,
                    "created_by_email": "jane@example.com",
                    "created_by_name": "Jane Dev"
                  }
                },
                "offline": {
                  "summary": "Minimal request (--offline mode)",
                  "value": {
                    "repo_id": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                    "type": "git",
                    "init_at": "2025-12-18T16:30:00Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Repository already exists (idempotent response)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "description": "The existing repo_id",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "description": "ID of the existing team",
                      "example": "team_abc123xyz"
                    },
                    "web_base_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Base URL for web UI (enterprise deployments)",
                      "example": "https://sageox.ai"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Repository registered successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "description": "The registered repo_id",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "description": "ID of the newly created team",
                      "example": "team_abc123xyz"
                    },
                    "web_base_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Base URL for web UI (enterprise deployments)",
                      "example": "https://sageox.ai"
                    },
                    "claim_code": {
                      "type": "string",
                      "description": "Code for claiming team ownership (unauthenticated requests only)",
                      "example": "abc123xyz"
                    },
                    "claim_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Full URL for browser-based team claiming (unauthenticated requests only)",
                      "example": "https://sageox.ai/team/claim?code=abc123xyz&team=team_abc123xyz"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_repo_id": {
                    "value": {
                      "error": "repo_id is required"
                    }
                  },
                  "invalid_repo_id": {
                    "value": {
                      "error": "repo_id must be in format repo_<uuidv7>"
                    }
                  },
                  "invalid_type": {
                    "value": {
                      "error": "type must be 'git'"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repo/merge": {
      "post": {
        "operationId": "mergeRepos",
        "summary": "Merge concurrent repository registrations",
        "description": "Called by ox-cli when it detects multiple .repo_* files (concurrent inits).\nDetermines the canonical repo_id based on UUIDv7 timestamps (time-sortable).\n\n**Current implementation:** Logs the merge request and returns the canonical repo_id.\nFull merge logic is planned for a future release.\n",
        "tags": [
          "Repository"
        ],
        "security": [
          {
            "BearerAuth": []
          },
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "repo_ids"
                ],
                "properties": {
                  "repo_ids": {
                    "type": "array",
                    "description": "Array of repo_<uuidv7> identifiers to merge",
                    "minItems": 2,
                    "items": {
                      "type": "string",
                      "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
                    },
                    "example": [
                      "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                      "repo_01934f5b-1234-7abc-9012-def456789012"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Merge processed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "canonical_repo_id",
                    "merged"
                  ],
                  "properties": {
                    "canonical_repo_id": {
                      "type": "string",
                      "description": "The earliest repo_id by UUIDv7 timestamp (becomes canonical)",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "merged": {
                      "type": "boolean",
                      "description": "Whether merge was processed (always true for now)",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "insufficient_ids": {
                    "value": {
                      "error": "at least 2 repo_ids required for merge"
                    }
                  },
                  "invalid_format": {
                    "value": {
                      "error": "all repo_ids must be in format repo_<uuidv7>"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cli/auth/token": {
      "get": {
        "operationId": "cliTokenExchange",
        "summary": "Exchange session token for JWT",
        "description": "Exchanges an opaque session token for a JWT access token.\nUsed by ox-cli after device flow authentication to obtain a short-lived JWT.\n\n**Authentication:** Public (no auth required)\n- Request can include Bearer token (opaque session token from device flow)\n- Returns JWT valid for 15 minutes\n\n**Rate limit:** 30 requests/minute per IP address\n",
        "tags": [
          "CLI"
        ],
        "security": [],
        "parameters": [
          {
            "in": "header",
            "name": "Authorization",
            "schema": {
              "type": "string",
              "example": "Bearer opaque-session-token-from-device-flow"
            },
            "description": "Optional session token to exchange. If not provided or already a JWT, validates and returns as-is."
          }
        ],
        "responses": {
          "200": {
            "description": "Token exchange successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "access_token",
                    "token_type",
                    "expires_in"
                  ],
                  "properties": {
                    "access_token": {
                      "type": "string",
                      "description": "JWT access token for subsequent API calls",
                      "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfMTIzNDU2IiwiZXhwIjoxNzI5NjU5MTAwfQ.sign"
                    },
                    "token_type": {
                      "type": "string",
                      "description": "Always \"Bearer\"",
                      "enum": [
                        "Bearer"
                      ],
                      "example": "Bearer"
                    },
                    "expires_in": {
                      "type": "integer",
                      "description": "Token expiration time in seconds (typically 900 = 15 minutes)",
                      "example": 900
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or expired token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_token": {
                    "value": {
                      "success": false,
                      "error": "missing bearer token"
                    }
                  },
                  "invalid_token": {
                    "value": {
                      "success": false,
                      "error": "invalid token"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Server error during token exchange",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cli/doctor/context": {
      "get": {
        "operationId": "getCliDoctorContext",
        "summary": "Get server-side diagnostic context for CLI",
        "description": "Returns comprehensive server-side context for client troubleshooting.\nUsed by `ox doctor` command to verify connectivity, configuration, and feature availability.\n\nIncludes user info, repositories, teams with git configurations, integration endpoints,\nfeature flags, expected environment variables, and server metadata.\n\n**Authentication:** Bearer token required\n",
        "tags": [
          "CLI"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Diagnostic context retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repositories",
                    "teams",
                    "endpoints",
                    "features",
                    "server"
                  ],
                  "properties": {
                    "user": {
                      "type": "object",
                      "description": "Authenticated user information",
                      "properties": {
                        "id": {
                          "type": "string",
                          "example": "usr_01aq5p00aq5p00aq5p"
                        },
                        "email": {
                          "type": "string",
                          "format": "email",
                          "example": "user@example.com"
                        },
                        "name": {
                          "type": "string",
                          "example": "Jane Developer"
                        },
                        "tier": {
                          "type": "string",
                          "description": "User subscription tier",
                          "enum": [
                            "free",
                            "pro",
                            "enterprise"
                          ],
                          "example": "pro"
                        }
                      }
                    },
                    "repositories": {
                      "type": "array",
                      "description": "Repositories registered for this user",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Repository ID (repo_<uuidv7>)",
                            "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "git"
                            ],
                            "example": "git"
                          },
                          "status": {
                            "type": "string",
                            "description": "Repository status in SageOx",
                            "enum": [
                              "active",
                              "archived",
                              "error"
                            ],
                            "example": "active"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-18T10:30:00Z"
                          },
                          "teams": {
                            "type": "array",
                            "description": "Team IDs this repo belongs to",
                            "items": {
                              "type": "string"
                            },
                            "example": [
                              "team_abc123xyz",
                              "team_def456uvw"
                            ]
                          },
                          "git": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string",
                                "enum": [
                                  "gitlab",
                                  "github",
                                  "gitea"
                                ],
                                "example": "gitlab"
                              },
                              "default_branch": {
                                "type": "string",
                                "example": "main"
                              },
                              "remote_url": {
                                "type": "string",
                                "format": "uri",
                                "example": "http://localhost:8929/group/project.git"
                              }
                            }
                          }
                        }
                      }
                    },
                    "teams": {
                      "type": "array",
                      "description": "Teams the user belongs to with git configurations",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "team_abc123xyz"
                          },
                          "slug": {
                            "type": "string",
                            "description": "URL-safe team identifier",
                            "example": "my-team"
                          },
                          "name": {
                            "type": "string",
                            "example": "My Team"
                          },
                          "role": {
                            "type": "string",
                            "description": "User's role in this team",
                            "enum": [
                              "owner",
                              "admin",
                              "editor",
                              "viewer"
                            ],
                            "example": "owner"
                          },
                          "git": {
                            "type": "object",
                            "description": "Git configuration for this team",
                            "properties": {
                              "remote_url": {
                                "type": "string",
                                "format": "uri",
                                "example": "http://localhost:8929/group/norms.git"
                              },
                              "default_branch": {
                                "type": "string",
                                "example": "main"
                              },
                              "provider": {
                                "type": "string",
                                "example": "gitlab"
                              }
                            }
                          },
                          "norms_url": {
                            "type": "string",
                            "format": "uri",
                            "description": "Git URL for team conventions repository",
                            "example": "http://localhost:8929/group/norms.git"
                          }
                        }
                      }
                    },
                    "endpoints": {
                      "type": "object",
                      "description": "Integration endpoints client should verify",
                      "required": [
                        "api",
                        "auth"
                      ],
                      "properties": {
                        "api": {
                          "type": "string",
                          "format": "uri",
                          "description": "SageOx API base URL",
                          "example": "http://localhost:3000"
                        },
                        "auth": {
                          "type": "string",
                          "format": "uri",
                          "description": "Authentication service URL",
                          "example": "http://localhost:3000"
                        },
                        "gitlab": {
                          "type": "string",
                          "format": "uri",
                          "description": "GitLab instance URL (if configured)",
                          "example": "http://localhost:8929"
                        },
                        "websocket": {
                          "type": "string",
                          "format": "uri",
                          "description": "WebSocket endpoint for real-time updates",
                          "example": "ws://localhost:3000"
                        }
                      }
                    },
                    "features": {
                      "type": "object",
                      "description": "Feature flags that affect client behavior",
                      "properties": {
                        "temporal": {
                          "type": "boolean",
                          "description": "Temporal workflow engine availability",
                          "example": true
                        },
                        "ocr": {
                          "type": "boolean",
                          "description": "Optical character recognition feature",
                          "example": false
                        },
                        "notifications": {
                          "type": "object",
                          "description": "Notification channel configuration"
                        }
                      }
                    },
                    "expected_env_vars": {
                      "type": "array",
                      "description": "Environment variables client should check",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "example": "SAGEOX_API_URL"
                          },
                          "description": {
                            "type": "string",
                            "example": "Base URL for SageOx API"
                          },
                          "required": {
                            "type": "boolean",
                            "example": false
                          },
                          "example": {
                            "type": "string",
                            "example": "http://localhost:3000"
                          }
                        }
                      }
                    },
                    "server": {
                      "type": "object",
                      "description": "Server metadata and version info",
                      "required": [
                        "version",
                        "environment",
                        "timestamp"
                      ],
                      "properties": {
                        "version": {
                          "type": "string",
                          "description": "API server version",
                          "example": "0.15.0"
                        },
                        "environment": {
                          "type": "string",
                          "enum": [
                            "development",
                            "staging",
                            "production"
                          ],
                          "example": "development"
                        },
                        "timestamp": {
                          "type": "string",
                          "format": "date-time",
                          "description": "Server time when context was generated",
                          "example": "2025-12-18T10:30:00Z"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cli/friction": {
      "post": {
        "operationId": "submitCliEvents",
        "summary": "Submit CLI friction events",
        "description": "Accepts batched CLI friction events for UX improvement and friction analysis.\nUsed by ox-cli to report issues such as unknown commands, invalid flags, parsing errors, etc.\n\n**Authentication:** Optional (can be authenticated or public)\n- If authenticated, associates events with user account\n- If not authenticated, events are recorded anonymously\n\n**Events validation:**\n- Timestamp: RFC3339 format required\n- Kind: must be one of unknown-command, unknown-flag, missing-required, invalid-arg, parse-error\n- Actor: must be human, agent, or unknown\n- PathBucket: must be home, repo, or other\n- Input: max 500 characters\n- ErrorMsg: max 200 characters\n- MaxEventsPerRequest: 100 events per batch\n\n**Server feedback:**\n- X-SageOx-Friction-Status header indicates collection status (active, paused, sampling)\n- X-SageOx-Sample-Rate header (if sampling) indicates sample rate\n- X-SageOx-Pause-Until header (if paused) indicates when collection resumes\n",
        "tags": [
          "CLI"
        ],
        "security": [
          {
            "BearerAuth": []
          },
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "events"
                ],
                "properties": {
                  "events": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 100,
                    "description": "Array of friction events (max 100 per request)",
                    "items": {
                      "type": "object",
                      "required": [
                        "ts",
                        "kind",
                        "command",
                        "actor",
                        "path_bucket",
                        "input",
                        "error_msg"
                      ],
                      "properties": {
                        "ts": {
                          "type": "string",
                          "format": "date-time",
                          "description": "Event timestamp in RFC3339 format",
                          "example": "2025-12-18T10:30:45Z"
                        },
                        "kind": {
                          "type": "string",
                          "description": "Type of friction event",
                          "enum": [
                            "unknown-command",
                            "unknown-flag",
                            "missing-required",
                            "invalid-arg",
                            "parse-error"
                          ],
                          "example": "unknown-command"
                        },
                        "command": {
                          "type": "string",
                          "description": "Command that triggered the event",
                          "example": "ox"
                        },
                        "subcommand": {
                          "type": "string",
                          "description": "Subcommand (optional)",
                          "example": "init"
                        },
                        "actor": {
                          "type": "string",
                          "description": "Who triggered the event",
                          "enum": [
                            "human",
                            "agent",
                            "unknown"
                          ],
                          "example": "human"
                        },
                        "agent_type": {
                          "type": "string",
                          "description": "Type of agent if actor=agent",
                          "example": "claude-3-sonnet"
                        },
                        "path_bucket": {
                          "type": "string",
                          "description": "Working directory category",
                          "enum": [
                            "home",
                            "repo",
                            "other"
                          ],
                          "example": "repo"
                        },
                        "input": {
                          "type": "string",
                          "description": "Command input (redacted if sensitive, max 500 chars)",
                          "example": "ox init --invalid-flag",
                          "maxLength": 500
                        },
                        "error_msg": {
                          "type": "string",
                          "description": "Error message (max 200 chars)",
                          "example": "unknown flag: --invalid-flag",
                          "maxLength": 200
                        },
                        "suggestion": {
                          "type": "string",
                          "description": "Suggested correction (optional)",
                          "example": "Did you mean: --no-install?"
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "single_event": {
                    "summary": "Single friction event",
                    "value": {
                      "events": [
                        {
                          "ts": "2025-12-18T10:30:45Z",
                          "kind": "unknown-flag",
                          "command": "ox",
                          "subcommand": "init",
                          "actor": "human",
                          "path_bucket": "repo",
                          "input": "ox init --invalid-flag",
                          "error_msg": "unknown flag: --invalid-flag",
                          "suggestion": "Did you mean: --no-install?"
                        }
                      ]
                    }
                  },
                  "batch": {
                    "summary": "Batch of multiple events",
                    "value": {
                      "events": [
                        {
                          "ts": "2025-12-18T10:30:45Z",
                          "kind": "unknown-flag",
                          "command": "ox",
                          "actor": "human",
                          "path_bucket": "repo",
                          "input": "ox init --verbose",
                          "error_msg": "unknown flag: --verbose"
                        },
                        {
                          "ts": "2025-12-18T10:31:12Z",
                          "kind": "invalid-arg",
                          "command": "ox",
                          "subcommand": "config",
                          "actor": "human",
                          "path_bucket": "home",
                          "input": "ox config set invalid_key value",
                          "error_msg": "invalid configuration key"
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Events accepted and processed",
            "headers": {
              "X-SageOx-Friction-Status": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "active",
                    "paused",
                    "sampling"
                  ]
                },
                "description": "Current friction collection status",
                "example": "active"
              },
              "X-SageOx-Sample-Rate": {
                "schema": {
                  "type": "string"
                },
                "description": "Sample rate if status is sampling (e.g., \"0.5\")",
                "example": "0.5"
              },
              "X-SageOx-Pause-Until": {
                "schema": {
                  "type": "string",
                  "format": "date-time"
                },
                "description": "Resume time if status is paused",
                "example": "2025-12-18T11:30:45Z"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "accepted"
                  ],
                  "properties": {
                    "accepted": {
                      "type": "integer",
                      "description": "Number of events accepted and processed",
                      "example": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "no_events": {
                    "value": {
                      "success": false,
                      "error": "No events provided"
                    }
                  },
                  "too_many_events": {
                    "value": {
                      "success": false,
                      "error": "Too many events: 150 (max 100)"
                    }
                  },
                  "invalid_json": {
                    "value": {
                      "success": false,
                      "error": "Invalid JSON body"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Payload too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Friction tracking not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_configured": {
                    "value": {
                      "success": false,
                      "error": "Friction tracking not configured"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cli/repos": {
      "get": {
        "operationId": "listCliRepos",
        "summary": "List user's registered repositories",
        "description": "Lists all repositories registered with SageOx for the authenticated user.\nReturns minimal repository information including ID, team associations, and registration time.\n\n**Authentication:** Bearer token required\n\n**Pagination:** Not implemented (returns all repos)\n",
        "tags": [
          "CLI"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of user's repositories",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "repo_id",
                      "created_at"
                    ],
                    "properties": {
                      "repo_id": {
                        "type": "string",
                        "description": "Repository ID (repo_<uuidv7>)",
                        "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                      },
                      "team_id": {
                        "type": "string",
                        "description": "Primary team ID (if repository is associated with a single team)",
                        "example": "team_abc123xyz"
                      },
                      "name": {
                        "type": "string",
                        "description": "Human-readable repository name (optional)",
                        "example": "my-project"
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the repository was registered",
                        "example": "2025-12-18T10:30:00Z"
                      }
                    }
                  }
                },
                "examples": {
                  "multiple_repos": {
                    "value": [
                      {
                        "repo_id": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                        "team_id": "team_abc123xyz",
                        "name": "my-project",
                        "created_at": "2025-12-18T10:30:00Z"
                      },
                      {
                        "repo_id": "repo_01934f5b-1234-7abc-9012-def456789012",
                        "team_id": "team_def456uvw",
                        "name": "another-project",
                        "created_at": "2025-12-10T08:15:00Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/cli/repo/init": {
      "post": {
        "operationId": "initCliRepo",
        "summary": "Initialize repository with CLI support",
        "description": "Registers a git repository with SageOx and creates an associated team.\n**Preferred route for ox-cli** (use instead of /api/v1/repo/init).\n\nSupports additional `teams` array parameter for multi-team repositories.\n\n**Authentication:** Optional\n- **Authenticated:** User becomes owner of newly created team\n- **Unauthenticated:** Creates orphan team (can be claimed later with claim code)\n\n**Idempotency:** If repo_id already exists, returns existing repo/team info with 200 status.\n\nTeams can be merged later via /api/v1/repo/merge endpoint.\n",
        "tags": [
          "CLI"
        ],
        "security": [
          {
            "BearerAuth": []
          },
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "repo_id",
                  "type",
                  "init_at"
                ],
                "properties": {
                  "repo_id": {
                    "type": "string",
                    "description": "Client-generated repo identifier",
                    "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                    "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                  },
                  "type": {
                    "type": "string",
                    "description": "VCS type (git supported, svn planned)",
                    "enum": [
                      "git"
                    ],
                    "example": "git"
                  },
                  "init_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Timestamp from .repo_<id> marker file",
                    "example": "2025-12-18T16:30:00Z"
                  },
                  "repo_salt": {
                    "type": "string",
                    "description": "Initial commit hash for salted remote hashing (optional, omitted in --offline mode)",
                    "example": "abc123def456789abc123def456789abc123def456"
                  },
                  "repo_remote_hashes": {
                    "type": "array",
                    "description": "SHA256(repo_salt + remote_url) for each git remote (optional, omitted in --offline mode)",
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "sha256:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0",
                      "sha256:e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x"
                    ]
                  },
                  "is_public": {
                    "type": "boolean",
                    "description": "When true, prevents automatic merging with repos that have matching hashes (fork protection)",
                    "example": false
                  },
                  "created_by_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Git user.email from local config (optional, omitted in --offline mode)",
                    "example": "developer@example.com"
                  },
                  "created_by_name": {
                    "type": "string",
                    "description": "Git user.name from local config (optional, omitted in --offline mode)",
                    "example": "Developer Name"
                  },
                  "teams": {
                    "type": "array",
                    "description": "Additional team IDs to associate with this repository (optional, CLI extension)",
                    "items": {
                      "type": "string",
                      "pattern": "^team_"
                    },
                    "example": [
                      "team_abc123xyz",
                      "team_def456uvw"
                    ]
                  }
                }
              },
              "examples": {
                "full": {
                  "summary": "Full request with all optional fields",
                  "value": {
                    "repo_id": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                    "type": "git",
                    "init_at": "2025-12-18T16:30:00Z",
                    "repo_salt": "abc123def456789abc123def456789abc123def456",
                    "repo_remote_hashes": [
                      "sha256:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"
                    ],
                    "is_public": false,
                    "created_by_email": "developer@example.com",
                    "created_by_name": "Developer Name",
                    "teams": [
                      "team_abc123xyz"
                    ]
                  }
                },
                "offline": {
                  "summary": "Minimal request (--offline mode)",
                  "value": {
                    "repo_id": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                    "type": "git",
                    "init_at": "2025-12-18T16:30:00Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Repository already exists (idempotent response)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "description": "The existing repo_id",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "description": "ID of the existing team",
                      "example": "team_abc123xyz"
                    },
                    "web_base_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Base URL for web UI (enterprise deployments)",
                      "example": "https://sageox.ai"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Repository registered successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "description": "The registered repo_id",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "description": "ID of the newly created team",
                      "example": "team_abc123xyz"
                    },
                    "web_base_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Base URL for web UI (enterprise deployments)",
                      "example": "https://sageox.ai"
                    },
                    "claim_code": {
                      "type": "string",
                      "description": "Code for claiming team ownership (unauthenticated requests only)",
                      "example": "abc123xyz"
                    },
                    "claim_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Full URL for browser-based team claiming (unauthenticated requests only)",
                      "example": "https://sageox.ai/team/claim?code=abc123xyz&team=team_abc123xyz"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_repo_id": {
                    "value": {
                      "success": false,
                      "error": "repo_id is required"
                    }
                  },
                  "invalid_repo_id": {
                    "value": {
                      "success": false,
                      "error": "repo_id must be in format repo_<uuidv7>"
                    }
                  },
                  "invalid_type": {
                    "value": {
                      "success": false,
                      "error": "type must be 'git'"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/capture": {
      "post": {
        "operationId": "agentxCapture",
        "summary": "Ingest telemetry events",
        "description": "Accepts a batch of telemetry events from CLI tools and AI agents.\nEvents are validated, timestamped, and stored in the app's event stream.\n\n**Authentication:** API key (`axk_...`) in `Authorization: Bearer` header.\nNo JWT required — this endpoint is designed for embedding in open-source CLIs.\n\n**Collection controls:** If the app has `collection_enabled: false`, events are\naccepted but silently dropped (returns `{\"status\": 1, \"accepted\": 0}`).\nIf `sample_rate < 1.0`, events are randomly sampled before storage.\n\n**Validation rules:**\n- Event names must match `^[a-z][a-z0-9]*(\\.[a-z][a-z0-9-]*)*$` (dot-namespaced)\n- `distinct_id` is required per event (opaque device/machine identifier)\n- Timestamps older than 89 days or more than 1 day in the future are clamped (not rejected)\n- Properties: max 4KB total per event, max 500 characters per individual value\n- Max 500 events per batch\n\n**Deduplication:** Include `$insert_id` (client-generated UUID) in properties to\nprevent metric inflation from retries. Events with duplicate `$insert_id` values\nwithin a 24-hour window are silently skipped.\n\nSee [Capture endpoint](#tag/AgentX/operation/agentxCapture) for integration examples.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "events"
                ],
                "properties": {
                  "events": {
                    "type": "array",
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [
                        "event",
                        "distinct_id"
                      ],
                      "properties": {
                        "event": {
                          "type": "string",
                          "pattern": "^[a-z][a-z0-9]*(\\.[a-z][a-z0-9-]*)*$",
                          "description": "Dot-namespaced event name. Must start with a lowercase letter.\nExamples: `command.executed`, `friction.unknown-command`, `session.start`.\n",
                          "example": "command.executed"
                        },
                        "distinct_id": {
                          "type": "string",
                          "description": "Opaque device/machine identifier. SDK-generated UUID, persisted locally\non the client. Not PII — just a correlation key for counting unique devices.\n",
                          "example": "d8f2a1b3-4c5e-6f7a-8b9c-0d1e2f3a4b5c"
                        },
                        "timestamp": {
                          "type": "string",
                          "format": "date-time",
                          "description": "Event timestamp (RFC 3339). Defaults to server receive time if omitted.\nTimestamps older than 89 days or more than 1 day in the future are\nclamped to the boundary (not rejected), and `$adjusted_ts: true` is set\nin properties.\n",
                          "example": "2026-03-26T14:30:00Z"
                        },
                        "properties": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "Arbitrary key-value metadata. Max 4KB total, max 500 characters per\nindividual string value.\n\n**Reserved properties (set by SDK):**\n- `$insert_id` — Client UUID per event for deduplication\n- `$lib` — SDK name (e.g., `agentx-go`)\n- `$lib_version` — SDK version\n- `$user_id` — Optional opaque user identifier for user-level analytics\n\n**Friction properties (convention):**\n- `kind` — Friction type: `unknown-command`, `unknown-flag`, `missing-required`, `invalid-arg`, `parse-error`\n- `actor` — `human` or `agent`\n- `agent_type` — Agent identifier (e.g., `copilot`, `cursor`)\n- `command`, `subcommand` — CLI command context\n- `error_msg` — Error message shown to user\n- `suggestion` — Client-side auto-correction suggestion\n"
                        }
                      }
                    }
                  }
                }
              },
              "examples": {
                "single-event": {
                  "summary": "Single command execution event",
                  "value": {
                    "events": [
                      {
                        "event": "command.executed",
                        "distinct_id": "d8f2a1b3-4c5e-6f7a-8b9c-0d1e2f3a4b5c",
                        "properties": {
                          "command": "deploy",
                          "duration_ms": 1234,
                          "$lib": "my-cli",
                          "$lib_version": "1.2.0",
                          "$insert_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                        }
                      }
                    ]
                  }
                },
                "friction-batch": {
                  "summary": "Friction events batch",
                  "value": {
                    "events": [
                      {
                        "event": "friction.unknown-command",
                        "distinct_id": "d8f2a1b3-4c5e-6f7a-8b9c-0d1e2f3a4b5c",
                        "properties": {
                          "kind": "unknown-command",
                          "actor": "human",
                          "command": "delpoy",
                          "error_msg": "unknown command: delpoy",
                          "$insert_id": "b2c3d4e5-f6a7-8901-bcde-f23456789012"
                        }
                      },
                      {
                        "event": "friction.invalid-arg",
                        "distinct_id": "d8f2a1b3-4c5e-6f7a-8b9c-0d1e2f3a4b5c",
                        "properties": {
                          "kind": "invalid-arg",
                          "actor": "agent",
                          "agent_type": "copilot",
                          "command": "config",
                          "subcommand": "set",
                          "error_msg": "invalid value for --timeout: abc",
                          "$insert_id": "c3d4e5f6-a7b8-9012-cdef-345678901234"
                        }
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Batch accepted. `accepted` indicates how many events were stored (may be less than submitted due to validation or sampling).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "integer",
                      "description": "Always `1` on success",
                      "example": 1
                    },
                    "accepted": {
                      "type": "integer",
                      "description": "Number of events stored. May be 0 if collection is disabled or all events were sampled out.",
                      "example": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (empty batch, malformed JSON)"
          },
          "413": {
            "description": "Batch exceeds 500 events"
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying (includes jitter)"
              },
              "X-SageOx-Rate-Limit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Events remaining in current rate limit window"
              },
              "X-SageOx-Quota-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Events remaining in monthly quota"
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/apps": {
      "post": {
        "operationId": "agentxCreateApp",
        "summary": "Register a new app",
        "description": "Creates a new AgentX application and returns the API key.\n\n**The API key is shown only once in this response.** It is not retrievable\nlater via the GET endpoint. To obtain a new key, delete the app and recreate it.\n\nThe caller must be an active member of the specified team.\n\n**Default metadata:** `rate_limit: 1000/min`, `burst_limit: 5000/min`, `monthly_quota: 10M events`.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "team_id",
                  "title",
                  "slug"
                ],
                "properties": {
                  "team_id": {
                    "type": "string",
                    "description": "Team that owns this app. Must be a valid `team_` prefixed ID.",
                    "example": "team_abc123"
                  },
                  "title": {
                    "type": "string",
                    "description": "Human-readable app name",
                    "example": "My CLI Tool"
                  },
                  "slug": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9-]{0,49}$",
                    "description": "URL-safe identifier. Lowercase alphanumeric with hyphens, 1–50 characters. Must be unique per team.",
                    "example": "my-cli"
                  },
                  "description": {
                    "type": "string",
                    "description": "Optional description stored in app metadata"
                  }
                }
              },
              "example": {
                "team_id": "team_abc123",
                "title": "My CLI Tool",
                "slug": "my-cli",
                "description": "Telemetry for the my-cli command-line tool"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "App created. API key included in response (shown once).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "app": {
                      "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/responses/200/content/application~1json/schema"
                    },
                    "api_key": {
                      "type": "string",
                      "description": "API key for the capture endpoint. **Shown only once** — store it securely.\nFormat: `axk_` followed by 32 random base62 characters.\n",
                      "example": "axk_a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5P6"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing fields, bad slug format)"
          },
          "403": {
            "description": "Not a member of the specified team"
          },
          "409": {
            "description": "An app with this slug already exists for this team"
          }
        }
      },
      "get": {
        "operationId": "agentxListApps",
        "summary": "List apps for a team",
        "description": "Returns all AgentX applications registered to the specified team.\nAPI keys are never included in list responses.\n\nThe caller must be an active member of the specified team.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "team_id",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123"
            },
            "description": "Team ID to list apps for. Must be a valid `team_` prefixed ID."
          }
        ],
        "responses": {
          "200": {
            "description": "List of apps (may be empty)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/responses/200/content/application~1json/schema"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid team_id"
          },
          "403": {
            "description": "Not a member of the specified team"
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}": {
      "get": {
        "operationId": "agentxGetApp",
        "summary": "Get app details",
        "description": "Returns application details including metadata and settings.\nThe API key is **not** included — it is only shown once at creation time.\n\nRequires JWT authentication and team membership.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^app_[0-9a-f-]+$",
              "example": "app_01924a5b-6c7d-8e9f-0a1b-2c3d4e5f6a7b"
            },
            "description": "AgentX application ID"
          }
        ],
        "responses": {
          "200": {
            "description": "App details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Application ID (`app_` prefix + UUIDv7)",
                      "example": "app_01924a5b-6c7d-8e9f-0a1b-2c3d4e5f6a7b"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123"
                    },
                    "title": {
                      "type": "string",
                      "example": "My CLI Tool"
                    },
                    "slug": {
                      "type": "string",
                      "example": "my-cli"
                    },
                    "metadata": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "App configuration including rate limits, display settings, and collection controls"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "App not found"
          }
        }
      },
      "delete": {
        "operationId": "agentxDeleteApp",
        "summary": "Delete an app",
        "description": "Permanently deletes the application and invalidates its API key.\nAny subsequent capture requests using this key will fail with 401.\n\n**This action is irreversible.** All associated event data remains in storage\nbut is no longer queryable through the dashboard.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          }
        ],
        "responses": {
          "204": {
            "description": "App deleted"
          },
          "404": {
            "description": "App not found"
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/settings": {
      "patch": {
        "operationId": "agentxUpdateSettings",
        "summary": "Update collection settings",
        "description": "Updates collection control settings for the app.\n\n- **`collection_enabled`**: When `false`, the capture endpoint accepts events\n  but drops them immediately — zero server-side resources consumed.\n- **`sample_rate`**: Controls what fraction of events are stored (0.0 to 1.0).\n  Events are randomly sampled before database insertion. Set to `1.0` to keep\n  all events, or lower to reduce storage for high-volume apps.\n\nSettings take effect on the next capture request (cached for up to 5 minutes\nin the API key middleware).\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "collection_enabled": {
                    "type": "boolean",
                    "description": "When `false`, incoming telemetry is accepted but dropped immediately.\nNo events are stored or processed. Defaults to `true`.\n"
                  },
                  "sample_rate": {
                    "type": "number",
                    "format": "double",
                    "minimum": 0,
                    "maximum": 1,
                    "description": "Fraction of events to store (0.0 to 1.0). Events are randomly sampled\nbefore database insertion. `1.0` keeps all events; `0.5` drops ~50%.\n"
                  }
                }
              },
              "examples": {
                "disable-collection": {
                  "summary": "Disable collection entirely",
                  "value": {
                    "collection_enabled": false
                  }
                },
                "reduce-sampling": {
                  "summary": "Keep 50% of events",
                  "value": {
                    "sample_rate": 0.5
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated settings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "collection_enabled": {
                      "type": "boolean",
                      "example": true
                    },
                    "sample_rate": {
                      "type": "number",
                      "format": "double",
                      "example": 1
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid sample_rate (must be 0.0–1.0)"
          },
          "404": {
            "description": "App not found"
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/summary": {
      "get": {
        "operationId": "agentxSummary",
        "summary": "Get KPI summary",
        "description": "Returns fast KPI data from pre-aggregated counters. Designed for dashboard\nwidgets and overview cards. Responds in <100ms.\n\nReturns events in the last 24 hours. Does not accept date range parameters.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          }
        ],
        "responses": {
          "200": {
            "description": "KPI summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events_24h": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Total events in the last 24 hours"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/overview": {
      "get": {
        "operationId": "agentxOverview",
        "summary": "Get overview statistics",
        "description": "Returns aggregate statistics for the specified date range: total events,\nunique users, friction event count, friction rate, and latest client version.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/1"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/2"
          },
          {
            "in": "query",
            "name": "tz",
            "schema": {
              "type": "string",
              "example": "America/Los_Angeles"
            },
            "description": "IANA timezone for time series bucketing. Defaults to UTC."
          }
        ],
        "responses": {
          "200": {
            "description": "Overview statistics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total_events": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "total_users": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "friction_events": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "friction_rate": {
                      "type": "number",
                      "format": "double",
                      "description": "Percentage of events that are friction events (0–100)"
                    },
                    "latest_version": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/events": {
      "get": {
        "operationId": "agentxEvents",
        "summary": "Get event time series",
        "description": "Returns time-bucketed event counts grouped by event name.\nBuckets are hourly for ranges <= 7 days, daily for longer ranges.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/1"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/2"
          }
        ],
        "responses": {
          "200": {
            "description": "Time series data points",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/responses/200/content/application~1json/schema/items"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/friction": {
      "get": {
        "operationId": "agentxFriction",
        "summary": "Get friction forensics",
        "description": "Returns comprehensive friction analysis with selective metric loading.\nUse the `metrics` parameter to request only the sections you need — each\nmetric is fetched concurrently for optimal performance.\n\n**Available metrics:** `time_series`, `by_actor`, `by_tool`,\n`top_unknown_commands`, `agent_stats`, `client_versions`, `hotspots`,\n`recent_events`.\n\nWhen `compare=true`, includes a previous-period comparison for trend analysis.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/1"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/2"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1overview/get/parameters/3"
          },
          {
            "in": "query",
            "name": "kind",
            "schema": {
              "type": "string",
              "enum": [
                "unknown-command",
                "unknown-flag",
                "missing-required",
                "invalid-arg",
                "parse-error"
              ]
            },
            "description": "Filter by friction kind"
          },
          {
            "in": "query",
            "name": "metrics",
            "schema": {
              "type": "string",
              "example": "time_series,by_actor,hotspots"
            },
            "description": "Comma-separated list of metric sections to include. Omit to include all."
          },
          {
            "in": "query",
            "name": "events_limit",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 500
            },
            "description": "Max recent events to return"
          },
          {
            "in": "query",
            "name": "events_offset",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            },
            "description": "Offset for recent events pagination"
          },
          {
            "in": "query",
            "name": "compare",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "default": "false"
            },
            "description": "Include previous-period comparison"
          }
        ],
        "responses": {
          "200": {
            "description": "Friction forensics response. Sections not requested via `metrics` will be empty arrays.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Composite friction forensics response. Each section is independently\nloaded based on the `metrics` query parameter. Sections not requested\nreturn empty arrays.\n",
                  "properties": {
                    "time_series": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "event_count": {
                            "type": "integer",
                            "format": "int64"
                          }
                        }
                      }
                    },
                    "by_actor": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "actor": {
                            "type": "string",
                            "enum": [
                              "human",
                              "agent"
                            ]
                          },
                          "kind": {
                            "type": "string"
                          },
                          "event_count": {
                            "type": "integer",
                            "format": "int64"
                          }
                        }
                      }
                    },
                    "by_tool": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "tool": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "event_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "unique_users": {
                            "type": "integer",
                            "format": "int64"
                          }
                        }
                      }
                    },
                    "top_unknown_commands": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "command": {
                            "type": "string"
                          },
                          "input": {
                            "type": "string"
                          },
                          "attempt_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "unique_users": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "last_seen": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "agent_stats": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "agent_type": {
                            "type": "string"
                          },
                          "total_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "agent_triggered": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "human_triggered": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "unique_users": {
                            "type": "integer",
                            "format": "int64"
                          }
                        }
                      }
                    },
                    "client_versions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "version": {
                            "type": "string"
                          },
                          "event_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "unique_kinds": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "first_seen": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "last_seen": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "hotspots": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "command": {
                            "type": "string"
                          },
                          "subcommand": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "event_count": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "affected_users": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "last_seen": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "recent_events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ts": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "event": {
                            "type": "string"
                          },
                          "distinct_id": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "actor": {
                            "type": "string"
                          },
                          "agent_type": {
                            "type": "string"
                          },
                          "command": {
                            "type": "string"
                          },
                          "subcommand": {
                            "type": "string"
                          },
                          "input": {
                            "type": "string"
                          },
                          "error_msg": {
                            "type": "string"
                          },
                          "suggestion": {
                            "type": "string"
                          },
                          "lib_version": {
                            "type": "string"
                          },
                          "path_bucket": {
                            "type": "string"
                          },
                          "total_count": {
                            "type": "integer",
                            "format": "int64",
                            "description": "Total matching events (for pagination)"
                          }
                        }
                      }
                    },
                    "events_total": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Total matching friction events (for pagination metadata)"
                    },
                    "events_limit": {
                      "type": "integer",
                      "format": "int32"
                    },
                    "events_offset": {
                      "type": "integer",
                      "format": "int32"
                    },
                    "previous_period": {
                      "type": "object",
                      "nullable": true,
                      "description": "Present only when `compare=true`",
                      "properties": {
                        "kind": {
                          "type": "string"
                        },
                        "current_count": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "previous_count": {
                          "type": "integer",
                          "format": "int64"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/commands": {
      "get": {
        "operationId": "agentxCommands",
        "summary": "Get command usage ranking",
        "description": "Returns the top 50 commands by usage count with percentage distribution.\nCommand names are extracted from `properties->>'command'` in events.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/1"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/2"
          }
        ],
        "responses": {
          "200": {
            "description": "Command distribution",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1agents/get/responses/200/content/application~1json/schema/items"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/agents": {
      "get": {
        "operationId": "agentxAgents",
        "summary": "Get agent type distribution",
        "description": "Returns event counts grouped by actor and agent type.\nLabels are formatted as `{actor}/{agent_type}` (e.g., `agent/copilot`).\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/1"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/2"
          }
        ],
        "responses": {
          "200": {
            "description": "Agent distribution",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "type": "string",
                        "description": "Category label (command name, agent type, etc.)"
                      },
                      "count": {
                        "type": "integer",
                        "format": "int64"
                      },
                      "pct": {
                        "type": "number",
                        "format": "double",
                        "description": "Percentage of total (0–100)"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/versions": {
      "get": {
        "operationId": "agentxVersions",
        "summary": "Get version adoption data",
        "description": "Returns daily event counts grouped by client library version\n(`properties->>'$lib_version'`). Useful for tracking version adoption curves.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/1"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/2"
          }
        ],
        "responses": {
          "200": {
            "description": "Version time series (daily buckets)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/responses/200/content/application~1json/schema/items"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/users": {
      "get": {
        "operationId": "agentxUsers",
        "summary": "Get daily active users",
        "description": "Returns daily active user counts. Users are identified by\n`COALESCE(properties->>'$user_id', distinct_id)`.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          },
          {
            "in": "query",
            "name": "start_date",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-03-19"
            },
            "description": "Start of date range (ISO 8601 date or datetime). Defaults to 7 days ago."
          },
          {
            "in": "query",
            "name": "end_date",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-03-26"
            },
            "description": "End of date range (ISO 8601 date or datetime). Defaults to now."
          }
        ],
        "responses": {
          "200": {
            "description": "DAU time series",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "bucket": {
                        "type": "string",
                        "description": "Time bucket (RFC 3339 for hourly, `YYYY-MM-DD` for daily)",
                        "example": "2026-03-26T14:00:00Z"
                      },
                      "count": {
                        "type": "integer",
                        "format": "int64"
                      },
                      "event": {
                        "type": "string",
                        "description": "Event name or version string (present when grouped by event/version)"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agentx/{app_id}/export": {
      "get": {
        "operationId": "agentxExport",
        "summary": "Export friction events as CSV",
        "description": "Streams all friction events for the date range as a CSV download.\n\n**Columns:** `ts`, `event`, `distinct_id`, `kind`, `actor`, `agent_type`,\n`command`, `subcommand`, `input`, `error_msg`, `suggestion`, `lib_version`,\n`path_bucket`, `user_id`.\n",
        "tags": [
          "AgentX"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D/get/parameters/0"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/1"
          },
          {
            "$ref": "#/paths/~1api~1v1~1agentx~1%7Bapp_id%7D~1users/get/parameters/2"
          }
        ],
        "responses": {
          "200": {
            "description": "CSV file download",
            "headers": {
              "Content-Disposition": {
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=agentx-friction-app_01234.csv"
                }
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/repos/{repo_id}": {
      "get": {
        "operationId": "getPublicRepo",
        "summary": "Get public repository information",
        "description": "Retrieves basic public information about a repository.\nDoes not include sensitive team information or access control details.\n\n**Authentication:** Not required (public endpoint)\n**Rate limit:** Tiered per IP (60 req/min unauthenticated, 300 req/min authenticated)\n",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "repo_id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository ID to retrieve"
          }
        ],
        "responses": {
          "200": {
            "description": "Repository information retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "type"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "git"
                      ],
                      "example": "git"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "is_public": {
                      "type": "boolean",
                      "example": false
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/repos/{repo_id}/merge-candidates": {
      "get": {
        "operationId": "getRepoMergeCandidates",
        "summary": "Get repositories that could be merged",
        "description": "Returns a list of repositories with matching remote hashes that could be merged\ninto this repository. Respects `is_public` flag for fork protection.\n\n**Use case:** Help users identify duplicate registrations that should be consolidated.\n\n**Authentication:** Not required\n**Rate limit:** Tiered per IP\n",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "repo_id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository ID to find merge candidates for"
          }
        ],
        "responses": {
          "200": {
            "description": "List of merge candidates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "repo_id": {
                        "type": "string",
                        "example": "repo_01934f5b-1234-7abc-9012-def456789012"
                      },
                      "team_id": {
                        "type": "string",
                        "example": "team_def456uvw"
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2025-12-10T08:15:00Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/repos/{repo_id}/has-merge-candidates": {
      "get": {
        "operationId": "hasRepoMergeCandidates",
        "summary": "Check if merge candidates exist",
        "description": "Lightweight check to determine if this repository has merge candidates.\nReturns a boolean without fetching full candidate details.\n\n**Use case:** Show UI indication of potential merges without expensive list fetch.\n\n**Authentication:** Not required\n**Rate limit:** Tiered per IP\n",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "repo_id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository ID to check"
          }
        ],
        "responses": {
          "200": {
            "description": "Merge candidate status determined",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "has_candidates"
                  ],
                  "properties": {
                    "has_candidates": {
                      "type": "boolean",
                      "description": "Whether merge candidates exist for this repo",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/repos/{repo_id}/doctor": {
      "get": {
        "operationId": "getRepoDoctorInfo",
        "summary": "Run repository diagnostics",
        "description": "Runs diagnostic checks on a repository including health status,\nconfiguration validation, and merge analysis.\n\n**Diagnostics included:**\n- Repository status and metadata\n- Team associations\n- Merge candidate analysis\n- Git configuration validation\n- Feature availability\n\n**Authentication:** Not required\n**Rate limit:** Tiered per IP\n",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "repo_id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository ID to diagnose"
          }
        ],
        "responses": {
          "200": {
            "description": "Diagnostic results retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "healthy",
                        "degraded",
                        "error"
                      ],
                      "example": "healthy"
                    },
                    "checks": {
                      "type": "object",
                      "properties": {
                        "metadata_valid": {
                          "type": "boolean",
                          "example": true
                        },
                        "teams_accessible": {
                          "type": "boolean",
                          "example": true
                        },
                        "merge_analysis": {
                          "type": "object",
                          "properties": {
                            "has_candidates": {
                              "type": "boolean",
                              "example": true
                            },
                            "candidate_count": {
                              "type": "integer",
                              "example": 1
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/teams/{team_id}": {
      "get": {
        "operationId": "getPublicTeam",
        "summary": "Get public team information",
        "description": "Retrieves basic public information about a team.\nDoes not include sensitive member or access control information.\n\n**Authentication:** Not required\n**Rate limit:** Tiered per IP\n",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_",
              "example": "team_abc123xyz"
            },
            "description": "Team ID to retrieve"
          }
        ],
        "responses": {
          "200": {
            "description": "Team information retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "slug",
                    "name"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "slug": {
                      "type": "string",
                      "description": "URL-safe team identifier",
                      "example": "my-team"
                    },
                    "name": {
                      "type": "string",
                      "example": "My Team"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/teams/{team_id}/repos": {
      "get": {
        "operationId": "getTeamRepos",
        "summary": "Get team's repositories",
        "description": "Lists all repositories associated with a team (public view).\nDoes not include private or access-controlled repository details.\n\n**Authentication:** Not required\n**Rate limit:** Tiered per IP\n",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_",
              "example": "team_abc123xyz"
            },
            "description": "Team ID to list repositories for"
          }
        ],
        "responses": {
          "200": {
            "description": "List of team repositories",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "repo_id": {
                        "type": "string",
                        "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                      },
                      "type": {
                        "type": "string",
                        "enum": [
                          "git"
                        ],
                        "example": "git"
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2025-12-18T10:30:00Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/teams/{team_id}/merge-candidates": {
      "get": {
        "operationId": "getTeamMergeCandidates",
        "summary": "Get team's merge candidates",
        "description": "Returns repositories from this team that have merge candidates\n(duplicate registrations that could be consolidated).\n\n**Authentication:** Not required\n**Rate limit:** Tiered per IP\n",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_",
              "example": "team_abc123xyz"
            },
            "description": "Team ID to analyze for merge candidates"
          }
        ],
        "responses": {
          "200": {
            "description": "List of repositories with merge candidates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "repo_id": {
                        "type": "string",
                        "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                      },
                      "merge_candidates": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "repo_id": {
                              "type": "string",
                              "example": "repo_01934f5b-1234-7abc-9012-def456789012"
                            },
                            "team_id": {
                              "type": "string",
                              "example": "team_def456uvw"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/teams/{team_id}/info": {
      "get": {
        "operationId": "getTeamPublicInfo",
        "summary": "Get team public info for join page",
        "description": "Returns information needed for team join/signup page.\nIncludes team name, member count, and visibility status.\n\n**Use case:** Public join page showing team details without authentication.\n\n**Authentication:** Not required\n**Rate limit:** Tiered per IP\n",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_",
              "example": "team_abc123xyz"
            },
            "description": "Team ID to retrieve info for"
          }
        ],
        "responses": {
          "200": {
            "description": "Team public information retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "name",
                    "slug",
                    "member_count"
                  ],
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "Team display name",
                      "example": "Product Engineering"
                    },
                    "slug": {
                      "type": "string",
                      "description": "URL-safe team identifier",
                      "example": "product-engineering"
                    },
                    "member_count": {
                      "type": "integer",
                      "description": "Number of team members",
                      "example": 12
                    },
                    "description": {
                      "type": "string",
                      "description": "Team description or tagline",
                      "nullable": true,
                      "example": "Building the next generation platform"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/config/features": {
      "get": {
        "operationId": "getConfigFeatures",
        "summary": "Get platform feature flags",
        "description": "Returns platform-level feature flags that determine which features are enabled/disabled.\nUsed by frontend and clients to conditionally render UI, show settings, or enable features.\n\n**Feature flags:**\n- **photos:** Photo/media features enabled\n- **notifications:** Notification delivery channels configuration\n\nFor user-targeted feature flags via PostHog, use the frontend SDK with user context.\n\n**Authentication:** Not required (public endpoint)\n**Rate limit:** Standard rate limiting applies\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Feature flags retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "photos",
                    "notifications"
                  ],
                  "properties": {
                    "photos": {
                      "type": "boolean",
                      "description": "Photo/media features enabled",
                      "example": true
                    },
                    "notifications": {
                      "type": "object",
                      "description": "Notification channel configuration",
                      "properties": {
                        "email": {
                          "type": "boolean",
                          "example": true
                        },
                        "push": {
                          "type": "boolean",
                          "example": true
                        },
                        "sms": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signing-keys": {
      "get": {
        "operationId": "getSigningKeys",
        "summary": "Get signing keys (JWKS format)",
        "description": "Returns the global SageOx signing keys in JWKS (JSON Web Key Set) format per RFC 7517.\nUsed to verify signatures on SAGEOX.md files and other signed artifacts.\n\n**Format:** JWKS-style response with Ed25519 public keys\n**Key type:** OKP (Octet Key Pair) with Ed25519 curve\n**Algorithm:** EdDSA\n\n**Caching:**\n- Fresh for 10 hours (max-age=36000)\n- Serve stale up to 7 days while revalidating in background\n- CDN-safe with public Cache-Control header\n\n**Authentication:** Not required (public endpoint)\n**Rate limit:** 30 requests/minute per IP (prevents key enumeration)\n\n**Note:** In the team-only model, organization-specific signing keys have been removed.\nAll signatures use the global SageOx signing key.\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Signing keys retrieved (JWKS format)",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "Caching directive for CDN and browsers",
                "example": "public, max-age=36000, stale-while-revalidate=604800"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "keys"
                  ],
                  "properties": {
                    "keys": {
                      "type": "array",
                      "description": "Array of JSON Web Keys",
                      "items": {
                        "type": "object",
                        "required": [
                          "kid",
                          "kty",
                          "alg",
                          "crv",
                          "x",
                          "use"
                        ],
                        "properties": {
                          "kid": {
                            "type": "string",
                            "description": "Key ID (matches public_key_id in signature blocks)",
                            "example": "sageox-key-2025-01"
                          },
                          "kty": {
                            "type": "string",
                            "description": "Key type (OKP for Octet Key Pair)",
                            "enum": [
                              "OKP"
                            ],
                            "example": "OKP"
                          },
                          "alg": {
                            "type": "string",
                            "description": "Signature algorithm",
                            "enum": [
                              "EdDSA"
                            ],
                            "example": "EdDSA"
                          },
                          "crv": {
                            "type": "string",
                            "description": "Elliptic curve",
                            "enum": [
                              "Ed25519"
                            ],
                            "example": "Ed25519"
                          },
                          "x": {
                            "type": "string",
                            "description": "Base64url-encoded public key (32 bytes for Ed25519 = 43 chars)",
                            "example": "abcdefghijklmnopqrstuvwxyz0123456789ABCD"
                          },
                          "use": {
                            "type": "string",
                            "description": "Key use (sig for signatures)",
                            "enum": [
                              "sig"
                            ],
                            "example": "sig"
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "with_keys": {
                    "value": {
                      "keys": [
                        {
                          "kid": "sageox-key-2025-01",
                          "kty": "OKP",
                          "alg": "EdDSA",
                          "crv": "Ed25519",
                          "x": "abcdefghijklmnopqrstuvwxyz0123456789ABCD",
                          "use": "sig"
                        }
                      ]
                    }
                  },
                  "no_keys": {
                    "value": {
                      "keys": []
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/update": {
      "get": {
        "operationId": "getSignedUpdate",
        "summary": "Get signed SAGEOX.md update",
        "description": "Returns the signed SAGEOX.md file (team conventions) for the authenticated user.\nThe response includes content and cryptographic signature for verification.\n\n**Signature format:** EdDSA signature using the global SageOx signing key\n**Verification:** Use /api/v1/signing-keys to get public key for verification\n\n**Parameters:**\n- **team_id** (optional): Specific team's SAGEOX.md. If not provided, returns default/merged content.\n\n**Authorization:** User must be member of requested team (if team_id specified)\n\n**Authentication:** Bearer token required\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "team_id",
            "schema": {
              "type": "string",
              "pattern": "^team_",
              "example": "team_abc123xyz"
            },
            "description": "Optional team ID to get team-specific SAGEOX.md"
          }
        ],
        "responses": {
          "200": {
            "description": "Signed SAGEOX.md content",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "content",
                    "signature"
                  ],
                  "properties": {
                    "content": {
                      "type": "string",
                      "description": "SAGEOX.md file content (markdown)",
                      "example": "# SAGEOX.md\\n\\nTeam conventions and standards..."
                    },
                    "signature": {
                      "type": "object",
                      "description": "Cryptographic signature metadata",
                      "properties": {
                        "value": {
                          "type": "string",
                          "description": "EdDSA signature (base64url-encoded)",
                          "example": "abcdefgh..."
                        },
                        "algorithm": {
                          "type": "string",
                          "description": "Signing algorithm used",
                          "enum": [
                            "EdDSA"
                          ],
                          "example": "EdDSA"
                        },
                        "public_key_id": {
                          "type": "string",
                          "description": "Key ID used to create signature (matches JWKS kid)",
                          "example": "sageox-key-2025-01"
                        }
                      }
                    },
                    "team_id": {
                      "type": "string",
                      "description": "Team ID if team-specific content (null for default)",
                      "nullable": true,
                      "example": "team_abc123xyz"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Unauthorized - user not member of requested team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/entities": {
      "get": {
        "operationId": "searchEntities",
        "summary": "Search user's entities",
        "description": "Full-text search across user's entities (repositories, teams, etc.).\nReturns matching entities with metadata.\n\n**Query parameter:** `q` - search query string (required)\n**Type parameter:** `type` - optional filter by entity type\n\n**Supported entity types:**\n- `repo` - repositories\n- `team` - teams\n- `user` - users (limited visibility)\n\n**Authentication:** Bearer token required\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "description": "Search query string",
            "example": "my-project"
          },
          {
            "in": "query",
            "name": "type",
            "schema": {
              "type": "string",
              "enum": [
                "repo",
                "team",
                "user"
              ]
            },
            "description": "Optional entity type filter",
            "example": "repo"
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "repo",
                              "team",
                              "user"
                            ],
                            "example": "repo"
                          },
                          "id": {
                            "type": "string",
                            "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                          },
                          "name": {
                            "type": "string",
                            "example": "my-project"
                          },
                          "description": {
                            "type": "string",
                            "nullable": true,
                            "example": "Production repository"
                          },
                          "score": {
                            "type": "number",
                            "description": "Relevance score for sorting",
                            "example": 0.95
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid search query",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/guidance/": {
      "get": {
        "operationId": "getRootGuidance",
        "summary": "Get root guidance content",
        "description": "Returns guidance content for the root path.\nUsed to bootstrap guided experiences and progressive disclosure.\n\n**Progressive disclosure:** Guidance is tiered based on user context:\n- Unauthenticated: Limited guidance, 60 req/min\n- Authenticated: Full guidance, 300 req/min\n\n**Authentication:** Optional (tiered rate limiting based on auth status)\n**Rate limit:** Tiered (60 req/min unauthenticated, 300 req/min authenticated)\n",
        "tags": [
          "Guidance"
        ],
        "security": [
          {
            "BearerAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "Root guidance content",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "title": {
                      "type": "string",
                      "example": "Getting Started"
                    },
                    "content": {
                      "type": "string",
                      "description": "Markdown content",
                      "example": "# Getting Started\\n\\nWelcome to SageOx..."
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "href": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/guidance/{path}": {
      "get": {
        "operationId": "getPathGuidance",
        "summary": "Get path-based guidance",
        "description": "Returns guidance content for a specific path (wildcard route).\nSupports nested paths for progressive disclosure.\n\n**Path examples:**\n- `/api/v1/guidance/getting-started`\n- `/api/v1/guidance/repos/setup`\n- `/api/v1/guidance/teams/collaboration`\n\n**Progressive disclosure:** Content adjusted based on user tier and context\n\n**Authentication:** Optional (tiered rate limiting)\n**Rate limit:** Tiered (60 req/min unauthenticated, 300 req/min authenticated)\n",
        "tags": [
          "Guidance"
        ],
        "security": [
          {
            "BearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Guidance path (supports nested paths with slashes)",
            "example": "getting-started/setup"
          }
        ],
        "responses": {
          "200": {
            "description": "Guidance content for path",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string",
                      "example": "getting-started"
                    },
                    "title": {
                      "type": "string",
                      "example": "Getting Started"
                    },
                    "content": {
                      "type": "string",
                      "description": "Markdown content",
                      "example": "# Getting Started\\n\\nStep by step guide..."
                    },
                    "next": {
                      "type": "array",
                      "description": "Suggested next topics",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Guidance not found for path",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/guidance/my-stats": {
      "get": {
        "operationId": "getGuidanceStats",
        "summary": "Get user guidance statistics",
        "description": "Returns guidance-related statistics for the authenticated user.\nTracks progress, visited topics, and engagement metrics.\n\n**Statistics tracked:**\n- Topics visited\n- Guidance completion percentage\n- Recommended next steps based on usage\n\n**Authentication:** Bearer token required\n",
        "tags": [
          "Guidance"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Guidance statistics for user",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total_topics": {
                      "type": "integer",
                      "example": 15
                    },
                    "visited_topics": {
                      "type": "integer",
                      "example": 8
                    },
                    "completion_percentage": {
                      "type": "integer",
                      "description": "Percentage of guidance completed",
                      "example": 53
                    },
                    "last_visited": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "recommended": {
                      "type": "array",
                      "description": "Recommended topics based on usage",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "reason": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/newsletter": {
      "post": {
        "operationId": "subscribeNewsletter",
        "summary": "Subscribe to newsletter",
        "description": "Subscribes an email address to the product newsletter.\nSyncs to MailerLite if configured.\n\n**Rate limit:** Standard rate limiting\n**Duplicate handling:** Idempotent - returns success for existing subscriptions\n\n**Authentication:** Not required (public endpoint)\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Email address to subscribe",
                    "example": "user@example.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Newsletter subscription processed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Subscription successful"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid email address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/gitlab/pat": {
      "get": {
        "operationId": "getGitLabPAT",
        "summary": "Get GitLab personal access token",
        "description": "Returns the authenticated user's GitLab personal access token.\nUsed by CLI and integrations to authenticate with GitLab API.\n\n**Security:** Token is sensitive - only returned to authenticated user\n**Token type:** GitLab PAT (personal access token)\n**Scopes:** api, read_repository, write_repository\n\n**Authentication:** Bearer token required\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "GitLab PAT retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "token"
                  ],
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "GitLab personal access token",
                      "example": "glpat-abc123xyz..."
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Token expiration timestamp (null if no expiry)",
                      "nullable": true,
                      "example": "2026-12-18T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "GitLab token not configured for user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/docs": {
      "get": {
        "operationId": "getApiDocs",
        "summary": "Get API documentation UI",
        "description": "Returns interactive API documentation (Swagger/OpenAPI UI).\nServes the SwaggerUI interface for exploring the API.\n\n**Authentication:** Not required (public endpoint)\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "API documentation HTML page",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/docs/openapi.json": {
      "get": {
        "operationId": "getOpenAPISpec",
        "summary": "Get OpenAPI specification",
        "description": "Returns the complete OpenAPI 3.1.0 specification for the API.\nUsed by code generation tools, API clients, and documentation generators.\n\n**Format:** OpenAPI 3.1.0 (JSON)\n**Caching:** Safe to cache and serve from CDN\n\n**Authentication:** Not required (public endpoint)\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI specification",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/avatars/{id}": {
      "get": {
        "operationId": "getAvatar",
        "summary": "Generate identicon avatar",
        "description": "Generates a deterministic identicon avatar (visual hash) for a given ID.\nUseful for displaying unique visual identifiers for users, teams, or repos.\n\n**SVG generation:** Seedable random vector art based on ID hash\n**Deterministic:** Same ID always generates same avatar\n**Caching:** Safe to cache indefinitely (content-addressed)\n\n**Format negotiation:**\n- `Accept: image/svg+xml` → SVG (default, lightweight)\n- `Accept: image/png` → PNG (rasterized, if supported)\n\n**Authentication:** Not required (public endpoint)\n**Rate limit:** Standard rate limiting\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID to generate avatar for (user_id, team_id, repo_id, etc.)",
            "example": "usr_01aq5p00aq5p00aq5p"
          },
          {
            "in": "header",
            "name": "Accept",
            "schema": {
              "type": "string",
              "enum": [
                "image/svg+xml",
                "image/png"
              ]
            },
            "description": "Desired image format",
            "example": "image/svg+xml"
          }
        ],
        "responses": {
          "200": {
            "description": "Generated identicon avatar",
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Invalid ID format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/metrics": {
      "get": {
        "operationId": "getPrometheusMetrics",
        "summary": "Get Prometheus metrics",
        "description": "Returns application metrics in Prometheus text format.\nUsed by monitoring systems (Prometheus, Grafana, etc.) for telemetry collection.\n\n**Format:** Prometheus exposition format (text/plain)\n**Endpoint type:** Scrape endpoint (intended for machine consumption)\n**Metrics included:**\n- HTTP request duration and status codes\n- Database connection pool stats\n- Business logic metrics (repos registered, teams created, etc.)\n- Custom application metrics\n\n**Authentication:** Not required (typically scraped by internal monitoring)\n**Rate limit:** Standard rate limiting (or exempt in some deployments)\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Prometheus metrics in text format",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string",
                  "example": "# HELP http_requests_total Total HTTP requests\\n# TYPE http_requests_total counter\\nhttp_requests_total{method=\"GET\",status=\"200\"} 1234\\n"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/ready/temporal/smoke": {
      "get": {
        "operationId": "temporalSmokeTest",
        "summary": "Temporal workflow engine smoke test",
        "description": "Quick connectivity and health check for Temporal workflow engine.\nReturns status of Temporal connection and basic functionality.\n\n**Purpose:** Verification endpoint for deployment health checks\n**Timeout:** ~5 seconds (fail-fast)\n\n**Authentication:** Not required (health check endpoint)\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Temporal service is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "degraded"
                      ],
                      "example": "ok"
                    },
                    "message": {
                      "type": "string",
                      "example": "Temporal server is reachable"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporal service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "error"
                      ],
                      "example": "error"
                    },
                    "message": {
                      "type": "string",
                      "example": "Unable to reach Temporal server"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/ready/gitlab/smoke": {
      "get": {
        "operationId": "gitlabSmokeTest",
        "summary": "GitLab integration smoke test",
        "description": "Quick connectivity and health check for GitLab integration.\nReturns status of GitLab API endpoint and authentication.\n\n**Purpose:** Verification endpoint for deployment health checks\n**Timeout:** ~5 seconds (fail-fast)\n\n**Authentication:** Not required (health check endpoint)\n",
        "tags": [
          "Miscellaneous"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "GitLab service is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "degraded"
                      ],
                      "example": "ok"
                    },
                    "message": {
                      "type": "string",
                      "example": "GitLab server is reachable"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "GitLab service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "error"
                      ],
                      "example": "error"
                    },
                    "message": {
                      "type": "string",
                      "example": "Unable to reach GitLab server"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings": {
      "post": {
        "operationId": "startRecordingRepo",
        "summary": "Start recording (repo-scoped)",
        "description": "Initialize a new chunked recording for a repository. Returns presigned URL\nfor uploading the first chunk.\n\n**Workflow:**\n1. POST to start recording → get recording_id and upload URL\n2. Upload audio chunks to presigned URL\n3. POST /chunks/prefetch to batch-fetch future chunk URLs\n4. POST /chunks/heartbeat after each chunk upload (optional)\n5. POST /complete to finalize and trigger processing\n\n**Status flow:** pending → uploading → processing → ready\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier (repo_<uuidv7>)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "mime_type"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Optional display name for the recording",
                    "example": "Architecture Review - Jan 2025"
                  },
                  "mime_type": {
                    "type": "string",
                    "description": "Media type (audio/webm, video/mp4, audio/mp4, etc.)",
                    "example": "audio/webm"
                  },
                  "duration_hint": {
                    "type": "integer",
                    "format": "int64",
                    "description": "Expected duration in seconds (for progress tracking)",
                    "example": 1800
                  },
                  "metadata": {
                    "type": "object",
                    "description": "Optional client-provided context",
                    "example": {
                      "topic": "API design",
                      "participants": 2
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Recording initialized successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "recording_id",
                    "upload",
                    "created_at"
                  ],
                  "properties": {
                    "recording_id": {
                      "type": "string",
                      "description": "Unique identifier for this recording (rec_<uuidv7>)",
                      "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "upload": {
                      "type": "object",
                      "required": [
                        "upload_url",
                        "expires_at",
                        "chunk_index",
                        "bucket",
                        "s3_key"
                      ],
                      "properties": {
                        "upload_url": {
                          "type": "string",
                          "format": "uri",
                          "description": "Presigned PUT URL for direct S3 upload",
                          "example": "https://s3.amazonaws.com/bucket/repos/repo_01934f5a/recordings/rec_01934f5a/chunk_1?..."
                        },
                        "fields": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "string"
                          },
                          "description": "Additional form fields for multipart uploads (if applicable)"
                        },
                        "expires_at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the presigned URL expires",
                          "example": "2025-01-30T20:22:00Z"
                        },
                        "chunk_index": {
                          "type": "integer",
                          "description": "Zero-based chunk index",
                          "example": 1
                        },
                        "bucket": {
                          "type": "string",
                          "description": "S3 bucket name",
                          "example": "sageox-recordings-prod"
                        },
                        "s3_key": {
                          "type": "string",
                          "description": "Full S3 object key path",
                          "example": "repos/repo_01934f5a/recordings/rec_01934f5a/chunk_1"
                        }
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Timestamp when recording was initialized",
                      "example": "2025-01-30T14:22:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing mime_type, invalid format, etc.)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_mime_type": {
                    "value": {
                      "error": "mime_type is required"
                    }
                  },
                  "invalid_mime_type": {
                    "value": {
                      "error": "invalid mime_type format"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - no access to repository",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listRecordingsRepo",
        "summary": "List recordings (repo-scoped)",
        "description": "Retrieve paginated list of recordings for a repository with optional filtering\nby status, media type, and timestamp range.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "uploading",
                "processing",
                "ready",
                "failed",
                "deleted"
              ],
              "example": "ready"
            },
            "description": "Filter by recording status"
          },
          {
            "name": "mime_type",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "audio/"
            },
            "description": "Filter by MIME type prefix (e.g., 'audio/', 'video/')"
          },
          {
            "name": "timestamp_start",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "example": "2025-01-01T00:00:00Z"
            },
            "description": "Filter recordings created after this timestamp (RFC3339)"
          },
          {
            "name": "timestamp_end",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "example": "2025-01-31T23:59:59Z"
            },
            "description": "Filter recordings created before this timestamp (RFC3339)"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100,
              "example": 20
            },
            "description": "Maximum number of recordings to return"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "example": 0
            },
            "description": "Number of recordings to skip for pagination"
          }
        ],
        "responses": {
          "200": {
            "description": "List of recordings retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "recordings",
                    "pagination"
                  ],
                  "properties": {
                    "recordings": {
                      "type": "array",
                      "items": {
                        "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings~1%7Brec_id%7D/get/responses/200/content/application~1json/schema"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "required": [
                        "total",
                        "limit",
                        "offset"
                      ],
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 42
                        },
                        "limit": {
                          "type": "integer",
                          "example": 20
                        },
                        "offset": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_timestamp": {
                    "value": {
                      "error": "invalid timestamp_start format (expected RFC3339)"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}": {
      "get": {
        "operationId": "getRecordingRepo",
        "summary": "Get recording details (repo-scoped)",
        "description": "Retrieve full recording details including metadata, status, processing steps,\nand URLs. Processing steps show the pipeline state (upload, transcribe, summarize, commit).\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Recording identifier (rec_<uuidv7>)",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recording details retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "context_type",
                    "context_id",
                    "title",
                    "status",
                    "mime_type",
                    "size",
                    "chunk_count",
                    "created_by",
                    "created_at",
                    "updated_at"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Recording identifier (rec_<uuidv7>)",
                      "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "context_type": {
                      "type": "string",
                      "enum": [
                        "repo",
                        "team"
                      ],
                      "description": "Recording scope type",
                      "example": "repo"
                    },
                    "context_id": {
                      "type": "string",
                      "description": "Repository or team ID",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "title": {
                      "type": "string",
                      "description": "Display name",
                      "example": "Architecture Review - Jan 2025"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "uploading",
                        "processing",
                        "ready",
                        "failed",
                        "deleted"
                      ],
                      "description": "Current recording status",
                      "example": "ready"
                    },
                    "mime_type": {
                      "type": "string",
                      "description": "Media type",
                      "example": "audio/webm"
                    },
                    "duration": {
                      "type": "number",
                      "format": "double",
                      "nullable": true,
                      "description": "Duration in seconds (null if not yet known)",
                      "example": 1847.5
                    },
                    "size": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Total size in bytes",
                      "example": 3145728
                    },
                    "chunk_count": {
                      "type": "integer",
                      "description": "Number of uploaded chunks",
                      "example": 12
                    },
                    "playback_url": {
                      "type": "string",
                      "description": "URL for playback (empty if not ready)",
                      "example": "https://sageox.ai/recordings/rec_01934f5a/play"
                    },
                    "thumbnail_url": {
                      "type": "string",
                      "nullable": true,
                      "description": "Thumbnail URL (if available)"
                    },
                    "metadata": {
                      "type": "object",
                      "description": "Client-provided and system metadata"
                    },
                    "processing_steps": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "additionalProperties": true
                      },
                      "description": "Pipeline step states (upload, transcribe, summarize, commit)",
                      "example": {
                        "upload": {
                          "status": "completed",
                          "started_at": "2025-01-30T14:22:00Z",
                          "completed_at": "2025-01-30T14:45:30Z"
                        },
                        "transcribe": {
                          "status": "in-progress",
                          "started_at": "2025-01-30T14:45:30Z"
                        },
                        "summarize": {
                          "status": "pending"
                        },
                        "commit": {
                          "status": "pending"
                        }
                      }
                    },
                    "created_by": {
                      "type": "string",
                      "description": "User ID of recording creator",
                      "example": "usr_abc123xyz"
                    },
                    "created_by_name": {
                      "type": "string",
                      "nullable": true,
                      "description": "Display name of creator"
                    },
                    "created_by_email": {
                      "type": "string",
                      "nullable": true,
                      "description": "Email of creator"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-01-30T14:22:00Z"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-01-30T14:45:30Z"
                    },
                    "completed_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "When recording was finalized (null if not complete)"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid recording ID format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateRecordingRepo",
        "summary": "Update recording metadata (repo-scoped)",
        "description": "Update recording title and/or metadata. Only specified fields are updated.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Updated display name",
                    "example": "API Design Discussion - Updated"
                  },
                  "metadata": {
                    "type": "object",
                    "description": "Additional context to merge with existing metadata",
                    "example": {
                      "speaker": "Team Lead",
                      "resolved": true
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recording updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings~1%7Brec_id%7D/get/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteRecordingRepo",
        "summary": "Delete recording (repo-scoped)",
        "description": "Soft-delete a recording. The recording is marked as deleted but retained for auditing.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Recording deleted successfully"
          },
          "400": {
            "description": "Invalid recording ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/chunks": {
      "post": {
        "operationId": "getChunkURLRepo",
        "summary": "Get presigned URL for chunk upload (repo-scoped)",
        "description": "Get a presigned URL for uploading a specific chunk. Use this to upload\nindividual chunks sequentially, or use /chunks/prefetch for batch URLs.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "chunk_index"
                ],
                "properties": {
                  "chunk_index": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Zero-based chunk index",
                    "example": 1
                  },
                  "chunk_size": {
                    "type": "integer",
                    "format": "int64",
                    "description": "Chunk size in bytes (optional, for validation)",
                    "example": 262144
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned URL generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "upload"
                  ],
                  "properties": {
                    "upload": {
                      "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings/post/responses/201/content/application~1json/schema/properties/upload"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Recording not in uploading state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/chunks/prefetch": {
      "post": {
        "operationId": "prefetchChunkURLsRepo",
        "summary": "Batch prefetch chunk upload URLs (repo-scoped)",
        "description": "Generate multiple presigned URLs at once for continued recording during API downtime\n(deployments, hot-reload). Each URL expires after 6 hours.\n\n**Why this matters:**\n- During API restarts, the client has pre-fetched URLs and can continue recording\n- Recording doesn't stall waiting for new presigned URLs\n- Workflow automatically heartbeats on prefetch to keep session alive\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "count"
                ],
                "properties": {
                  "count": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 40,
                    "default": 20,
                    "description": "Number of URLs to prefetch (clamped to 1-40)",
                    "example": 20
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "URLs prefetched successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "chunks"
                  ],
                  "properties": {
                    "chunks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings/post/responses/201/content/application~1json/schema/properties/upload"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Recording not in uploading state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/chunks/heartbeat": {
      "post": {
        "operationId": "chunkHeartbeatRepo",
        "summary": "Send chunk upload heartbeat (repo-scoped)",
        "description": "Lightweight signal that a chunk was successfully uploaded to S3.\nKeeps the session workflow aware of recording activity without generating\na new presigned URL. Fire-and-forget (no response body expected).\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "chunk_index"
                ],
                "properties": {
                  "chunk_index": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Index of chunk that was uploaded",
                    "example": 5
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Heartbeat recorded"
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/pause": {
      "post": {
        "operationId": "pauseRecordingRepo",
        "summary": "Pause recording (repo-scoped)",
        "description": "Signal to the session workflow that recording was paused. Resets the\ninactivity timer so the workflow doesn't auto-complete during pause.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Pause signal recorded"
          },
          "400": {
            "description": "Invalid recording ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/resume": {
      "post": {
        "operationId": "resumeRecordingRepo",
        "summary": "Resume recording (repo-scoped)",
        "description": "Signal to the session workflow that recording was resumed after being paused.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Resume signal recorded"
          },
          "400": {
            "description": "Invalid recording ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/complete": {
      "post": {
        "operationId": "completeRecordingRepo",
        "summary": "Complete recording upload (repo-scoped)",
        "description": "Finalize the recording after all chunks are uploaded. Updates recording\nstatus to \"processing\" and starts the Temporal workflow for transcription,\nsummarization, and commit to ledger.\n\n**Status transition:** pending/uploading → processing → ready\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "chunk_count"
                ],
                "properties": {
                  "chunk_count": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Total number of chunks uploaded",
                    "example": 12
                  },
                  "total_size": {
                    "type": "integer",
                    "format": "int64",
                    "description": "Total size in bytes across all chunks",
                    "example": 3145728
                  },
                  "duration": {
                    "type": "number",
                    "format": "double",
                    "description": "Actual recording duration in seconds",
                    "example": 1847.5
                  },
                  "checksum": {
                    "type": "string",
                    "description": "Optional integrity checksum (e.g., SHA-256)",
                    "example": "sha256:a1b2c3d4e5f6..."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recording completed and processing started",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "recording_id",
                    "status",
                    "completed_at"
                  ],
                  "properties": {
                    "recording_id": {
                      "type": "string",
                      "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing"
                      ],
                      "example": "processing"
                    },
                    "playback_url": {
                      "type": "string",
                      "description": "URL for playback (once ready)",
                      "example": "https://sageox.ai/recordings/rec_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "completed_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-01-30T14:45:30Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing chunk_count, etc.)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Recording in invalid state for completion",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/force-complete": {
      "post": {
        "operationId": "forceCompleteRecordingRepo",
        "summary": "Force-complete stuck recording (repo-scoped)",
        "description": "Escape hatch for recordings stuck in pending/uploading state when the normal\ncomplete flow fails (network issues, API restart).\n\n**What this does:**\n1. Validates recording is in stuck state (pending or uploading)\n2. Updates status to processing\n3. Sends force_complete signal to session workflow\n4. Starts processing workflow directly as fallback\n\nUse this sparingly - only when normal completion fails.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recording force-completed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings~1%7Brec_id%7D/get/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "400": {
            "description": "Invalid recording ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Recording not in stuck state (pending/uploading)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/transcript": {
      "get": {
        "operationId": "getTranscriptRepo",
        "summary": "Get transcript (repo-scoped)",
        "description": "Retrieve VTT (WebVTT) formatted transcript from the git ledger.\nReturns the raw VTT content with proper Content-Type header.\n\n**VTT format example:**\n```\nWEBVTT\n\n00:00:00.000 --> 00:00:05.123\nSpeaker A: This is the opening statement.\n\n00:00:05.123 --> 00:00:12.456\nSpeaker B: And this is the response.\n```\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Transcript retrieved as VTT text",
            "content": {
              "text/vtt": {
                "schema": {
                  "type": "string",
                  "format": "binary",
                  "description": "WebVTT format transcript"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording or transcript not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/decisions": {
      "get": {
        "operationId": "getDecisionsRepo",
        "summary": "Get extracted decisions (repo-scoped)",
        "description": "Retrieve decisions extracted from the recording by the AI analysis workflow.\nIncludes decision makers, behavioral patterns, and agreement status.\n\n**Decisions contain:**\n- Category, significance, status, title, description\n- Per-person agreement tracking\n- Supporting transcript evidence\n- Decision maker influence analysis\n- Behavioral pattern detection\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Decisions retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "recording_id",
                    "decisions"
                  ],
                  "properties": {
                    "recording_id": {
                      "type": "string",
                      "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "extracted_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "When decisions were extracted"
                    },
                    "participants_detected": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Identified participants",
                      "example": [
                        "Alice Chen",
                        "Bob Wilson",
                        "Charlie Davis"
                      ]
                    },
                    "decision_makers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "name"
                        ],
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Participant name",
                            "example": "Alice Chen"
                          },
                          "influence_score": {
                            "type": "number",
                            "format": "double",
                            "description": "Influence score from 0-1",
                            "example": 0.85
                          },
                          "influence_markers": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Behavioral indicators of influence",
                            "example": [
                              "frequently-speaks",
                              "drives-conclusions",
                              "steers-discussion"
                            ]
                          }
                        }
                      },
                      "description": "Decision influencers and their analysis"
                    },
                    "decisions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "category",
                          "significance",
                          "status",
                          "title",
                          "description",
                          "decision"
                        ],
                        "properties": {
                          "category": {
                            "type": "string",
                            "description": "Decision category",
                            "example": "technical-architecture"
                          },
                          "significance": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 5,
                            "description": "Significance level (1=Critical, 5=Trivial)",
                            "example": 2
                          },
                          "status": {
                            "type": "string",
                            "description": "Agreement status",
                            "example": "agreed"
                          },
                          "title": {
                            "type": "string",
                            "maxLength": 255,
                            "description": "Short decision description (3-8 words)",
                            "example": "Adopt microservices architecture"
                          },
                          "description": {
                            "type": "string",
                            "description": "Full context about the decision",
                            "example": "Team agreed to migrate from monolith to microservices..."
                          },
                          "decision": {
                            "type": "string",
                            "description": "The actual decision or \"No decision reached\"",
                            "example": "Use Kubernetes for orchestration"
                          },
                          "agreements": {
                            "type": "object",
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "Per-person agreement status",
                            "example": {
                              "Alice": "agreed",
                              "Bob": "needs-clarification"
                            }
                          },
                          "notes": {
                            "type": "string",
                            "description": "Supporting evidence from transcript"
                          }
                        }
                      },
                      "description": "Extracted decisions"
                    },
                    "behavioral_patterns": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "type",
                          "description"
                        ],
                        "properties": {
                          "type": {
                            "type": "string",
                            "description": "Pattern type",
                            "example": "hedged-language"
                          },
                          "description": {
                            "type": "string",
                            "description": "What was observed",
                            "example": "Used phrases like \"maybe\" and \"sort of\" when stating opinions"
                          },
                          "participants": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Participants involved",
                            "example": [
                              "Bob",
                              "Charlie"
                            ]
                          },
                          "evidence": {
                            "type": "string",
                            "description": "Supporting transcript excerpt"
                          }
                        }
                      },
                      "description": "Detected patterns in discussion"
                    },
                    "provider": {
                      "type": "string",
                      "nullable": true,
                      "description": "LLM provider used for extraction",
                      "example": "openai"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/recordings/{rec_id}/download": {
      "get": {
        "operationId": "getDownloadURLRepo",
        "summary": "Get download URL (repo-scoped)",
        "description": "Get a presigned URL for downloading the final processed audio file.\nOnly available for recordings in \"ready\" state.\n\n**URL expires:** 1 hour after generation\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Download URL generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "download_url",
                    "filename",
                    "content_type",
                    "expires_at"
                  ],
                  "properties": {
                    "download_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Presigned S3 URL (expires in 1 hour)",
                      "example": "https://s3.amazonaws.com/bucket/repos/repo_01934f5a/recordings/rec_01934f5a/final.mp3?..."
                    },
                    "filename": {
                      "type": "string",
                      "description": "Suggested filename for download",
                      "example": "Architecture Review - Jan 2025.mp3"
                    },
                    "content_type": {
                      "type": "string",
                      "example": "audio/mpeg"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-01-30T15:45:30Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found or not ready for download",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings": {
      "post": {
        "operationId": "startRecordingTeam",
        "summary": "Start recording (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            },
            "description": "Team identifier"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "mime_type"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 200,
                    "example": "Team Standup - Jan 30"
                  },
                  "mime_type": {
                    "type": "string",
                    "example": "audio/webm"
                  },
                  "duration_hint": {
                    "type": "integer",
                    "format": "int64",
                    "example": 900
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Recording initialized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "recording_id",
                    "upload",
                    "created_at"
                  ],
                  "properties": {
                    "recording_id": {
                      "type": "string",
                      "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "upload": {
                      "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings/post/responses/201/content/application~1json/schema/properties/upload"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listRecordingsTeam",
        "summary": "List recordings (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "uploading",
                "processing",
                "ready",
                "failed",
                "deleted"
              ]
            }
          },
          {
            "name": "mime_type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "timestamp_start",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "timestamp_end",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of recordings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "recordings": {
                      "type": "array",
                      "items": {
                        "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings~1%7Brec_id%7D/get/responses/200/content/application~1json/schema"
                      }
                    },
                    "pagination": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}": {
      "get": {
        "operationId": "getRecordingTeam",
        "summary": "Get recording details (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recording details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings~1%7Brec_id%7D/get/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateRecordingTeam",
        "summary": "Update recording metadata (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recording updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings~1%7Brec_id%7D/get/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteRecordingTeam",
        "summary": "Delete recording (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Recording deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/chunks": {
      "post": {
        "operationId": "getChunkURLTeam",
        "summary": "Get presigned URL for chunk upload (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "chunk_index"
                ],
                "properties": {
                  "chunk_index": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "chunk_size": {
                    "type": "integer",
                    "format": "int64"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned URL generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "upload": {
                      "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings/post/responses/201/content/application~1json/schema/properties/upload"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Recording not in uploading state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/chunks/prefetch": {
      "post": {
        "operationId": "prefetchChunkURLsTeam",
        "summary": "Batch prefetch chunk URLs (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "count"
                ],
                "properties": {
                  "count": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 40,
                    "default": 20
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "URLs prefetched",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "chunks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings/post/responses/201/content/application~1json/schema/properties/upload"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/chunks/heartbeat": {
      "post": {
        "operationId": "chunkHeartbeatTeam",
        "summary": "Send heartbeat (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "chunk_index"
                ],
                "properties": {
                  "chunk_index": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Heartbeat recorded"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/pause": {
      "post": {
        "operationId": "pauseRecordingTeam",
        "summary": "Pause recording (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Pause signal recorded"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/resume": {
      "post": {
        "operationId": "resumeRecordingTeam",
        "summary": "Resume recording (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Resume signal recorded"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/complete": {
      "post": {
        "operationId": "completeRecordingTeam",
        "summary": "Complete recording upload (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "chunk_count"
                ],
                "properties": {
                  "chunk_count": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "total_size": {
                    "type": "integer",
                    "format": "int64"
                  },
                  "duration": {
                    "type": "number",
                    "format": "double"
                  },
                  "checksum": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recording completed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "recording_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "playback_url": {
                      "type": "string"
                    },
                    "completed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Recording in invalid state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/force-complete": {
      "post": {
        "operationId": "forceCompleteRecordingTeam",
        "summary": "Force-complete stuck recording (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recording force-completed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings~1%7Brec_id%7D/get/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Recording not in stuck state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/transcript": {
      "get": {
        "operationId": "getTranscriptTeam",
        "summary": "Get transcript (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Transcript retrieved",
            "content": {
              "text/vtt": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/decisions": {
      "get": {
        "operationId": "getDecisionsTeam",
        "summary": "Get extracted decisions (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Decisions retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1recordings~1%7Brec_id%7D~1decisions/get/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/recordings/{rec_id}/download": {
      "get": {
        "operationId": "getDownloadURLTeam",
        "summary": "Get download URL (team-scoped)",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Download URL generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "download_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "filename": {
                      "type": "string"
                    },
                    "content_type": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/recordings/{rec_id}/reactions": {
      "get": {
        "operationId": "listRecordingReactions",
        "summary": "List recording reactions",
        "description": "Every reaction (live-meeting emoji) recorded against this recording, in\nchronological (oldest-first) order. Unbounded by design — recording\nreactions are retained indefinitely as transcript-timeline metadata.\nThe UI is responsible for bucketing or windowing on render.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Reactions retrieved (possibly empty list)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "reactions"
                  ],
                  "properties": {
                    "reactions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "recordingId",
                          "userId",
                          "emoji",
                          "createdAt",
                          "metadata"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Reaction UUID",
                            "example": "01935a7b-1234-7abc-9def-0123456789ab"
                          },
                          "recordingId": {
                            "type": "string",
                            "description": "Recording the reaction belongs to (rec_<uuidv7>)",
                            "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
                          },
                          "userId": {
                            "type": "string",
                            "description": "User who reacted (usr_<id>)",
                            "example": "usr_abc123xyz"
                          },
                          "emoji": {
                            "type": "string",
                            "description": "Reaction emoji (UTF-8, ≤16 bytes)",
                            "example": "🎉"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2026-05-01T12:00:00Z"
                          },
                          "metadata": {
                            "type": "object",
                            "description": "Client-side context (skin tone, origin point, etc.)"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid rec_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — caller is not a member of the recording's team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found, or recording is not team-scoped",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/recordings/{rec_id}/comments": {
      "get": {
        "operationId": "listRecordingComments",
        "summary": "List recording (live-meeting) chat comments",
        "description": "All chat-message comments tied to the meeting (recording) entity, in\nchronological order. Wraps the generic comments table with the meeting-\nscoped filter (entity_type='meeting', scope_type='meeting',\nscope_id='global') used by the live cast surface.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Comments retrieved (possibly empty list)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "comments"
                  ],
                  "properties": {
                    "comments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "entityId",
                          "authorId",
                          "body",
                          "createdAt",
                          "updatedAt"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Comment ID (cmt_<uuidv7>)",
                            "example": "cmt_01935a7b-1234-7abc-9def-0123456789ab"
                          },
                          "entityId": {
                            "type": "string",
                            "description": "Recording ID (rec_<uuidv7>)",
                            "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
                          },
                          "authorId": {
                            "type": "string",
                            "example": "usr_abc123xyz"
                          },
                          "body": {
                            "type": "string",
                            "example": "agreed, ship it"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid rec_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/recordings/{rec_id}/decisions": {
      "get": {
        "operationId": "listRecordingDecisionMarks",
        "summary": "List participant-marked decisions",
        "description": "All participant-marked decisions for this recording (chronological).\nDistinct from /api/v1/teams/{team_id}/recordings/{rec_id}/decisions,\nwhich serves AI-extracted decisions from recordings.metadata. AI rows\nwill migrate to this table in a future ADR.\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Decisions retrieved (possibly empty list)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "decisions"
                  ],
                  "properties": {
                    "decisions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "recordingId",
                          "text",
                          "raisedByUserId",
                          "raisedAt",
                          "source"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Decision ID (dec_<uuidv7>)",
                            "example": "dec_01935a7b-1234-7abc-9def-0123456789ab"
                          },
                          "recordingId": {
                            "type": "string",
                            "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
                          },
                          "text": {
                            "type": "string",
                            "example": "ship cast v1 before next demo"
                          },
                          "raisedByUserId": {
                            "type": "string",
                            "example": "usr_abc123xyz"
                          },
                          "raisedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "source": {
                            "type": "string",
                            "description": "Origin of the decision row (today only 'human' is produced)",
                            "enum": [
                              "human",
                              "ai"
                            ]
                          },
                          "sourceMessageId": {
                            "type": "string",
                            "description": "Originating chat-message ID when marked from a chat bubble",
                            "example": "cmt_01935a7b-1234-7abc-9def-0123456789ab"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid rec_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/recordings/{rec_id}/questions": {
      "get": {
        "operationId": "listRecordingQuestions",
        "summary": "List participant-marked questions",
        "description": "All participant-marked questions for this recording (chronological).",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Questions retrieved (possibly empty list)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "questions"
                  ],
                  "properties": {
                    "questions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "recordingId",
                          "text",
                          "raisedByUserId",
                          "raisedAt",
                          "source"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Question ID (qst_<uuidv7>)"
                          },
                          "recordingId": {
                            "type": "string"
                          },
                          "text": {
                            "type": "string"
                          },
                          "raisedByUserId": {
                            "type": "string"
                          },
                          "raisedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "human",
                              "ai"
                            ]
                          },
                          "sourceMessageId": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid rec_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/recordings/{rec_id}/action-items": {
      "get": {
        "operationId": "listRecordingActionItems",
        "summary": "List participant-marked action items",
        "description": "All participant-marked action items for this recording (chronological).\nEach item carries a required assignee (assigneeUserId).\n",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Action items retrieved (possibly empty list)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "actionItems"
                  ],
                  "properties": {
                    "actionItems": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "recordingId",
                          "task",
                          "assigneeUserId",
                          "raisedByUserId",
                          "raisedAt",
                          "source"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Action item ID (ait_<uuidv7>)"
                          },
                          "recordingId": {
                            "type": "string"
                          },
                          "task": {
                            "type": "string"
                          },
                          "assigneeUserId": {
                            "type": "string",
                            "description": "User responsible for the action item (required at insert)"
                          },
                          "raisedByUserId": {
                            "type": "string"
                          },
                          "raisedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "human",
                              "ai"
                            ]
                          },
                          "sourceMessageId": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid rec_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/recordings/{rec_id}/concerns": {
      "get": {
        "operationId": "listRecordingConcerns",
        "summary": "List participant-marked concerns",
        "description": "All participant-marked concerns for this recording (chronological).",
        "tags": [
          "Recordings"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "rec_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Concerns retrieved (possibly empty list)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "concerns"
                  ],
                  "properties": {
                    "concerns": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "recordingId",
                          "text",
                          "raisedByUserId",
                          "raisedAt",
                          "source"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Concern ID (con_<uuidv7>)"
                          },
                          "recordingId": {
                            "type": "string"
                          },
                          "text": {
                            "type": "string"
                          },
                          "raisedByUserId": {
                            "type": "string"
                          },
                          "raisedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "human",
                              "ai"
                            ]
                          },
                          "sourceMessageId": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid rec_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Recording not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/sessions/top": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Get top sessions by token usage",
        "description": "Returns the top 5 sessions ranked by total token consumption\nin the last 7 days. Sessions are grouped by ox_sid and include\nagent/model metadata.\n",
        "operationId": "getTopSessions",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Top sessions retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sessions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ox_sid": {
                            "type": "string",
                            "description": "Session identifier",
                            "example": "oxsid_abc123xyz"
                          },
                          "total_tokens": {
                            "type": "integer",
                            "format": "int64",
                            "description": "Total tokens consumed",
                            "example": 12450
                          },
                          "path_count": {
                            "type": "integer",
                            "format": "int64",
                            "description": "Number of path accesses",
                            "example": 23
                          },
                          "duration_seconds": {
                            "type": "integer",
                            "description": "Session duration in seconds",
                            "example": 272
                          },
                          "agent": {
                            "type": "string",
                            "nullable": true,
                            "description": "Coding agent platform",
                            "example": "claude-code"
                          },
                          "model": {
                            "type": "string",
                            "nullable": true,
                            "description": "AI model used",
                            "example": "claude-opus-4-5"
                          },
                          "first_access": {
                            "type": "string",
                            "format": "date-time",
                            "description": "First access timestamp"
                          },
                          "last_access": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Last access timestamp"
                          }
                        },
                        "required": [
                          "ox_sid",
                          "total_tokens",
                          "path_count",
                          "duration_seconds",
                          "first_access",
                          "last_access"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Admin access required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1admin~1sessions~1top/get/responses/401/content/application~1json/schema"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/sessions/{sid}": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Get session details",
        "description": "Returns detailed analytics for a specific session including\ntimeline of accesses, path exploration tree, and metadata.\n",
        "operationId": "getSessionDetail",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Session ID (ox_sid)",
            "example": "oxsid_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Session details retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ox_sid": {
                      "type": "string"
                    },
                    "user_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "total_tokens": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "path_count": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "unique_paths": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "duration_seconds": {
                      "type": "integer"
                    },
                    "agent": {
                      "type": "string",
                      "nullable": true
                    },
                    "model": {
                      "type": "string",
                      "nullable": true
                    },
                    "first_access": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "last_access": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "timeline": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string",
                            "example": "infra/aws/lambda"
                          },
                          "tokens": {
                            "type": "integer",
                            "example": 450
                          },
                          "timestamp": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "metadata": {
                            "type": "object",
                            "additionalProperties": true,
                            "nullable": true
                          }
                        }
                      }
                    },
                    "path_tree": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "segment": {
                            "type": "string"
                          },
                          "tokens": {
                            "type": "integer"
                          },
                          "access_count": {
                            "type": "integer"
                          },
                          "children": {
                            "type": "array",
                            "items": {
                              "$ref": "#/paths/~1api~1v1~1admin~1sessions~1%7Bsid%7D/get/responses/200/content/application~1json/schema/properties/path_tree/items"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Session not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1admin~1sessions~1top/get/responses/401/content/application~1json/schema"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/paths/top": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Get top paths by TF-IDF score",
        "description": "Returns the top 10 guidance paths weighted by TF-IDF score.\nThis highlights paths that are unexpectedly popular relative\nto their baseline expectation (deeper paths get a bonus).\n",
        "operationId": "getTopPaths",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Top paths retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "paths": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string",
                            "example": "infra/aws/lambda/edge-functions"
                          },
                          "access_count": {
                            "type": "integer",
                            "format": "int64",
                            "example": 42
                          },
                          "unique_sessions": {
                            "type": "integer",
                            "format": "int64",
                            "example": 15
                          },
                          "total_tokens": {
                            "type": "integer",
                            "format": "int64",
                            "example": 8500
                          },
                          "tfidf_score": {
                            "type": "number",
                            "format": "float",
                            "description": "TF-IDF weighted score",
                            "example": 12.45
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/agents/top": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Get top agents by usage",
        "description": "Returns top coding agents (claude-code, cursor, windsurf, etc.)\nranked by total token usage in the last 7 days.\n",
        "operationId": "getTopAgents",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Top agents retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "agent": {
                            "type": "string",
                            "example": "claude-code"
                          },
                          "session_count": {
                            "type": "integer",
                            "format": "int64",
                            "example": 150
                          },
                          "request_count": {
                            "type": "integer",
                            "format": "int64",
                            "example": 3200
                          },
                          "total_tokens": {
                            "type": "integer",
                            "format": "int64",
                            "example": 450000
                          },
                          "avg_tokens_per_request": {
                            "type": "integer",
                            "example": 140
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/models/top": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Get top models by usage",
        "description": "Returns top AI models (claude-opus-4-5, gpt-4o, etc.)\nranked by total token usage in the last 7 days.\n",
        "operationId": "getTopModels",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Top models retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "models": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "model": {
                            "type": "string",
                            "example": "claude-opus-4-5"
                          },
                          "session_count": {
                            "type": "integer",
                            "format": "int64",
                            "example": 120
                          },
                          "request_count": {
                            "type": "integer",
                            "format": "int64",
                            "example": 2800
                          },
                          "total_tokens": {
                            "type": "integer",
                            "format": "int64",
                            "example": 380000
                          },
                          "avg_tokens_per_request": {
                            "type": "integer",
                            "example": 135
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/versions/top": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Get top ox-cli versions by usage",
        "description": "Returns top ox-cli versions ranked by total token usage\nin the last 7 days. Version is parsed from User-Agent header.\n",
        "operationId": "getTopCliVersions",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Top CLI versions retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "versions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "client_version": {
                            "type": "string",
                            "description": "ox-cli version from User-Agent header",
                            "example": "1.2.3"
                          },
                          "session_count": {
                            "type": "integer",
                            "format": "int64",
                            "example": 85
                          },
                          "request_count": {
                            "type": "integer",
                            "format": "int64",
                            "example": 1900
                          },
                          "total_tokens": {
                            "type": "integer",
                            "format": "int64",
                            "example": 280000
                          },
                          "avg_tokens_per_request": {
                            "type": "integer",
                            "example": 147
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/firmware/latest": {
      "get": {
        "operationId": "getFirmwareManifest",
        "summary": "Check for firmware updates",
        "description": "Device-facing endpoint that returns the latest available firmware manifest\nfor the specified device type. The device polls this endpoint periodically\nand compares the returned version against its current firmware.\n\nThis endpoint is **unauthenticated** (devices have no JWT) but rate-limited\nby X-Device-ID header. Returns 204 No Content when no update is available.\n\nThe response `url` field contains a pre-signed S3 URL (15-minute TTL) for\ndirect firmware binary download. The device fetches this URL directly with\nno auth headers.\n",
        "tags": [
          "Firmware OTA"
        ],
        "security": [],
        "parameters": [
          {
            "name": "device",
            "in": "query",
            "required": true,
            "description": "Hardware type identifier (e.g., `scribe`, `clip`).",
            "schema": {
              "type": "string",
              "example": "scribe"
            }
          },
          {
            "name": "version",
            "in": "query",
            "required": true,
            "description": "Currently running firmware version (semver format).",
            "schema": {
              "type": "string",
              "example": "1.0.0"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "Release channel to check. Defaults to `stable`.",
            "schema": {
              "type": "string",
              "default": "stable",
              "enum": [
                "stable",
                "early-access",
                "beta",
                "nightly"
              ]
            }
          },
          {
            "name": "X-Device-ID",
            "in": "header",
            "required": false,
            "description": "Hardware-derived stable identifier. For scribe, this is the 12-character lowercase hex of the ESP32 base MAC address.",
            "schema": {
              "type": "string",
              "example": "aabbccddeeff"
            }
          },
          {
            "name": "X-Device-Type",
            "in": "header",
            "description": "Hardware type, same as the `device` query parameter. Informational.",
            "schema": {
              "type": "string",
              "example": "scribe"
            }
          },
          {
            "name": "User-Agent",
            "in": "header",
            "description": "Device firmware user agent string.",
            "schema": {
              "type": "string",
              "example": "sageox-scribe/1.0.0 (esp32-s3; xtensa-lx7)"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A newer firmware version is available.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "version",
                    "url"
                  ],
                  "description": "Firmware manifest returned to devices. Field sizes are constrained by\nthe ESP32 firmware parser buffer sizes.\n",
                  "properties": {
                    "version": {
                      "type": "string",
                      "description": "Semver version string. Must be newer than the device's current version.",
                      "maxLength": 31,
                      "example": "1.2.0"
                    },
                    "url": {
                      "type": "string",
                      "description": "Pre-signed S3 URL for direct firmware binary download (15-minute TTL, no auth required).",
                      "maxLength": 511
                    },
                    "sha256": {
                      "type": "string",
                      "description": "SHA-256 hash of the firmware binary, lowercase hex.",
                      "pattern": "^[0-9a-f]{64}$",
                      "example": "a3f1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1"
                    },
                    "signature": {
                      "type": "string",
                      "description": "Base64-encoded RSA-2048 signature over the SHA-256 digest. Required for production builds.",
                      "maxLength": 511
                    },
                    "size": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Firmware binary size in bytes. Used for progress bar and hash verification."
                    },
                    "changelog": {
                      "type": "string",
                      "description": "Human-readable changelog. Devices with small screens truncate on their end.",
                      "maxLength": 2048
                    },
                    "release_date": {
                      "type": "string",
                      "format": "date",
                      "description": "ISO-8601 release date."
                    },
                    "min_version": {
                      "type": "string",
                      "description": "Security floor. Devices below this version get a forced update (no skip option).",
                      "maxLength": 31
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "No update available. Device is up to date or not targeted."
          },
          "400": {
            "description": "Missing required query parameters."
          },
          "429": {
            "description": "Rate limit exceeded. Back off and retry."
          },
          "500": {
            "description": "Server error."
          }
        }
      }
    },
    "/api/v1/internal/hq/firmware": {
      "post": {
        "operationId": "uploadFirmwareRelease",
        "summary": "Upload new firmware release",
        "description": "Create a firmware release record and get a pre-signed S3 upload URL for\nthe binary. The release starts in `staged` status and must be explicitly\nactivated via the activate endpoint.\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "device_type",
                  "version",
                  "sha256",
                  "size_bytes"
                ],
                "properties": {
                  "device_type": {
                    "type": "string",
                    "example": "scribe"
                  },
                  "version": {
                    "type": "string",
                    "maxLength": 31,
                    "example": "1.2.0"
                  },
                  "sha256": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$"
                  },
                  "signature": {
                    "type": "string",
                    "description": "Base64 RSA-2048 signature. Required for production releases."
                  },
                  "size_bytes": {
                    "type": "integer",
                    "format": "int64",
                    "maximum": 4194304
                  },
                  "changelog": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "release_date": {
                    "type": "string",
                    "format": "date"
                  },
                  "min_version": {
                    "type": "string",
                    "maxLength": 31
                  },
                  "channel": {
                    "type": "string",
                    "default": "stable",
                    "enum": [
                      "stable",
                      "early-access",
                      "beta",
                      "nightly"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Release created. Upload the binary to the returned URL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "release": {
                      "$ref": "#/paths/~1api~1v1~1internal~1hq~1firmware~1%7Bfirmware_id%7D/patch/responses/200/content/application~1json/schema"
                    },
                    "upload_url": {
                      "type": "string",
                      "description": "Pre-signed S3 PUT URL for uploading the firmware binary. Expires in 15 minutes."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing fields, bad SHA-256 format, etc.)."
          },
          "409": {
            "description": "Version already exists for this device type and channel."
          }
        }
      },
      "get": {
        "operationId": "listFirmwareReleases",
        "summary": "List firmware releases",
        "description": "List all firmware releases for a device type, newest first.\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_type",
            "in": "query",
            "description": "Filter by device type. Defaults to `scribe`.",
            "schema": {
              "type": "string",
              "default": "scribe"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of firmware releases.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "pagination"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/paths/~1api~1v1~1internal~1hq~1firmware~1%7Bfirmware_id%7D/patch/responses/200/content/application~1json/schema"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "required": [
                        "total",
                        "limit",
                        "offset",
                        "has_more"
                      ],
                      "properties": {
                        "total": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        },
                        "has_more": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/internal/hq/firmware/{firmware_id}": {
      "patch": {
        "operationId": "updateFirmwareRelease",
        "summary": "Update min_version security floor and/or rollout percentage",
        "description": "Update mutable fields on a firmware release. At least one of `min_version`\nor `rollout_percent` must be supplied.\n\n- `min_version`: devices running below this floor get a forced update (no\n  skip option). Send an empty string to clear the floor.\n- `rollout_percent`: percentage of the cohort (0-100) eligible to receive\n  this release. Device IDs are hashed into a 0-99 bucket; a device is\n  served only if its bucket is below the configured percent. Use this to\n  gradually expand a release from canary to full rollout.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "firmware_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "At least one of min_version or rollout_percent is required.",
                "properties": {
                  "min_version": {
                    "type": "string",
                    "nullable": true,
                    "description": "Semver minimum version. Devices below this get forced update. Empty string clears.",
                    "maxLength": 31
                  },
                  "rollout_percent": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Cohort fraction served this release (0-100). 100 means everyone in cohort."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated release.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "fw_019d68dd-eda3-70d6-84bf-000000000001"
                    },
                    "device_type": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "s3_key": {
                      "type": "string"
                    },
                    "sha256": {
                      "type": "string"
                    },
                    "signature": {
                      "type": "string"
                    },
                    "size_bytes": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "changelog": {
                      "type": "string"
                    },
                    "release_date": {
                      "type": "string",
                      "format": "date"
                    },
                    "min_version": {
                      "type": "string"
                    },
                    "rollout_percent": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100,
                      "description": "Cohort fraction (0-100) currently served this release."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "staged",
                        "active"
                      ]
                    },
                    "channel": {
                      "type": "string",
                      "enum": [
                        "stable",
                        "early-access",
                        "beta",
                        "nightly"
                      ]
                    },
                    "uploaded_by": {
                      "type": "string"
                    },
                    "activated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "paused_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "When non-null, manifest resolver returns 204 for this release fleet-wide."
                    },
                    "paused_by": {
                      "type": "string",
                      "nullable": true,
                      "description": "User ID of the operator who paused the release."
                    },
                    "pause_reason": {
                      "type": "string",
                      "nullable": true,
                      "description": "Human-readable justification for the pause."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Neither min_version nor rollout_percent supplied, or rollout_percent out of range."
          },
          "404": {
            "description": "Release not found."
          }
        }
      }
    },
    "/api/v1/internal/hq/firmware/{firmware_id}/activate": {
      "post": {
        "operationId": "activateFirmwareRelease",
        "summary": "Activate a staged firmware release",
        "description": "Atomically returns the current active release to `staged` and activates\nthe specified one. Only releases in `staged` status can be activated.\n\n**Rollback:** To rollback, activate any previous staged release.\nThe old active release returns to `staged`, so it can be re-activated later.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "firmware_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "fw_019d68dd-eda3-70d6-84bf-000000000001"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Release activated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1internal~1hq~1firmware~1%7Bfirmware_id%7D/patch/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "400": {
            "description": "Release is not in staged status."
          },
          "404": {
            "description": "Release not found."
          }
        }
      }
    },
    "/api/v1/internal/hq/firmware/{firmware_id}/pause": {
      "post": {
        "operationId": "pauseFirmwareRelease",
        "summary": "Pause a firmware release (fleet-wide kill-switch)",
        "description": "Sets `paused_at` on the release. While paused, the manifest resolver\nreturns 204 No Content for this release even for devices in its rollout\ncohort. Independent of `rollout_percent` — pause is the kill-switch primitive.\n\nThe audit trail records `paused_by` and `pause_reason`.\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "firmware_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "Human-readable justification (e.g. 'elevated crash rate', 'customer complaint').",
                    "maxLength": 512
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Release paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1internal~1hq~1firmware~1%7Bfirmware_id%7D/patch/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "400": {
            "description": "Missing reason or release already paused."
          },
          "404": {
            "description": "Release not found."
          }
        }
      }
    },
    "/api/v1/internal/hq/firmware/{firmware_id}/resume": {
      "post": {
        "operationId": "resumeFirmwareRelease",
        "summary": "Resume a paused firmware release",
        "description": "Clears `paused_at`, `paused_by`, and `pause_reason` on the release. The\nmanifest resolver will once again serve this release to eligible devices.\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "firmware_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Release resumed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1internal~1hq~1firmware~1%7Bfirmware_id%7D/patch/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "400": {
            "description": "Release is not paused."
          },
          "404": {
            "description": "Release not found."
          }
        }
      }
    },
    "/api/v1/internal/hq/firmware/catalog": {
      "get": {
        "operationId": "listFirmwareCatalog",
        "summary": "List firmware catalog with fleet rollout signals",
        "description": "Catalog view of firmware releases enriched with fleet-derived signals:\ndevice counts, adoption series, crash counts, and pause status. Used by\nthe HQ web console to render the fleet dashboard. Distinct from the basic\nlist endpoint because it joins against `physical_devices` and\n`device_update_events`.\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_type",
            "in": "query",
            "description": "Filter by hardware type (e.g. scribe). Defaults to scribe.",
            "schema": {
              "type": "string",
              "default": "scribe"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "description": "Filter by release channel.",
            "schema": {
              "type": "string",
              "enum": [
                "stable",
                "early-access",
                "beta",
                "nightly"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by release status.",
            "schema": {
              "type": "string",
              "enum": [
                "staged",
                "active"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Catalog entries, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "id",
                      "version",
                      "device_type",
                      "channel",
                      "status"
                    ],
                    "description": "Catalog entry enriched with fleet-derived adoption and crash signals.\nComputed by joining `firmware_releases` against `physical_devices` and\n`device_update_events`.\n",
                    "properties": {
                      "id": {
                        "type": "string",
                        "example": "fw_019d68dd-eda3-70d6-84bf-000000000001"
                      },
                      "version": {
                        "type": "string"
                      },
                      "device_type": {
                        "type": "string"
                      },
                      "channel": {
                        "type": "string",
                        "enum": [
                          "stable",
                          "early-access",
                          "beta",
                          "nightly"
                        ]
                      },
                      "status": {
                        "type": "string",
                        "enum": [
                          "staged",
                          "active"
                        ]
                      },
                      "uploaded_by": {
                        "type": "string"
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "activated_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                      },
                      "paused_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                      },
                      "paused_by": {
                        "type": "string",
                        "nullable": true
                      },
                      "pause_reason": {
                        "type": "string",
                        "nullable": true
                      },
                      "sha256": {
                        "type": "string",
                        "pattern": "^[0-9a-f]{64}$"
                      },
                      "size_bytes": {
                        "type": "integer",
                        "format": "int64"
                      },
                      "current_device_count": {
                        "type": "integer",
                        "description": "Devices currently reporting this version via firmware check-in."
                      },
                      "ever_updated_count": {
                        "type": "integer",
                        "description": "Distinct devices that have reached `verified` for this release."
                      },
                      "crash_count_last_7d": {
                        "type": "integer",
                        "description": "Crash reports in the last 7 days from devices on this release."
                      },
                      "adoption_series": {
                        "type": "array",
                        "description": "Daily adoption counts (newest last) for sparkline rendering.",
                        "items": {
                          "type": "object",
                          "required": [
                            "date",
                            "count"
                          ],
                          "properties": {
                            "date": {
                              "type": "string",
                              "format": "date"
                            },
                            "count": {
                              "type": "integer"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/internal/hq/firmware/{firmware_id}/dryrun": {
      "post": {
        "operationId": "dryrunFirmwareRollout",
        "summary": "Preview rollout cohort without targeting devices",
        "description": "Evaluate a candidate cohort selector and report how many devices would\nmatch, how many are eligible (after policy/version/hardware filters), and\nwhich devices are excluded and why. Read-only — no devices are targeted.\n\nUsed by the HQ console to give operators confidence before they create a\nreal rollout.\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "firmware_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Optional cohort selector. Omit the body to preview the release against\nits default cohort.\n",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Optional cohort selector for the dryrun preview. The body itself is\noptional — POSTing an empty body returns the default preview for the\nrelease.\n",
                "properties": {
                  "target_cohort": {
                    "type": "object",
                    "description": "Cohort selector to evaluate. Same shape as `firmware_rollouts.target_cohort`.",
                    "properties": {
                      "channel": {
                        "type": "string",
                        "enum": [
                          "stable",
                          "early-access",
                          "beta",
                          "nightly"
                        ]
                      },
                      "from_version_glob": {
                        "type": "string",
                        "description": "Semver glob (e.g. '1.2.*') matching device's current firmware_version."
                      },
                      "group_ids": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dryrun result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "firmware_id",
                    "matched_count",
                    "eligible_count",
                    "excluded_disabled_devices",
                    "excluded_pinned_elsewhere",
                    "below_min_version",
                    "already_on_target_version"
                  ],
                  "properties": {
                    "firmware_id": {
                      "type": "string",
                      "description": "fw_-prefixed release ID this dryrun was evaluated against.",
                      "example": "fw_019d68dd-eda3-70d6-84bf-000000000001"
                    },
                    "matched_count": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Devices matching the cohort selector before policy filters."
                    },
                    "eligible_count": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Devices that would actually be served the release."
                    },
                    "excluded_disabled_devices": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Count of devices excluded because their `ota_policy` is `disabled`."
                    },
                    "excluded_pinned_elsewhere": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Count of devices with `ota_policy=pinned` pinned to a different release."
                    },
                    "below_min_version": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Count of devices below this release's `min_version` floor."
                    },
                    "already_on_target_version": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Count of devices already running the release's target version."
                    },
                    "notes": {
                      "type": "string",
                      "description": "Free-form operator-facing notes. Used to flag approximations or\ndegraded preview modes when precise cohort matching is unavailable.\n"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid cohort selector."
          },
          "404": {
            "description": "Release not found."
          }
        }
      }
    },
    "/api/v1/internal/hq/devices/{device_id}/firmware-target": {
      "put": {
        "operationId": "pinDeviceFirmwareTarget",
        "summary": "Pin a device to a specific firmware release",
        "description": "Creates or replaces the firmware pin for a single device. While pinned,\nthe manifest resolver serves the targeted release regardless of the\ndevice's channel — provided the device's `ota_policy` is `pinned`.\n\nPins are the primary pilot-testing primitive: bring a single rig onto\nbeta firmware without affecting the rest of the fleet.\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "description": "Hardware device ID (12-character lowercase hex MAC for scribe).",
            "schema": {
              "type": "string",
              "example": "aabbccddeeff"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "firmware_id",
                  "reason"
                ],
                "properties": {
                  "firmware_id": {
                    "type": "string",
                    "description": "fw_-prefixed release ID to pin.",
                    "example": "fw_019d68dd-eda3-70d6-84bf-000000000001"
                  },
                  "reason": {
                    "type": "string",
                    "description": "Human-readable justification (e.g. 'pilot device for beta firmware').",
                    "maxLength": 512
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pin created or replaced.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "device_id",
                    "firmware_id",
                    "pinned_by",
                    "pinned_at"
                  ],
                  "description": "A pin overriding channel-based resolution for one device.",
                  "properties": {
                    "device_id": {
                      "type": "string",
                      "description": "Hardware device ID (e.g. 12-char lowercase hex MAC for scribe).",
                      "example": "aabbccddeeff"
                    },
                    "firmware_id": {
                      "type": "string",
                      "description": "fw_-prefixed release ID this device is pinned to.",
                      "example": "fw_019d68dd-eda3-70d6-84bf-000000000001"
                    },
                    "reason": {
                      "type": "string",
                      "nullable": true
                    },
                    "pinned_by": {
                      "type": "string",
                      "description": "User ID of the operator who created the pin."
                    },
                    "pinned_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing fields, unknown firmware_id)."
          },
          "404": {
            "description": "Device not found."
          }
        }
      },
      "delete": {
        "operationId": "unpinDeviceFirmwareTarget",
        "summary": "Remove a device firmware pin",
        "description": "Deletes the pin for a device. The device returns to channel-based\nresolution. Note this does not change `ota_policy`; if the device is\nstill in `pinned` policy with no pin, the resolver returns 204\n(intentional: prevents accidental re-targeting onto the channel).\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Pin removed (or never existed)."
          },
          "404": {
            "description": "Device not found."
          }
        }
      }
    },
    "/api/v1/internal/hq/devices/{device_id}/ota-policy": {
      "get": {
        "operationId": "getDeviceOTAPolicy",
        "summary": "Get the OTA policy for a device",
        "description": "Returns the device's OTA policy plus optional firmware pin (when policy is\n`pinned`). Precedence in the resolver: `disabled` > `pinned` > `auto`.\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Device OTA policy state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "policy"
                  ],
                  "properties": {
                    "policy": {
                      "$ref": "#/paths/~1api~1v1~1internal~1hq~1devices~1%7Bdevice_id%7D~1ota-policy/put/requestBody/content/application~1json/schema/properties/policy"
                    },
                    "reason": {
                      "type": "string",
                      "nullable": true,
                      "description": "Human-readable justification for non-`auto` policy."
                    },
                    "set_by": {
                      "type": "string",
                      "nullable": true,
                      "description": "User ID of the operator who last set the policy."
                    },
                    "set_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "firmware_target": {
                      "allOf": [
                        {
                          "$ref": "#/paths/~1api~1v1~1internal~1hq~1devices~1%7Bdevice_id%7D~1firmware-target/put/responses/200/content/application~1json/schema"
                        }
                      ],
                      "nullable": true,
                      "description": "Present when `policy` is `pinned` and a pin exists."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Device not found."
          }
        }
      },
      "put": {
        "operationId": "setDeviceOTAPolicy",
        "summary": "Set the OTA policy for a device",
        "description": "Set `ota_policy` to `auto`, `pinned`, or `disabled` for a single device.\nRecords `set_by` and `set_at` for the audit trail.\n\nSwitching to `pinned` does NOT create a pin — call PUT\n`/devices/{device_id}/firmware-target` separately. Until a pin exists,\na `pinned` device receives 204 from the manifest resolver.\n\nSwitching to `disabled` is the strongest signal: the resolver returns 204\nunconditionally. Used for engineering rigs and devices flashed manually.\n\n**Auth:** JWT + HQ admin only.\n",
        "tags": [
          "Firmware Admin"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "policy",
                  "reason"
                ],
                "properties": {
                  "policy": {
                    "type": "string",
                    "enum": [
                      "auto",
                      "pinned",
                      "disabled"
                    ],
                    "description": "Per-device OTA policy.\n- `auto`: normal channel/rollout resolution.\n- `pinned`: resolver consults `device_firmware_target` for the served release.\n- `disabled`: resolver returns 204 unconditionally (self-managed).\nResolver precedence: `disabled` > `pinned` > `auto`.\n"
                  },
                  "reason": {
                    "type": "string",
                    "description": "Human-readable justification (e.g. 'eng rig - manual flashing').",
                    "maxLength": 512
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Policy updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1internal~1hq~1devices~1%7Bdevice_id%7D~1ota-policy/get/responses/200/content/application~1json/schema"
                }
              }
            }
          },
          "400": {
            "description": "Invalid policy value or missing reason."
          },
          "404": {
            "description": "Device not found."
          }
        }
      }
    },
    "/api/v1/devices": {
      "get": {
        "operationId": "listDevices",
        "summary": "List devices paired to the current user",
        "description": "Returns every device the authenticated user has registered, ordered\nmost-recently-active first (by `last_seen_at DESC NULLS LAST`, then\n`paired_at DESC`). Used by the browser dashboard on /device when\ncalled without a user_code query param.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Device list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "devices"
                  ],
                  "properties": {
                    "devices": {
                      "type": "array",
                      "items": {
                        "$ref": "#/paths/~1api~1v1~1devices~1register/post/responses/201/content/application~1json/schema"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Database error"
          }
        }
      }
    },
    "/api/v1/devices/register": {
      "post": {
        "operationId": "registerDevice",
        "summary": "Register (or re-register) a device after pairing",
        "description": "Called by the firmware immediately after the OAuth device-code flow\ncompletes. Idempotent on the server: upserts the `devices` row keyed\nby `(user_id, X-Device-ID)` so a re-register is safe and refreshes\nserver-visible facts such as `firmware_version`, `name`, and\n`ota_slot_bytes`.\n\nRe-register is the supported path for a device to override the\nserver's legacy assumed OTA slot once newer firmware can report the\nreal partition size.\n\nIf the `X-Pairing-User-Code` header is set, the handler consumes the\nmatching row in `device_pairing_intents` (created by the browser's\nteam picker interstitial) and assigns the device to the chosen team.\nOtherwise it falls back to the user's first team membership.\n\nThe `ON CONFLICT DO UPDATE` clause deliberately does NOT touch\n`team_id`, so a plain re-register can never silently move a device\nbetween teams. When an intent is consumed, a separate `UPDATE` runs\nto apply the user's explicit choice — that's the only path that\nrewrites `team_id` on an existing row.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Device-ID",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Hardware-derived stable id the device sends on every request.\nFor scribe: 12-char lowercase hex of the ESP32-S3 base MAC.\n",
            "example": "aabbccddeeff"
          },
          {
            "name": "X-Pairing-User-Code",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "OAuth device-flow user_code the scribe displayed during pairing\nand the user approved in the browser. When set, the handler\nlooks up the matching `device_pairing_intents` row to pick the\nteam_id. Only sent on the initial post-pairing register call.\n",
            "example": "ABCD1234"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "hardware_type"
                ],
                "properties": {
                  "hardware_type": {
                    "type": "string",
                    "description": "Device class — matches the X-Device-Type header used elsewhere.",
                    "example": "scribe"
                  },
                  "firmware_version": {
                    "type": "string",
                    "description": "Last-reported firmware version, for support and rollout targeting.",
                    "example": "0.1.0"
                  },
                  "name_hint": {
                    "type": "string",
                    "description": "Optional friendly name a client may suggest at register time\n(e.g. user-entered in a companion app). If omitted, or if\nthe row already has a name set, the server's deterministic\ndefault / existing name wins.\n",
                    "example": "Kitchen Scribe"
                  },
                  "ota_slot_bytes": {
                    "type": "integer",
                    "format": "int32",
                    "description": "OTA partition (slot) size in bytes as reported by the\ndevice. Safe to omit on legacy firmware; the server then\nuses its legacy assumed slot until the device re-registers\nwith an explicit value.\n",
                    "example": 3060016
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Device registered (either freshly inserted or upserted)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "device_id",
                    "user_id",
                    "hardware_type",
                    "config",
                    "paired_at",
                    "updated_at"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Internal dev_<uuidv7> id",
                      "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
                    },
                    "device_id": {
                      "type": "string",
                      "description": "Hardware-derived stable id (X-Device-ID header)",
                      "example": "aabbccddeeff"
                    },
                    "user_id": {
                      "type": "string",
                      "description": "Owning user",
                      "example": "usr_ck3n8j2m10"
                    },
                    "team_id": {
                      "type": "string",
                      "description": "Active team, if assigned",
                      "example": "team_abc123xyz"
                    },
                    "hardware_type": {
                      "type": "string",
                      "example": "scribe"
                    },
                    "firmware_version": {
                      "type": "string",
                      "example": "0.1.0"
                    },
                    "name": {
                      "type": "string",
                      "example": "Kitchen Scribe"
                    },
                    "config": {
                      "type": "object",
                      "description": "Reserved for future device settings (wakeword, rewind consent, etc.)",
                      "additionalProperties": true
                    },
                    "last_seen_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Updated on every GetDeviceConfig poll"
                    },
                    "paired_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid X-Device-ID header, missing hardware_type, or malformed body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/devices/pairing-intents": {
      "post": {
        "operationId": "createDevicePairingIntent",
        "summary": "Store a team selection for an in-flight device pairing",
        "description": "Called by the /device browser interstitial BEFORE\n`authClient.device.approve()`, so that the scribe's follow-up\n`POST /api/v1/devices/register` call (which carries\n`X-Pairing-User-Code`) can resolve the user's team choice.\n\nThe row is keyed by the normalized user_code (uppercased, hyphens\nand spaces stripped) and scoped to the caller's user_id to prevent\ncross-user hijack even if two users somehow receive the same\nuser_code. Rows auto-expire after 10 minutes — matching the OAuth\ndevice code lifetime — and are swept periodically.\n\nThe caller must be a member of the target team; non-members get\n403.\n\n⚠️  ROUTE ORDERING: this path MUST be registered in chi BEFORE\n`/devices/{device_id}` routes, otherwise chi will try to match\n`pairing-intents` as a `{device_id}` parameter and return 405.\nSee the comment at the registration site in cmd/server/main.go.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_code",
                  "team_id"
                ],
                "properties": {
                  "user_code": {
                    "type": "string",
                    "description": "OAuth device-flow user_code. Case and hyphen insensitive —\nserver normalizes before storing.\n",
                    "example": "ABCD1234"
                  },
                  "team_id": {
                    "type": "string",
                    "description": "Team the caller wants the device to join. Caller must be a member.",
                    "example": "team_abc123xyz"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Intent stored (created or replaced)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "user_code",
                    "team_id",
                    "expires_at"
                  ],
                  "properties": {
                    "user_code": {
                      "type": "string",
                      "description": "Normalized form of the submitted code",
                      "example": "ABCD1234"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "UTC timestamp after which this intent is ignored",
                      "example": "2026-04-05T18:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing user_code or invalid team_id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Caller is not a member of the target team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Database error"
          }
        }
      }
    },
    "/api/v1/devices/{device_id}": {
      "get": {
        "operationId": "getDevice",
        "summary": "Fetch a single device by ID",
        "description": "Returns the full device details for the settings page. The owner\nsees the complete `DeviceResponse` including the hardware MAC\n(`device_id`). Team members who don't own the device see the\n`TeamDeviceResponse` projection (MAC and user_id omitted).\nEveryone else gets 404 to prevent device enumeration.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Internal `dev_<uuidv7>` id",
            "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
          }
        ],
        "responses": {
          "200": {
            "description": "Device details. Shape depends on caller's relationship to the device:\nowner gets DeviceResponse, team member gets TeamDeviceResponse.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/paths/~1api~1v1~1devices~1register/post/responses/201/content/application~1json/schema"
                    },
                    {
                      "type": "object",
                      "description": "Sanitized device projection for team members who don't own the device.\nOmits device_id (MAC address) and user_id to prevent hardware\nidentifier and user ID leakage.\n",
                      "required": [
                        "id",
                        "is_owner",
                        "can_manage",
                        "hardware_type",
                        "paired_at",
                        "updated_at"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Internal dev_<uuidv7> id",
                          "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
                        },
                        "is_owner": {
                          "type": "boolean",
                          "description": "Whether the caller owns this device",
                          "example": false
                        },
                        "can_manage": {
                          "type": "boolean",
                          "description": "Whether the caller may perform manager-only actions on this device\n(rename, move team, shared-room mode, disconnect). Covers owner,\npolicy manager_user_id, and ADR-041 device_managers grants; prefer\nthis over is_owner for gating manager-only UI. See ADR-068.\n",
                          "example": false
                        },
                        "registered_by": {
                          "type": "string",
                          "description": "Display name of the user who paired this device",
                          "example": "Person A"
                        },
                        "team_id": {
                          "type": "string",
                          "description": "Active team, if assigned",
                          "example": "team_abc123xyz"
                        },
                        "hardware_type": {
                          "type": "string",
                          "example": "scribe"
                        },
                        "firmware_version": {
                          "type": "string",
                          "example": "0.1.0"
                        },
                        "name": {
                          "type": "string",
                          "example": "Kitchen Scribe"
                        },
                        "last_seen_at": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "paired_at": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "updated_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing device_id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Device not found or caller has no access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Database error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteDevice",
        "summary": "Logout and unpair a device",
        "description": "Revokes the device's Better Auth session (if one is tracked via\n`session_id`) and deletes the device row. Only the device owner\ncan perform this operation — non-owners get 404 to prevent\ndevice enumeration.\n\nSession revocation is best-effort: if it fails, the device row\nis still deleted. The session will expire naturally via Better\nAuth's TTL.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Internal `dev_<uuidv7>` id",
            "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
          }
        ],
        "responses": {
          "204": {
            "description": "Device deleted successfully (no content)"
          },
          "400": {
            "description": "Invalid or missing device_id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Device not found or caller is not the owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Database error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateDevice",
        "summary": "Rename a device or reassign it to a different team",
        "description": "Called by the browser dashboard to rename a device or move it\nbetween teams. Caller must own the device (`devices.user_id ==\nJWT.user_id`) and, when changing `team_id`, must be a member of\nthe target team.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Internal `dev_<uuidv7>` id",
            "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "At least one of team_id, name, or recording_destination_id must be present",
                "additionalProperties": false,
                "anyOf": [
                  {
                    "required": [
                      "team_id"
                    ]
                  },
                  {
                    "required": [
                      "name"
                    ]
                  },
                  {
                    "required": [
                      "recording_destination_id"
                    ]
                  }
                ],
                "properties": {
                  "team_id": {
                    "type": "string",
                    "description": "New team. Pass empty string to unassign. Caller must be\na member of the target team when non-empty.\n",
                    "example": "team_abc123xyz"
                  },
                  "name": {
                    "type": "string",
                    "description": "Friendly device name shown on the dashboard",
                    "example": "Kitchen Scribe"
                  },
                  "recording_destination_id": {
                    "type": "string",
                    "nullable": true,
                    "description": "The hub's active recording destination — a prefixed\n`team_<id>` or `kb_<id>` (Knowledge Bubble). Pass `null`\nor `\"\"` to clear it (falls back to the legacy team_id).\nGuest-scoped: must be reachable by the current user; a\nbubble destination on a hardware hub requires firmware\n>= 0.6.0 (else 409). See ADR-068/069.\n",
                    "example": "kb_019d5eff-728b-7a50-a56e-9f843d8378fe"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Device updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1devices~1register/post/responses/201/content/application~1json/schema"
                }
              }
            }
          },
          "400": {
            "description": "Empty body, invalid device_id, team_id, or recording_destination_id"
          },
          "401": {
            "description": "Authentication required"
          },
          "403": {
            "description": "Caller cannot operate the device; or the destination is not reachable\nby the caller; or a non-manager attempted to change the device name or\nteam (those are manager-only — see ADR-068).\n"
          },
          "404": {
            "description": "Device not found"
          },
          "409": {
            "description": "recording_destination_id is a Knowledge Bubble but either the hardware\nhub's firmware is < 0.6.0, OR the device is a shared-space device (which\ncan only record into a team, not a Knowledge Bubble, until session-epoch\n— C1, ADR-068).\n"
          },
          "500": {
            "description": "Database error"
          }
        }
      }
    },
    "/api/v1/devices/{device_id}/config": {
      "get": {
        "operationId": "getDeviceConfig",
        "summary": "Fetch device-scoped config — scribe poll endpoint",
        "description": "Lean projection of the device row that the firmware polls at boot,\nafter auth refresh, and periodically while idle. Returns the active\n`team_id` the device should apply. Touches `last_seen_at` on every\nsuccessful call.\n\nOwnership is enforced in the handler (404 for nonexistent rows,\n403 for rows belonging to a different user, both distinct from the\n404 returned by the feature flag being off).\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Internal `dev_<uuidv7>` id returned by RegisterDevice",
            "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
          }
        ],
        "responses": {
          "200": {
            "description": "Device config",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "device_id",
                    "updated_at"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
                    },
                    "device_id": {
                      "type": "string",
                      "description": "Hardware X-Device-ID echoed back",
                      "example": "aabbccddeeff"
                    },
                    "active_team_id": {
                      "type": "string",
                      "description": "The team the device should apply. Empty if user has no teams.",
                      "example": "team_abc123xyz"
                    },
                    "name": {
                      "type": "string",
                      "example": "Kitchen Scribe"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Use this to skip no-op NVS writes when polling periodically",
                      "example": "2026-04-05T17:03:11Z"
                    },
                    "flags": {
                      "type": "object",
                      "description": "PostHog feature flags evaluated for the device owner. Absent\nwhen PostHog is unreachable — firmware should fall back to\nNVS-cached values. All values are boolean.\n",
                      "additionalProperties": {
                        "type": "boolean"
                      },
                      "example": {
                        "rewind-enabled": true
                      }
                    },
                    "settings": {
                      "type": "object",
                      "description": "Non-boolean tunables from the device's own config blob (the\nJSONB `config` column). Absent when no settings are\nconfigured. Editable via PATCH /devices/{device_id}.\n",
                      "additionalProperties": true,
                      "example": {
                        "silence-threshold-db": -40,
                        "upload-chunk-size-kb": 64
                      }
                    },
                    "shared_space_mode": {
                      "type": "boolean",
                      "description": "When true, firmware enforces idle auto-logout and\nforce-disables rewind so the device can be safely\nshared across multiple walk-up users (e.g. a\nconference-room scribe). Sourced from the\n`device_policy` table keyed by hardware device_id;\ndefaults to `false` for any device with no policy\nrow. Always emitted (no omitempty) so the server is\nauthoritative on every poll.\n",
                      "example": false
                    },
                    "auto_logout_minutes": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 60,
                      "description": "Idle threshold in minutes. Omitted when no value is\nset; firmware applies its built-in default (5).\nServer validates 1..60 on PATCH; CHECK constraint\nenforces the same range as defense in depth.\n",
                      "example": 5
                    },
                    "manager_user_id": {
                      "type": "string",
                      "description": "User who manages device policy (toggles\nshared_space_mode, sets auto_logout_minutes).\nPinned to the first pairer of this hardware via\nINSERT ... ON CONFLICT DO NOTHING; preserved\nacross walk-up re-pairs in shared mode. Falls\nback to `devices.user_id` for legacy rows with no\npolicy entry. Firmware compares JWT.sub against\nthis value to gate manager-only actions.\n",
                      "example": "usr_ck3n8j2m10"
                    },
                    "manager_display_name": {
                      "type": "string",
                      "description": "Human-readable name (`user.name`) of whoever\n`manager_user_id` points at. Lets the firmware\nrender messages like \"Ask <name> to change this\nsetting\" when a walk-up user hits a manager-only\nACL. Display name only — email is intentionally\nNOT exposed here; matches the privacy posture of\n`registered_by` on the team-devices response.\nOmitted when the underlying user row is missing\n(deleted account) so callers fall back to the\nopaque `manager_user_id`.\n",
                      "example": "Alice Anderson"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing device_id"
          },
          "401": {
            "description": "Authentication required"
          },
          "404": {
            "description": "Device not found, or device exists but belongs to a different user.\nBoth cases return 404 to prevent enumeration — callers cannot\ndistinguish \"doesn't exist\" from \"not yours\".\n"
          },
          "500": {
            "description": "Database error"
          }
        }
      },
      "patch": {
        "operationId": "updateDeviceConfig",
        "summary": "Toggle shared-space-mode policy and idle threshold",
        "description": "Mutates the per-hardware `device_policy` row. Authorized to the\ndevice manager (`device_policy.manager_user_id`) OR an active\nmember of the device's `team_id`. Strict body decoding rejects\nunknown fields with 400 so typos in policy keys surface fast\ninstead of becoming silent no-ops.\n\nPointer-style optional fields: omit a field to preserve its\nexisting value (COALESCE on the upsert). Sending\n`auto_logout_minutes: 0` is a 400, not a no-op — use omission to\nmean \"unchanged\" and the firmware default to mean \"no value\nset\".\n\n`manager_user_id` is intentionally not mutable through this\nendpoint. It is set on the very first RegisterDevice call for\nthe hardware and is immutable until a future transfer-of-manager\nflow ships.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Internal `dev_<uuidv7>` id",
            "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "shared_space_mode": {
                    "type": "boolean",
                    "description": "Master switch for shared-space behavior. Server is the source of truth.",
                    "example": true
                  },
                  "auto_logout_minutes": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 60,
                    "description": "Idle threshold; firmware default is 5 if unset.",
                    "example": 10
                  }
                },
                "minProperties": 1
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Policy updated. Firmware picks up the change on its next config poll (~60s)."
          },
          "400": {
            "description": "Invalid request — malformed body, unknown field,\nout-of-range `auto_logout_minutes`, or empty body (need at\nleast one of `shared_space_mode`/`auto_logout_minutes`).\n"
          },
          "401": {
            "description": "Authentication required"
          },
          "403": {
            "description": "A non-manager attempted to change a manager-only policy field\n(`shared_space_mode`, `operational_metrics_enabled`, or\n`auto_logout_minutes`). Session-level fields (`cast_tv_id`,\n`privacy_mode`) remain settable by any current user — see ADR-068.\n"
          },
          "404": {
            "description": "Device not found, or caller is neither the manager nor a\nmember of the device's team. 404 (not 403) to prevent\nenumeration — hardware device_ids derive from MACs in\npredictable Espressif OUI space.\n"
          },
          "500": {
            "description": "Database error"
          }
        }
      }
    },
    "/api/v1/devices/{device_id}/destinations": {
      "get": {
        "operationId": "getDeviceDestinations",
        "summary": "List a hub's recording destinations and reported peripherals (Room OS)",
        "description": "Lean, ESP32-safe list of the recording destinations (teams +\nKnowledge Bubbles) the CURRENT USER can reach, the active one, and\n— Room OS (firmware >= 0.6.0 for a hardware hub; always for a\nsoftware hub) — the peripherals the hub has reported. Auth:\nJWT + canUseDevice (guest-scoped); 404 (not 403) on unauthorized to\nblock device-id enumeration. See ADR-069.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Internal `dev_<uuidv7>` id",
            "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
          }
        ],
        "responses": {
          "200": {
            "description": "Reachable destinations, the active selection, and reported peripherals",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "destinations",
                    "peripherals"
                  ],
                  "properties": {
                    "destinations": {
                      "type": "array",
                      "description": "Always present (empty array, never null)",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "name",
                          "is_public"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Prefixed `team_…` or `kb_…` id",
                            "example": "kb_019d5eff-728b-7a50-a56e-9f843d8378fe"
                          },
                          "name": {
                            "type": "string",
                            "example": "Engineering"
                          },
                          "is_public": {
                            "type": "boolean"
                          }
                        }
                      }
                    },
                    "active_id": {
                      "type": "string",
                      "description": "The active destination id (one of destinations[].id); omitted when none or no longer reachable",
                      "example": "team_abc123xyz"
                    },
                    "peripherals": {
                      "type": "array",
                      "description": "Always present (empty array when none or surface withheld for a pre-0.6.0 hardware hub)",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/paths/~1api~1v1~1devices~1%7Bdevice_id%7D~1peripherals~1%7Bexternal_id%7D/put/requestBody/content/application~1json/schema"
                          },
                          {
                            "type": "object",
                            "required": [
                              "external_id"
                            ]
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing device_id"
          },
          "401": {
            "description": "Authentication required"
          },
          "404": {
            "description": "Device not found or caller not authorized"
          },
          "500": {
            "description": "Database error"
          }
        }
      }
    },
    "/api/v1/devices/{device_id}/peripherals/{external_id}": {
      "put": {
        "operationId": "reportDevicePeripheral",
        "summary": "Report a paired peripheral (Room OS, hub-reported)",
        "description": "The hub (firmware on a hardware hub, the app on a software hub)\nreports a peripheral paired to it. Stored per-hardware under\n`physical_devices.metadata.peripherals`, keyed by `external_id`,\nwith a clobber-safe `jsonb_set`. Auth: JWT + canManageDevice (strict\nmanager); 404 (not 403) on unauthorized. See ADR-069.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
          },
          {
            "name": "external_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The peripheral's native id from the hub's perspective (a foreign id, NOT a SageOx prefixed id)",
            "example": "chromecast-7c8b9a01"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "A device paired to a hub (ADR-069). `types[]` and `protocols[]`\nare an OPEN kebab-slug vocabulary (never enums) so new classes\n(xr, llm, whiteboard, …) need no schema change. On a PUT the\nexternal_id is the path param and may be omitted from the body.\n",
                "required": [
                  "name",
                  "types",
                  "direction"
                ],
                "properties": {
                  "external_id": {
                    "type": "string",
                    "description": "The peripheral's native id from the hub's perspective (the pairing key)",
                    "example": "chromecast-7c8b9a01"
                  },
                  "name": {
                    "type": "string",
                    "example": "Boardroom TV"
                  },
                  "types": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Capability slugs (open vocab) — display, speaker, microphone, projector, holographic, whiteboard, headset, camera, xr, glasses, wearable, llm, compute, controller, …",
                    "example": [
                      "display",
                      "microphone"
                    ]
                  },
                  "direction": {
                    "type": "string",
                    "enum": [
                      "input",
                      "output",
                      "both"
                    ],
                    "description": "input (hub captures), output (hub drives), both"
                  },
                  "protocols": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "chromecast",
                      "airplay"
                    ]
                  },
                  "network": {
                    "type": "object",
                    "description": "The network the peripheral was paired on (the v1 \"room\")",
                    "properties": {
                      "bssid": {
                        "type": "string",
                        "example": "aa:bb:cc:dd:ee:11"
                      },
                      "name": {
                        "type": "string",
                        "example": "Conf-A 5G"
                      }
                    }
                  },
                  "paired_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "last_seen": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "default_for": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "tenure": {
                    "type": "string",
                    "enum": [
                      "fixture",
                      "transient"
                    ],
                    "description": "fixture = durable room device (default); transient = an ephemeral control client (a user's app)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Peripheral stored"
          },
          "400": {
            "description": "Invalid body, external_id, or device_id"
          },
          "401": {
            "description": "Authentication required"
          },
          "404": {
            "description": "Device not found or caller not a manager"
          },
          "500": {
            "description": "Database error"
          }
        }
      },
      "delete": {
        "operationId": "deleteDevicePeripheral",
        "summary": "Remove a paired peripheral (Room OS, admin)",
        "description": "The admin removes a peripheral from the hub. Idempotent (removing an\nabsent peripheral is a no-op). Auth: JWT + canManageDevice; 404 on\nunauthorized.\n",
        "tags": [
          "Devices"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "dev_019d5eff-728b-7a50-a56e-9f843d8378fe"
          },
          {
            "name": "external_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "chromecast-7c8b9a01"
          }
        ],
        "responses": {
          "204": {
            "description": "Peripheral removed (idempotent)"
          },
          "400": {
            "description": "Invalid or missing external_id or device_id"
          },
          "401": {
            "description": "Authentication required"
          },
          "404": {
            "description": "Device not found or caller not a manager"
          },
          "500": {
            "description": "Database error"
          }
        }
      }
    },
    "/api/v1/teams": {
      "post": {
        "operationId": "createTeam",
        "summary": "Create a new team",
        "description": "Creates a new team and adds the authenticated user as the team owner.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Team display name (required)",
                    "example": "Product Team"
                  },
                  "slug": {
                    "type": "string",
                    "description": "URL-safe team identifier (optional, auto-generated if omitted)",
                    "example": "product-team"
                  }
                }
              },
              "examples": {
                "minimal": {
                  "summary": "Minimal request with auto-generated slug",
                  "value": {
                    "name": "Product Team"
                  }
                },
                "full": {
                  "summary": "Full request with explicit slug",
                  "value": {
                    "name": "Product Team",
                    "slug": "product-team"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Team created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "slug",
                    "name",
                    "created_at"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Team identifier (team_*)",
                      "example": "team_abc123xyz"
                    },
                    "slug": {
                      "type": "string",
                      "description": "URL-safe team identifier",
                      "example": "product-team"
                    },
                    "name": {
                      "type": "string",
                      "example": "Product Team"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T14:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_name": {
                    "value": {
                      "success": false,
                      "error": "team name is required"
                    }
                  },
                  "invalid_slug": {
                    "value": {
                      "success": false,
                      "error": "slug must be lowercase alphanumeric with hyphens"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTeams",
        "summary": "List user's teams",
        "description": "Returns all teams the authenticated user is a member of, with pagination.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "description": "Maximum number of teams to return"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Number of teams to skip"
          }
        ],
        "responses": {
          "200": {
            "description": "List of teams",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "teams",
                    "pagination"
                  ],
                  "properties": {
                    "teams": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "slug",
                          "name",
                          "member_count",
                          "created_at",
                          "updated_at"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "team_abc123xyz"
                          },
                          "slug": {
                            "type": "string",
                            "example": "product-team"
                          },
                          "name": {
                            "type": "string",
                            "example": "Product Team"
                          },
                          "member_count": {
                            "type": "integer",
                            "example": 5
                          },
                          "policies": {
                            "type": "object",
                            "additionalProperties": true,
                            "nullable": true
                          },
                          "conventions": {
                            "type": "object",
                            "additionalProperties": true,
                            "nullable": true
                          },
                          "metadata": {
                            "type": "object",
                            "additionalProperties": true,
                            "nullable": true
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-03T14:30:00Z"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-03T14:30:00Z"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "required": [
                        "total",
                        "limit",
                        "offset"
                      ],
                      "properties": {
                        "total": {
                          "type": "integer",
                          "description": "Total number of teams",
                          "example": 42
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Requested limit",
                          "example": 20
                        },
                        "offset": {
                          "type": "integer",
                          "description": "Requested offset",
                          "example": 0
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}": {
      "get": {
        "operationId": "getTeam",
        "summary": "Get team details",
        "description": "Returns detailed information about a team. User must be a team member.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "description": "Team identifier",
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Team details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "slug",
                    "name",
                    "member_count",
                    "created_at",
                    "updated_at"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "slug": {
                      "type": "string",
                      "example": "product-team"
                    },
                    "name": {
                      "type": "string",
                      "example": "Product Team"
                    },
                    "member_count": {
                      "type": "integer",
                      "example": 5
                    },
                    "policies": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "conventions": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "metadata": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T14:30:00Z"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T14:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid team_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateTeam",
        "summary": "Update team details",
        "description": "Updates team name, policies, or conventions. Requires owner role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "New team name (optional)",
                    "example": "Product Team Updated"
                  },
                  "policies": {
                    "type": "object",
                    "description": "Team policies configuration (optional)",
                    "additionalProperties": true,
                    "example": {
                      "max_members": 100,
                      "allow_public": true
                    }
                  },
                  "conventions": {
                    "type": "object",
                    "description": "Team conventions (optional)",
                    "additionalProperties": true,
                    "example": {
                      "code_review_required": true
                    }
                  }
                }
              },
              "examples": {
                "name_only": {
                  "summary": "Update name only",
                  "value": {
                    "name": "Product Team Updated"
                  }
                },
                "with_policies": {
                  "summary": "Update name and policies",
                  "value": {
                    "name": "Product Team",
                    "policies": {
                      "max_members": 100
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Team updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "slug",
                    "name",
                    "member_count",
                    "created_at",
                    "updated_at"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "slug": {
                      "type": "string",
                      "example": "product-team"
                    },
                    "name": {
                      "type": "string",
                      "example": "Product Team Updated"
                    },
                    "member_count": {
                      "type": "integer",
                      "example": 5
                    },
                    "policies": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "conventions": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "metadata": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T14:30:00Z"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T14:35:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTeam",
        "summary": "Delete a team",
        "description": "Soft-deletes a team. Requires owner role. Team can be recovered during grace period.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "204": {
            "description": "Team deleted successfully"
          },
          "400": {
            "description": "Invalid team_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/check-slug": {
      "get": {
        "operationId": "checkTeamSlug",
        "summary": "Check if team slug is available",
        "description": "Validates slug format and returns availability status.",
        "tags": [
          "Teams"
        ],
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]+$"
            },
            "description": "Slug to check",
            "example": "product-team"
          }
        ],
        "responses": {
          "200": {
            "description": "Slug validation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "available"
                  ],
                  "properties": {
                    "available": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "description": "Optional validation message",
                      "example": "this slug is available"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing slug parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/adopt": {
      "post": {
        "operationId": "adoptTeam",
        "summary": "Team adoption (deprecated)",
        "description": "This endpoint is deprecated. Teams are now standalone entities and cannot be adopted into organizations.",
        "tags": [
          "Teams"
        ],
        "deprecated": true,
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "410": {
            "description": "Gone - team adoption is deprecated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/claim": {
      "post": {
        "operationId": "claimTeam",
        "summary": "Claim team ownership with code",
        "description": "Claims ownership of an orphan team using a claim code generated during initialization.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "team_id",
                  "claim_code"
                ],
                "properties": {
                  "team_id": {
                    "type": "string",
                    "description": "Team identifier to claim",
                    "pattern": "^team_[a-z0-9]{10}$",
                    "example": "team_abc123xyz"
                  },
                  "claim_code": {
                    "type": "string",
                    "description": "Claim code from team initialization",
                    "example": "abc123xyz"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Team claimed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "team_id"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "message": {
                      "type": "string",
                      "example": "Team claimed successfully"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "410": {
            "description": "Claim code expired or invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/parent": {
      "get": {
        "operationId": "getTeamParent",
        "summary": "Get team's parent",
        "description": "Returns the parent team if one is set, or null if team is a root team.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Parent team or null",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "team_parent123"
                    },
                    "name": {
                      "type": "string",
                      "example": "Parent Team"
                    },
                    "slug": {
                      "type": "string",
                      "example": "parent-team"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "setTeamParent",
        "summary": "Set or unset team parent",
        "description": "Sets a parent team to create hierarchy, or unsets the parent to make it a root team. Requires owner role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "parent_team_id"
                ],
                "properties": {
                  "parent_team_id": {
                    "type": "string",
                    "nullable": true,
                    "description": "Parent team ID, or null to make this a root team",
                    "example": "team_parent123"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Parent set successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "parent_team_id": {
                      "type": "string",
                      "nullable": true,
                      "example": "team_parent123"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "circular": {
                    "value": {
                      "success": false,
                      "error": "would create circular reference"
                    }
                  },
                  "self_reference": {
                    "value": {
                      "success": false,
                      "error": "team cannot be its own parent"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions or not member of parent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team or parent not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/children": {
      "get": {
        "operationId": "getTeamChildren",
        "summary": "Get team's child teams",
        "description": "Returns all direct child teams in the hierarchy.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Array of child teams",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "id",
                      "name",
                      "slug"
                    ],
                    "properties": {
                      "id": {
                        "type": "string",
                        "example": "team_child1xyz"
                      },
                      "name": {
                        "type": "string",
                        "example": "Child Team 1"
                      },
                      "slug": {
                        "type": "string",
                        "example": "child-team-1"
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "updated_at": {
                        "type": "string",
                        "format": "date-time"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/ancestors": {
      "get": {
        "operationId": "getTeamAncestors",
        "summary": "Get team's ancestor chain",
        "description": "Returns the complete ancestor chain up to the root team.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Array of ancestor teams from immediate parent to root",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "id",
                      "name",
                      "slug"
                    ],
                    "properties": {
                      "id": {
                        "type": "string",
                        "example": "team_root123"
                      },
                      "name": {
                        "type": "string",
                        "example": "Root Team"
                      },
                      "slug": {
                        "type": "string",
                        "example": "root-team"
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "updated_at": {
                        "type": "string",
                        "format": "date-time"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/members": {
      "get": {
        "operationId": "listTeamMembers",
        "summary": "List team members",
        "description": "Returns all active team members with their roles and metadata.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Team members list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "members",
                    "total"
                  ],
                  "properties": {
                    "members": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "user_id",
                          "email",
                          "role",
                          "invited_at"
                        ],
                        "properties": {
                          "user_id": {
                            "type": "string",
                            "example": "user_abc123"
                          },
                          "email": {
                            "type": "string",
                            "format": "email",
                            "example": "person@example.com"
                          },
                          "name": {
                            "type": "string",
                            "example": "Person Name"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "owner",
                              "admin",
                              "member"
                            ],
                            "example": "owner"
                          },
                          "invited_by": {
                            "type": "string",
                            "description": "User ID of person who invited this member",
                            "example": "user_xyz789"
                          },
                          "invited_at": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-03T14:30:00Z"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer",
                      "example": 5
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/members/{user_id}": {
      "put": {
        "operationId": "updateTeamMemberRole",
        "summary": "Update team member role",
        "description": "Changes a member's role within the team. Requires owner role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "User ID to update",
            "example": "user_def456"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "role"
                ],
                "properties": {
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "member"
                    ],
                    "description": "New role for the member",
                    "example": "admin"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member role updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "user_id",
                    "email",
                    "role",
                    "invited_at"
                  ],
                  "properties": {
                    "user_id": {
                      "type": "string",
                      "example": "user_def456"
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "example": "person@example.com"
                    },
                    "name": {
                      "type": "string",
                      "example": "Person Name"
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "owner",
                        "admin",
                        "member"
                      ],
                      "example": "admin"
                    },
                    "invited_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T14:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "last_owner": {
                    "value": {
                      "success": false,
                      "error": "cannot demote the last owner"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team or member not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "removeTeamMember",
        "summary": "Remove team member",
        "description": "Removes a member from the team. Requires owner role. Cannot remove the last owner.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "User ID to remove",
            "example": "user_def456"
          }
        ],
        "responses": {
          "204": {
            "description": "Member removed successfully"
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "last_owner": {
                    "value": {
                      "success": false,
                      "error": "cannot revoke the last owner"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team or member not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/members/me": {
      "delete": {
        "operationId": "leaveTeam",
        "summary": "Leave team",
        "description": "Allows the authenticated user to remove themselves from a team. Cannot leave if you are the last owner.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "204": {
            "description": "Successfully left team"
          },
          "400": {
            "description": "Cannot leave",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "last_owner": {
                    "value": {
                      "success": false,
                      "error": "cannot leave as the last owner - transfer ownership or delete the team instead"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found or not a member",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/members/bulk": {
      "put": {
        "operationId": "bulkUpdateTeamMemberRoles",
        "summary": "Bulk update member roles",
        "description": "Updates roles for multiple members in a single request. Requires owner role. Partial errors are returned with successful updates.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_ids",
                  "role"
                ],
                "properties": {
                  "user_ids": {
                    "type": "array",
                    "description": "Array of user IDs to update",
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "user_def456",
                      "user_ghi789"
                    ]
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "member"
                    ],
                    "description": "New role for all specified users",
                    "example": "admin"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Members updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "updated",
                    "total"
                  ],
                  "properties": {
                    "updated": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "user_id": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string",
                            "format": "email"
                          },
                          "name": {
                            "type": "string"
                          },
                          "role": {
                            "type": "string"
                          },
                          "invited_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "errors": {
                      "type": "array",
                      "description": "Errors from unsuccessful operations",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "bulkRemoveTeamMembers",
        "summary": "Bulk remove members",
        "description": "Removes multiple members from a team in a single request. Requires owner role. Cannot remove all owners.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_ids"
                ],
                "properties": {
                  "user_ids": {
                    "type": "array",
                    "description": "Array of user IDs to remove",
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "user_def456",
                      "user_ghi789"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Members removed (includes partial success)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "revoked",
                    "total"
                  ],
                  "properties": {
                    "revoked": {
                      "type": "array",
                      "description": "User IDs that were successfully removed",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "user_def456"
                      ]
                    },
                    "total": {
                      "type": "integer"
                    },
                    "errors": {
                      "type": "array",
                      "description": "Errors from unsuccessful operations",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "no_owners": {
                    "value": {
                      "success": false,
                      "error": "cannot revoke all owners from the team"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/invites": {
      "post": {
        "operationId": "createTeamInvite",
        "summary": "Create team invite",
        "description": "Invites a user to join a team by email. Requires owner role. An active invite must not already exist for this email.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Email address to invite",
                    "example": "newmember@example.com"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "member"
                    ],
                    "description": "Role for the invited member (defaults to member)",
                    "default": "member",
                    "example": "member"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invite created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "email",
                    "team_id",
                    "role",
                    "invited_by",
                    "invited_at",
                    "expires_at",
                    "token"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Invite ID",
                      "example": "inv_abc123"
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "example": "newmember@example.com"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "role": {
                      "type": "string",
                      "example": "member"
                    },
                    "invited_by": {
                      "type": "string",
                      "description": "User ID of person who created invite",
                      "example": "user_owner123"
                    },
                    "invited_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T14:30:00Z"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Invite expiration time",
                      "example": "2025-12-10T14:30:00Z"
                    },
                    "token": {
                      "type": "string",
                      "description": "Token for invite acceptance link",
                      "example": "token_abc123xyz"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Active invite already exists for this email",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTeamInvites",
        "summary": "List pending team invites",
        "description": "Returns all active (non-expired, non-accepted) invites for the team. Requires owner role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "List of pending invites",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "id",
                      "email",
                      "team_id",
                      "role",
                      "invited_by",
                      "invited_at",
                      "expires_at"
                    ],
                    "properties": {
                      "id": {
                        "type": "string",
                        "example": "inv_abc123"
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "example": "newmember@example.com"
                      },
                      "team_id": {
                        "type": "string",
                        "example": "team_abc123xyz"
                      },
                      "role": {
                        "type": "string",
                        "example": "member"
                      },
                      "invited_by": {
                        "type": "string",
                        "example": "user_owner123"
                      },
                      "invited_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2025-12-03T14:30:00Z"
                      },
                      "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2025-12-10T14:30:00Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/invites/{invite_id}": {
      "delete": {
        "operationId": "revokeTeamInvite",
        "summary": "Revoke team invite",
        "description": "Revokes a pending invite, preventing the recipient from accepting it. Requires owner role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          },
          {
            "name": "invite_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Invite ID to revoke",
            "example": "inv_abc123"
          }
        ],
        "responses": {
          "204": {
            "description": "Invite revoked"
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team or invite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/invites/team/{token}": {
      "get": {
        "operationId": "getTeamInviteByToken",
        "summary": "Get team invite details",
        "description": "Retrieves invite details using a token (no authentication required). Used to preview invites before accepting.",
        "tags": [
          "Teams"
        ],
        "security": [],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Invite token",
            "example": "token_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Invite details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "email",
                    "team_id",
                    "team_name",
                    "role",
                    "invited_by",
                    "expires_at"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "inv_abc123"
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "example": "newmember@example.com"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "team_name": {
                      "type": "string",
                      "example": "Product Team"
                    },
                    "role": {
                      "type": "string",
                      "example": "member"
                    },
                    "invited_by": {
                      "type": "string",
                      "description": "User ID of inviter",
                      "example": "user_owner123"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-10T14:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Invite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "410": {
            "description": "Invite expired or invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/invite-code": {
      "get": {
        "operationId": "getTeamInviteCode",
        "summary": "Get team invite code",
        "description": "Returns the current invite code for the team (generates one if none exists). Requires owner or admin role. Use code with join endpoint to add members.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Current invite code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "url"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Short invite code",
                      "example": "ABC2D3EF5GH7"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Full invite URL",
                      "example": "https://sageox.ai/teams/team_abc123xyz/join?code=ABC2D3EF5GH7"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner or admin role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "regenerateTeamInviteCode",
        "summary": "Regenerate team invite code",
        "description": "Generates a new invite code, invalidating the previous one. Requires owner role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "New invite code generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "url"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "New short invite code",
                      "example": "XYZ9ABCDEF2G"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Full invite URL",
                      "example": "https://sageox.ai/teams/team_abc123xyz/join?code=XYZ9ABCDEF2G"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/join": {
      "post": {
        "operationId": "joinTeamWithCode",
        "summary": "Join team with invite code",
        "description": "Joins an authenticated user to a team using an invite code. Automatically grants member role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "code"
                ],
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "Invite code from GET /api/v1/teams/{team_id}/invite-code",
                    "example": "ABC2D3EF5GH7"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully joined team",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "team_id",
                    "team_name",
                    "team_slug"
                  ],
                  "properties": {
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "team_name": {
                      "type": "string",
                      "example": "Product Team"
                    },
                    "team_slug": {
                      "type": "string",
                      "example": "product-team"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid code or already a member",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/delete": {
      "post": {
        "operationId": "initiateTeamDeletion",
        "summary": "Initiate team deletion",
        "description": "Starts the team deletion process with a grace period. Requires owner role. Returns a workflow ID for tracking.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "Optional reason for deletion (audit purposes)",
                    "example": "Project concluded"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deletion initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "team_id",
                    "status",
                    "status_url",
                    "expires_at"
                  ],
                  "properties": {
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending"
                      ],
                      "example": "pending"
                    },
                    "status_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "URL to check deletion status",
                      "example": "/api/v1/teams/team_abc123xyz/delete"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Estimated expiration (authoritative value in workflow)",
                      "example": "2025-12-10T14:30:00Z"
                    },
                    "workflow_id": {
                      "type": "string",
                      "description": "Temporal workflow ID for tracking",
                      "example": "team-deletion-requested-team_abc123xyz"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getTeamDeletionStatus",
        "summary": "Get team deletion status",
        "description": "Checks the current status of a team deletion request.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Deletion status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "team_id",
                    "status",
                    "initiated_by",
                    "initiated_at",
                    "expires_at"
                  ],
                  "properties": {
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "confirmed",
                        "canceled",
                        "expired",
                        "completed"
                      ],
                      "example": "pending"
                    },
                    "initiated_by": {
                      "type": "string",
                      "description": "User ID who initiated deletion",
                      "example": "user_owner123"
                    },
                    "initiated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T14:30:00Z"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-10T14:30:00Z"
                    },
                    "confirmed_by": {
                      "type": "string",
                      "nullable": true,
                      "description": "User ID who confirmed deletion",
                      "example": null
                    },
                    "confirmed_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "example": null
                    },
                    "workflow_id": {
                      "type": "string",
                      "example": "team-deletion-requested-team_abc123xyz"
                    },
                    "confirmation_required": {
                      "type": "string",
                      "description": "Text that must be typed to confirm (only when status is pending)",
                      "example": "team_abc123xyz"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found or no deletion in progress",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/delete/confirm": {
      "post": {
        "operationId": "confirmTeamDeletion",
        "summary": "Confirm team deletion",
        "description": "Confirms deletion of a team. Must type the team ID exactly to prevent accidental deletion. Requires owner role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirmation_text"
                ],
                "properties": {
                  "confirmation_text": {
                    "type": "string",
                    "description": "Must match the team_id exactly",
                    "example": "team_abc123xyz"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deletion confirmed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "team_id",
                    "status"
                  ],
                  "properties": {
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "confirmed"
                      ],
                      "example": "confirmed"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Confirmation text incorrect or deletion not pending",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/delete/cancel": {
      "post": {
        "operationId": "cancelTeamDeletion",
        "summary": "Cancel team deletion",
        "description": "Cancels a pending team deletion request. Requires owner role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Deletion canceled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "team_id",
                    "status"
                  ],
                  "properties": {
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "canceled"
                      ],
                      "example": "canceled"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "No deletion pending or already confirmed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/conventions": {
      "get": {
        "operationId": "getTeamConventions",
        "summary": "Get team conventions",
        "description": "Returns published and draft conventions for the team. Any team member can view.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Team conventions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "description": "Published conventions",
                      "example": "# Team Conventions\\n\\nAll PRs require 2 approvals."
                    },
                    "draft": {
                      "type": "string",
                      "nullable": true,
                      "description": "Draft conventions (if any)",
                      "example": "# Team Conventions\\n\\nAll PRs require 2 approvals.\\nCode coverage must be above 80%."
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-03T14:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/conventions/draft": {
      "put": {
        "operationId": "saveDraftConventions",
        "summary": "Save draft conventions",
        "description": "Saves draft conventions without publishing. Requires owner role. Drafts can be discarded or published.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "draft"
                ],
                "properties": {
                  "draft": {
                    "type": "string",
                    "description": "Draft conventions content (Markdown)",
                    "example": "# Team Conventions\\n\\nAll PRs require 2 approvals.\\nCode coverage must be above 80%."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Draft saved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string"
                    },
                    "draft": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "discardDraftConventions",
        "summary": "Discard draft conventions",
        "description": "Discards any unsaved draft conventions. Requires owner role.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "204": {
            "description": "Draft discarded"
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/conventions/publish": {
      "post": {
        "operationId": "publishConventions",
        "summary": "Publish conventions",
        "description": "Publishes the current draft as the active conventions. Requires owner role. Draft is cleared after publishing.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Conventions published",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "description": "Published conventions"
                    },
                    "draft": {
                      "type": "string",
                      "nullable": true,
                      "example": null
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "No draft to publish",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (requires owner role)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/diagram": {
      "get": {
        "operationId": "getTeamDiagram",
        "summary": "Get team diagram",
        "description": "Returns aggregated resource counts by category for visualization. Member-accessible.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Team diagram data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "team_id",
                    "total_resources",
                    "by_category"
                  ],
                  "properties": {
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "total_resources": {
                      "type": "integer",
                      "example": 42
                    },
                    "by_category": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "category",
                          "count"
                        ],
                        "properties": {
                          "category": {
                            "type": "string",
                            "example": "repository"
                          },
                          "count": {
                            "type": "integer",
                            "example": 12
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/entities": {
      "get": {
        "operationId": "getTeamEntities",
        "summary": "Get team entities",
        "description": "Returns flattened list of all entities (resources) in the team for table display. Member-accessible.",
        "tags": [
          "Teams"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^team_[a-z0-9]{10}$"
            },
            "example": "team_abc123xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Team entities list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "team_id",
                    "entities",
                    "total"
                  ],
                  "properties": {
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "entities": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "resource_id",
                          "resource_title",
                          "resource_type",
                          "category"
                        ],
                        "properties": {
                          "resource_id": {
                            "type": "string",
                            "example": "repo_012345"
                          },
                          "resource_title": {
                            "type": "string",
                            "example": "My Repository"
                          },
                          "resource_type": {
                            "type": "string",
                            "example": "repository"
                          },
                          "provider": {
                            "type": "string",
                            "example": "github"
                          },
                          "category": {
                            "type": "string",
                            "example": "repository"
                          },
                          "lifecycle": {
                            "type": "string",
                            "example": "active"
                          },
                          "status": {
                            "type": "string",
                            "example": "healthy"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer",
                      "example": 42
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/tree": {
      "get": {
        "operationId": "getRepoTree",
        "summary": "Get repository file tree",
        "description": "Returns the file and directory tree for a repository at the specified path and reference.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of a team associated with the repository.\n\n**Caching:** Responses are cached for 30 seconds to reduce GitLab API load.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          },
          {
            "name": "path",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "src/components"
            },
            "description": "Subdirectory path (default empty/root)"
          },
          {
            "name": "ref",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "main"
            },
            "description": "Branch, tag, or commit SHA (default HEAD)"
          },
          {
            "name": "recursive",
            "in": "query",
            "schema": {
              "type": "boolean",
              "example": false
            },
            "description": "Return recursive tree (all nested entries)"
          }
        ],
        "responses": {
          "200": {
            "description": "Repository tree retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "entries",
                    "ref",
                    "path"
                  ],
                  "properties": {
                    "entries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "name",
                          "type",
                          "path"
                        ],
                        "properties": {
                          "name": {
                            "type": "string",
                            "example": "package.json"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "file",
                              "directory"
                            ],
                            "example": "file"
                          },
                          "path": {
                            "type": "string",
                            "example": "package.json"
                          },
                          "size": {
                            "type": "integer",
                            "example": 1234
                          },
                          "mode": {
                            "type": "string",
                            "example": "100644"
                          }
                        }
                      }
                    },
                    "ref": {
                      "type": "string",
                      "example": "main"
                    },
                    "path": {
                      "type": "string",
                      "example": "src/components"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of any team associated with this repository",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository or path not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/files/{path}": {
      "get": {
        "operationId": "getRepoFileOrBlame",
        "summary": "Get file content or blame information",
        "description": "Returns file content with metadata or blame information if the path ends with `/blame`.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of a team associated with the repository.\n\n**Caching:** File content responses are cached for 30 seconds.\n\n**Blame Annotation:** Append `/blame` to the file path to retrieve line-by-line author and commit information.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "README.md"
            },
            "description": "File path (supports nested paths). Append `/blame` to get blame information.\nExample: `src/main.py/blame`\n"
          },
          {
            "name": "ref",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "main"
            },
            "description": "Branch, tag, or commit SHA (default HEAD)"
          }
        ],
        "responses": {
          "200": {
            "description": "File content retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "content",
                    "size",
                    "is_binary",
                    "is_renderable"
                  ],
                  "properties": {
                    "content": {
                      "type": "string",
                      "example": "# Welcome to Project A\\n\\nThis project demonstrates..."
                    },
                    "size": {
                      "type": "integer",
                      "example": 2048
                    },
                    "file_name": {
                      "type": "string",
                      "example": "README.md"
                    },
                    "content_type": {
                      "type": "string",
                      "example": "text/markdown"
                    },
                    "encoding": {
                      "type": "string",
                      "example": "utf-8"
                    },
                    "is_binary": {
                      "type": "boolean",
                      "example": false
                    },
                    "is_renderable": {
                      "type": "boolean",
                      "example": true
                    },
                    "render_type": {
                      "type": "string",
                      "enum": [
                        "markdown",
                        "plaintext",
                        "code",
                        "image",
                        "pdf"
                      ],
                      "example": "markdown"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of any team associated with this repository",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "File or repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/files/{path}/blame": {
      "get": {
        "operationId": "getRepoFileBlame",
        "summary": "Get file blame information",
        "description": "Returns blame information (line-by-line author and commit history) for a file.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of a team associated with the repository.\n\n**Caching:** Responses are cached for 30 seconds.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "src/main.py"
            },
            "description": "File path"
          },
          {
            "name": "ref",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "main"
            },
            "description": "Branch, tag, or commit SHA (default HEAD)"
          }
        ],
        "responses": {
          "200": {
            "description": "Blame information retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ranges",
                    "file_path",
                    "ref"
                  ],
                  "properties": {
                    "ranges": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "start_line",
                          "end_line",
                          "commit",
                          "author_name",
                          "author_email",
                          "commit_date"
                        ],
                        "properties": {
                          "start_line": {
                            "type": "integer",
                            "example": 1
                          },
                          "end_line": {
                            "type": "integer",
                            "example": 10
                          },
                          "commit": {
                            "type": "object",
                            "required": [
                              "id",
                              "message"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "example": "abc123def456789abc123def456789abc123def4"
                              },
                              "message": {
                                "type": "string",
                                "example": "Implement feature X"
                              }
                            }
                          },
                          "author_name": {
                            "type": "string",
                            "example": "Person A"
                          },
                          "author_email": {
                            "type": "string",
                            "format": "email",
                            "example": "user@example.com"
                          },
                          "commit_date": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-18T10:30:00Z"
                          }
                        }
                      }
                    },
                    "file_path": {
                      "type": "string",
                      "example": "src/main.py"
                    },
                    "ref": {
                      "type": "string",
                      "example": "main"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of any team associated with this repository",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "File or repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/commits": {
      "get": {
        "operationId": "getRepoCommits",
        "summary": "List repository commits",
        "description": "Returns a paginated list of commits for the repository, optionally filtered by path.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of a team associated with the repository.\n\n**Pagination:** Uses page-based pagination with configurable page size (max 100).\n\n**Caching:** Responses are cached for 30 seconds.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          },
          {
            "name": "ref",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "main"
            },
            "description": "Branch, tag, or commit SHA (default HEAD)"
          },
          {
            "name": "path",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "src"
            },
            "description": "Filter commits by path"
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            },
            "description": "Page number (default 1)"
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "example": 20
            },
            "description": "Items per page (default 20, max 100)"
          }
        ],
        "responses": {
          "200": {
            "description": "Commits retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "commits",
                    "page",
                    "per_page",
                    "has_more"
                  ],
                  "properties": {
                    "commits": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "message",
                          "author_name",
                          "author_email",
                          "authored_date"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "abc123def456789abc123def456789abc123def4"
                          },
                          "message": {
                            "type": "string",
                            "example": "Implement feature X"
                          },
                          "author_name": {
                            "type": "string",
                            "example": "Person A"
                          },
                          "author_email": {
                            "type": "string",
                            "format": "email",
                            "example": "user@example.com"
                          },
                          "authored_date": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-18T10:30:00Z"
                          },
                          "committed_date": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-18T10:30:00Z"
                          },
                          "parent_ids": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "example": [
                              "parent_sha_1",
                              "parent_sha_2"
                            ]
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "example": 1
                    },
                    "per_page": {
                      "type": "integer",
                      "example": 20
                    },
                    "total_count": {
                      "type": "integer",
                      "example": 150
                    },
                    "has_more": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of any team associated with this repository",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/commits/{sha}": {
      "get": {
        "operationId": "getRepoCommit",
        "summary": "Get commit details",
        "description": "Returns detailed information for a specific commit including diffs and statistics.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of a team associated with the repository.\n\n**Caching:** Responses are cached for 30 seconds.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          },
          {
            "name": "sha",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "abc123def456789abc123def456789abc123def4"
            },
            "description": "Commit SHA"
          }
        ],
        "responses": {
          "200": {
            "description": "Commit details retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "message",
                    "author_name",
                    "author_email",
                    "authored_date"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "abc123def456789abc123def456789abc123def4"
                    },
                    "message": {
                      "type": "string",
                      "example": "Implement feature X\\n\\nThis commit adds support for feature X..."
                    },
                    "author_name": {
                      "type": "string",
                      "example": "Person A"
                    },
                    "author_email": {
                      "type": "string",
                      "format": "email",
                      "example": "user@example.com"
                    },
                    "authored_date": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "committed_date": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "parent_ids": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "parent_sha_1"
                      ]
                    },
                    "additions": {
                      "type": "integer",
                      "example": 42
                    },
                    "deletions": {
                      "type": "integer",
                      "example": 8
                    },
                    "files_changed": {
                      "type": "integer",
                      "example": 3
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of any team associated with this repository",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Commit or repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/compare": {
      "get": {
        "operationId": "getRepoCompare",
        "summary": "Compare two references",
        "description": "Returns the diff between two references (branches, tags, or commits).\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of a team associated with the repository.\n\n**Caching:** Responses are cached for 30 seconds.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "main"
            },
            "description": "Base reference (branch, tag, or SHA)"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "feature/new-api"
            },
            "description": "Compare-to reference (branch, tag, or SHA)"
          }
        ],
        "responses": {
          "200": {
            "description": "Comparison retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "from",
                    "to"
                  ],
                  "properties": {
                    "from": {
                      "type": "string",
                      "example": "main"
                    },
                    "to": {
                      "type": "string",
                      "example": "feature/new-api"
                    },
                    "commits": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "message",
                          "author_name",
                          "authored_date"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "abc123def456789abc123def456789abc123def4"
                          },
                          "message": {
                            "type": "string",
                            "example": "Add new API endpoint"
                          },
                          "author_name": {
                            "type": "string",
                            "example": "Person A"
                          },
                          "authored_date": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-18T10:30:00Z"
                          }
                        }
                      }
                    },
                    "additions": {
                      "type": "integer",
                      "example": 120
                    },
                    "deletions": {
                      "type": "integer",
                      "example": 15
                    },
                    "files_changed": {
                      "type": "integer",
                      "example": 7
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters (missing from or to)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of any team associated with this repository",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository or references not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/ledger-status": {
      "get": {
        "operationId": "getRepoLedgerStatus",
        "summary": "Check repository Ledger status",
        "description": "Returns the status of the Ledger repository for a given repository.\n\n**Authentication:** Required (bearer token)\n\n**Status Values:**\n- `ready` - Ledger exists and is ready to use\n- `pending` - Ledger creation is in progress\n- `unavailable` - GitLab integration is not configured\n\n**Anti-Entropy:** This endpoint triggers async Ledger creation if missing.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Ledger status retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ready",
                        "pending",
                        "unavailable"
                      ],
                      "example": "ready"
                    },
                    "repo_url": {
                      "type": "string",
                      "format": "uri",
                      "example": "http://localhost:8929/groups/team-abc123/projects/ledger-repo-abc123"
                    },
                    "repo_id": {
                      "type": "integer",
                      "example": 42
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "message": {
                      "type": "string",
                      "example": "Ledger repository not yet created"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/create-ledger": {
      "post": {
        "operationId": "createRepoLedger",
        "summary": "Create repository Ledger",
        "description": "Manually triggers creation of a Ledger repository for a given repository.\n\n**Authentication:** Required (bearer token)\n\n**Response Codes:**\n- `201 Created` - Ledger was created successfully\n- `200 OK` - Ledger already exists\n- `503 Service Unavailable` - GitLab not configured or creation failed\n\n**Idempotent:** If Ledger already exists, returns existing repo information.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Ledger already exists",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "repo_url"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "ready"
                    },
                    "repo_url": {
                      "type": "string",
                      "format": "uri",
                      "example": "http://localhost:8929/groups/team-abc123/projects/ledger-repo-abc123"
                    },
                    "message": {
                      "type": "string",
                      "example": "Ledger repository already exists"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Ledger repository created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "repo_url"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "ready"
                    },
                    "repo_url": {
                      "type": "string",
                      "format": "uri",
                      "example": "http://localhost:8929/groups/team-abc123/projects/ledger-repo-abc123"
                    },
                    "repo_id": {
                      "type": "integer",
                      "example": 42
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "message": {
                      "type": "string",
                      "example": "Ledger repository created successfully"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "GitLab integration not configured or creation failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/norms-repo/tree": {
      "get": {
        "operationId": "getTeamNormsTree",
        "summary": "Get team norms repository file tree",
        "description": "Returns the file and directory tree for a team's norms repository.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of the team.\n\n**Caching:** Responses are cached for 30 seconds.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            },
            "description": "Team identifier"
          },
          {
            "name": "path",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "engineering"
            },
            "description": "Subdirectory path (default empty/root)"
          },
          {
            "name": "ref",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "main"
            },
            "description": "Branch, tag, or commit SHA (default HEAD)"
          },
          {
            "name": "recursive",
            "in": "query",
            "schema": {
              "type": "boolean",
              "example": false
            },
            "description": "Return recursive tree"
          }
        ],
        "responses": {
          "200": {
            "description": "Team norms tree retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "entries",
                    "ref",
                    "path"
                  ],
                  "properties": {
                    "entries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "name",
                          "type",
                          "path"
                        ],
                        "properties": {
                          "name": {
                            "type": "string",
                            "example": "CODING_STANDARDS.md"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "file",
                              "directory"
                            ],
                            "example": "file"
                          },
                          "path": {
                            "type": "string",
                            "example": "CODING_STANDARDS.md"
                          },
                          "size": {
                            "type": "integer",
                            "example": 3456
                          }
                        }
                      }
                    },
                    "ref": {
                      "type": "string",
                      "example": "main"
                    },
                    "path": {
                      "type": "string",
                      "example": "engineering"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team or path not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/norms-repo/files/{path}": {
      "get": {
        "operationId": "getTeamNormsFileOrBlame",
        "summary": "Get team norms file content or blame",
        "description": "Returns file content or blame information from a team's norms repository.\nAppend `/blame` to get blame information.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of the team.\n\n**Caching:** Responses are cached for 30 seconds.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            },
            "description": "Team identifier"
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "CODING_STANDARDS.md"
            },
            "description": "File path. Append `/blame` for blame information.\nExample: `CODING_STANDARDS.md/blame`\n"
          },
          {
            "name": "ref",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "main"
            },
            "description": "Branch, tag, or commit SHA (default HEAD)"
          }
        ],
        "responses": {
          "200": {
            "description": "File content retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "content",
                    "size",
                    "is_binary",
                    "is_renderable"
                  ],
                  "properties": {
                    "content": {
                      "type": "string",
                      "example": "# Coding Standards\\n\\n## Python\\n..."
                    },
                    "size": {
                      "type": "integer",
                      "example": 3456
                    },
                    "file_name": {
                      "type": "string",
                      "example": "CODING_STANDARDS.md"
                    },
                    "content_type": {
                      "type": "string",
                      "example": "text/markdown"
                    },
                    "is_binary": {
                      "type": "boolean",
                      "example": false
                    },
                    "is_renderable": {
                      "type": "boolean",
                      "example": true
                    },
                    "render_type": {
                      "type": "string",
                      "enum": [
                        "markdown",
                        "plaintext",
                        "code",
                        "image",
                        "pdf"
                      ],
                      "example": "markdown"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "File or team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "putTeamNormsFile",
        "summary": "Create or update team norms file",
        "description": "Creates or updates a file in a team's norms repository with a commit message.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of the team.\n\n**Branch:** Defaults to `main` if not specified.\n\n**Commit Attribution:** Author name and email from user's profile.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            },
            "description": "Team identifier"
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "ENGINEERING_PROCESS.md"
            },
            "description": "File path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "content",
                  "commit_message"
                ],
                "properties": {
                  "content": {
                    "type": "string",
                    "example": "# Engineering Process\\n\\n## Code Review\\n..."
                  },
                  "commit_message": {
                    "type": "string",
                    "example": "Update engineering process documentation"
                  },
                  "branch": {
                    "type": "string",
                    "example": "main",
                    "description": "Target branch (default main)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File saved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "file_path",
                    "commit_id",
                    "branch"
                  ],
                  "properties": {
                    "file_path": {
                      "type": "string",
                      "example": "ENGINEERING_PROCESS.md"
                    },
                    "commit_id": {
                      "type": "string",
                      "example": "abc123def456789abc123def456789abc123def4"
                    },
                    "branch": {
                      "type": "string",
                      "example": "main"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/norms-repo/commits": {
      "get": {
        "operationId": "getTeamNormsCommits",
        "summary": "List team norms repository commits",
        "description": "Returns a paginated list of commits for a team's norms repository.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of the team.\n\n**Caching:** Responses are cached for 30 seconds.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            },
            "description": "Team identifier"
          },
          {
            "name": "ref",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "main"
            },
            "description": "Branch, tag, or commit SHA (default HEAD)"
          },
          {
            "name": "path",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "engineering"
            },
            "description": "Filter commits by path"
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            },
            "description": "Page number (default 1)"
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "example": 20
            },
            "description": "Items per page (default 20, max 100)"
          }
        ],
        "responses": {
          "200": {
            "description": "Commits retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "commits",
                    "page",
                    "per_page",
                    "has_more"
                  ],
                  "properties": {
                    "commits": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "message",
                          "author_name",
                          "authored_date"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "abc123def456789abc123def456789abc123def4"
                          },
                          "message": {
                            "type": "string",
                            "example": "Update engineering process documentation"
                          },
                          "author_name": {
                            "type": "string",
                            "example": "Person A"
                          },
                          "authored_date": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-18T10:30:00Z"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer",
                      "example": 1
                    },
                    "per_page": {
                      "type": "integer",
                      "example": 20
                    },
                    "has_more": {
                      "type": "boolean",
                      "example": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/norms-repo/commits/{sha}": {
      "get": {
        "operationId": "getTeamNormsCommit",
        "summary": "Get team norms commit details",
        "description": "Returns detailed information for a specific commit in a team's norms repository.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of the team.\n\n**Caching:** Responses are cached for 30 seconds.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            },
            "description": "Team identifier"
          },
          {
            "name": "sha",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "abc123def456789abc123def456789abc123def4"
            },
            "description": "Commit SHA"
          }
        ],
        "responses": {
          "200": {
            "description": "Commit details retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "message",
                    "author_name",
                    "authored_date"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "abc123def456789abc123def456789abc123def4"
                    },
                    "message": {
                      "type": "string",
                      "example": "Update engineering process documentation"
                    },
                    "author_name": {
                      "type": "string",
                      "example": "Person A"
                    },
                    "authored_date": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "additions": {
                      "type": "integer",
                      "example": 15
                    },
                    "deletions": {
                      "type": "integer",
                      "example": 3
                    },
                    "files_changed": {
                      "type": "integer",
                      "example": 1
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Commit or team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/norms-repo/compare": {
      "get": {
        "operationId": "getTeamNormsCompare",
        "summary": "Compare team norms repository references",
        "description": "Returns the diff between two references in a team's norms repository.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of the team.\n\n**Caching:** Responses are cached for 30 seconds.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            },
            "description": "Team identifier"
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "main"
            },
            "description": "Base reference"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "staging"
            },
            "description": "Compare-to reference"
          }
        ],
        "responses": {
          "200": {
            "description": "Comparison retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "from",
                    "to"
                  ],
                  "properties": {
                    "from": {
                      "type": "string",
                      "example": "main"
                    },
                    "to": {
                      "type": "string",
                      "example": "staging"
                    },
                    "commits": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "abc123def456789abc123def456789abc123def4"
                          },
                          "message": {
                            "type": "string",
                            "example": "Update standards"
                          },
                          "author_name": {
                            "type": "string",
                            "example": "Person A"
                          },
                          "authored_date": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2025-12-18T10:30:00Z"
                          }
                        }
                      }
                    },
                    "additions": {
                      "type": "integer",
                      "example": 25
                    },
                    "deletions": {
                      "type": "integer",
                      "example": 5
                    },
                    "files_changed": {
                      "type": "integer",
                      "example": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team or references not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/context-repo-status": {
      "get": {
        "operationId": "getTeamContextRepoStatus",
        "summary": "Check team context repository status",
        "description": "Returns the status of the team's context (norms) repository.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of the team.\n\n**Status Values:**\n- `ready` - Context repo exists and is ready to use\n- `pending` - Context repo not yet created (auto-created during ox init)\n- `unavailable` - GitLab integration not configured\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            },
            "description": "Team identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Team context repo status retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ready",
                        "pending",
                        "unavailable"
                      ],
                      "example": "ready"
                    },
                    "repo_url": {
                      "type": "string",
                      "format": "uri",
                      "example": "http://localhost:8929/groups/team-abc123/projects/norms-repo"
                    },
                    "repo_id": {
                      "type": "integer",
                      "example": 43
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "message": {
                      "type": "string",
                      "example": "Team context repository not yet created"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid team_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/git/info": {
      "get": {
        "operationId": "getRepoGitInfo",
        "summary": "Get git checkout information",
        "description": "Returns non-sensitive git checkout information for debugging purposes.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of a team associated with the repository.\n\n**Security:** Intentionally excludes tokens and passwords.\n",
        "tags": [
          "Git"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Git info retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "server_url"
                  ],
                  "properties": {
                    "server_url": {
                      "type": "string",
                      "format": "uri",
                      "example": "http://localhost:8929"
                    },
                    "repo_url": {
                      "type": "string",
                      "format": "uri",
                      "example": "http://localhost:8929/groups/team-abc123/projects/team-repo"
                    },
                    "username": {
                      "type": "string",
                      "example": "person"
                    },
                    "group_path": {
                      "type": "string",
                      "example": "team-abc123"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "message": {
                      "type": "string",
                      "example": "git integration not configured"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of any team associated with this repository",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/uninstall": {
      "post": {
        "operationId": "initiateUninstall",
        "summary": "Initiate repository uninstall",
        "description": "Initiates an uninstall request for a repository, removing cloud resources while preserving data.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a team admin or owner.\n\n**Workflow:** Triggers a Temporal workflow that handles confirmation and cleanup.\n\n**Status:** Returns 202 Accepted - the workflow handles the rest asynchronously.\n\n**Confirmation:** User must confirm uninstall via POST /api/v1/repos/{repo_id}/uninstall/confirm\n",
        "tags": [
          "Repositories"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "example": "Project archived",
                    "description": "Optional reason for audit purposes"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Uninstall request accepted - workflow in progress",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id",
                    "status",
                    "status_url",
                    "expires_at"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "example": "pending"
                    },
                    "status_url": {
                      "type": "string",
                      "format": "uri",
                      "example": "https://web.example.com/repos/repo_01934f5a-8b9c-7def-b012-3456789abcde/uninstall"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-25T10:30:00Z"
                    },
                    "workflow_id": {
                      "type": "string",
                      "example": "uninstall-requested-repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id or request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a team admin or owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Uninstall already pending",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getUninstallStatus",
        "summary": "Get uninstall request status",
        "description": "Returns the current status of an uninstall request.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of the team associated with the repository.\n\n**Status Values:**\n- `pending` - Awaiting confirmation (includes confirmation_required field)\n- `confirmed` - Confirmed, cleanup in progress\n- `canceled` - Request was canceled\n- `expired` - Confirmation window expired\n- `completed` - Uninstall completed\n",
        "tags": [
          "Repositories"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Uninstall status retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id",
                    "status",
                    "initiated_by",
                    "initiated_at",
                    "expires_at"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "confirmed",
                        "canceled",
                        "expired",
                        "completed"
                      ],
                      "example": "pending"
                    },
                    "initiated_by": {
                      "type": "string",
                      "example": "user_2n3k4m5l6j7h8g9f"
                    },
                    "initiated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-25T10:30:00Z"
                    },
                    "confirmed_by": {
                      "type": "string",
                      "nullable": true,
                      "example": "user_2n3k4m5l6j7h8g9f"
                    },
                    "confirmed_at": {
                      "type": "string",
                      "nullable": true,
                      "format": "date-time",
                      "example": "2025-12-18T11:00:00Z"
                    },
                    "confirmation_required": {
                      "type": "string",
                      "description": "Text that must be typed to confirm (only when status is pending)",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "workflow_id": {
                      "type": "string",
                      "example": "uninstall-requested-repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of the associated team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository or uninstall request not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/uninstall/confirm": {
      "post": {
        "operationId": "confirmUninstall",
        "summary": "Confirm uninstall request",
        "description": "Confirms an uninstall request. User must type the repo ID to confirm.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a team admin or owner.\n\n**Confirmation:** The confirmation_text field must exactly match the repo_id.\n\n**Workflow:** Signals the Temporal workflow to proceed with uninstall.\n\n**Response:** Returns 202 Accepted - the workflow handles cleanup asynchronously.\n",
        "tags": [
          "Repositories"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirmation_text"
                ],
                "properties": {
                  "confirmation_text": {
                    "type": "string",
                    "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                    "description": "Must exactly match the repo_id"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Confirmation signal sent - workflow proceeding",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id",
                    "status"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "example": "confirming"
                    },
                    "initiated_by": {
                      "type": "string",
                      "example": "user_2n3k4m5l6j7h8g9f"
                    },
                    "initiated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-25T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id or confirmation_text does not match",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a team admin or owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository or uninstall request not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Uninstall request not pending or has expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/uninstall/cancel": {
      "post": {
        "operationId": "cancelUninstall",
        "summary": "Cancel uninstall request",
        "description": "Cancels a pending uninstall request.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a team admin or owner.\n\n**Workflow:** Signals the Temporal workflow to cancel the uninstall.\n\n**Response:** Returns 202 Accepted - the workflow handles state update asynchronously.\n",
        "tags": [
          "Repositories"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "responses": {
          "202": {
            "description": "Cancellation signal sent - workflow updating state",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id",
                    "status"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "example": "canceling"
                    },
                    "initiated_by": {
                      "type": "string",
                      "example": "user_2n3k4m5l6j7h8g9f"
                    },
                    "initiated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a team admin or owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository or uninstall request not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Uninstall request not pending or has expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/delete": {
      "post": {
        "operationId": "initiateDeletion",
        "summary": "Initiate repository deletion",
        "description": "Initiates a deletion request for a repository, permanently removing all data.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a team admin or owner.\n\n**Workflow:** Triggers a Temporal workflow that handles confirmation and cleanup.\n\n**Status:** Returns 202 Accepted - the workflow handles the rest asynchronously.\n\n**Confirmation:** User must confirm deletion via POST /api/v1/repos/{repo_id}/delete/confirm\n\n**Warning:** This operation is irreversible.\n",
        "tags": [
          "Repositories"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "example": "No longer needed",
                    "description": "Optional reason for audit purposes"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Deletion request accepted - workflow in progress",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id",
                    "status",
                    "status_url",
                    "expires_at"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "example": "pending"
                    },
                    "status_url": {
                      "type": "string",
                      "format": "uri",
                      "example": "https://web.example.com/repos/repo_01934f5a-8b9c-7def-b012-3456789abcde/delete"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-25T10:30:00Z"
                    },
                    "workflow_id": {
                      "type": "string",
                      "example": "deletion-requested-repo-repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id or request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a team admin or owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Deletion already pending",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getDeletionStatus",
        "summary": "Get deletion request status",
        "description": "Returns the current status of a deletion request.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a member of the team associated with the repository.\n\n**Status Values:**\n- `pending` - Awaiting confirmation\n- `confirmed` - Confirmed, deletion in progress\n- `canceled` - Request was canceled\n- `expired` - Confirmation window expired\n- `completed` - Deletion completed\n",
        "tags": [
          "Repositories"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Deletion status retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id",
                    "status",
                    "initiated_by",
                    "initiated_at",
                    "expires_at"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "confirmed",
                        "canceled",
                        "expired",
                        "completed"
                      ],
                      "example": "pending"
                    },
                    "initiated_by": {
                      "type": "string",
                      "example": "user_2n3k4m5l6j7h8g9f"
                    },
                    "initiated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-25T10:30:00Z"
                    },
                    "confirmed_by": {
                      "type": "string",
                      "nullable": true,
                      "example": "user_2n3k4m5l6j7h8g9f"
                    },
                    "confirmed_at": {
                      "type": "string",
                      "nullable": true,
                      "format": "date-time",
                      "example": "2025-12-18T11:00:00Z"
                    },
                    "canceled_by": {
                      "type": "string",
                      "nullable": true,
                      "example": "user_2n3k4m5l6j7h8g9f"
                    },
                    "canceled_at": {
                      "type": "string",
                      "nullable": true,
                      "format": "date-time",
                      "example": "2025-12-18T11:05:00Z"
                    },
                    "workflow_id": {
                      "type": "string",
                      "example": "deletion-requested-repo-repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a member of the associated team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository or deletion request not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/delete/confirm": {
      "post": {
        "operationId": "confirmDeletion",
        "summary": "Confirm deletion request",
        "description": "Confirms a deletion request. Permanently deletes the repository and all associated data.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a team admin or owner.\n\n**Workflow:** Signals the Temporal workflow to proceed with deletion.\n\n**Response:** Returns 202 Accepted - the workflow handles cleanup asynchronously.\n\n**Warning:** This operation is irreversible.\n",
        "tags": [
          "Repositories"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "responses": {
          "202": {
            "description": "Confirmation signal sent - deletion proceeding",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id",
                    "status"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "example": "confirming"
                    },
                    "initiated_by": {
                      "type": "string",
                      "example": "user_2n3k4m5l6j7h8g9f"
                    },
                    "initiated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-25T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a team admin or owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository or deletion request not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Deletion request not pending or has expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/delete/cancel": {
      "post": {
        "operationId": "cancelDeletion",
        "summary": "Cancel deletion request",
        "description": "Cancels a pending deletion request.\n\n**Authentication:** Required (bearer token)\n\n**Access Control:** User must be a team admin or owner.\n\n**Workflow:** Signals the Temporal workflow to cancel the deletion.\n\n**Response:** Returns 202 Accepted - the workflow handles state update asynchronously.\n",
        "tags": [
          "Repositories"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            },
            "description": "Repository identifier"
          }
        ],
        "responses": {
          "202": {
            "description": "Cancellation signal sent - workflow updating state",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "repo_id",
                    "team_id",
                    "status"
                  ],
                  "properties": {
                    "repo_id": {
                      "type": "string",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
                    },
                    "team_id": {
                      "type": "string",
                      "example": "team_abc123xyz"
                    },
                    "status": {
                      "type": "string",
                      "example": "canceling"
                    },
                    "initiated_by": {
                      "type": "string",
                      "example": "user_2n3k4m5l6j7h8g9f"
                    },
                    "initiated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-12-18T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid repo_id format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not a team admin or owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Repository or deletion request not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Deletion request not pending or has expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/photos": {
      "post": {
        "operationId": "requestRepoPhotoUploadURL",
        "summary": "Request upload URL for a photo",
        "description": "Generates a presigned URL for uploading a photo to a repository.\n\nThe returned URL can be used to directly upload an image file.\nAfter successful upload, call POST /api/v1/repos/{repo_id}/photos/{img_id}\nto create the photo metadata record.\n\nSupported image types: JPEG, PNG, GIF, WebP, SVG, HEIC, HEIF, TIFF\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "description": "Repository ID (repo_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "filename",
                  "content_type"
                ],
                "properties": {
                  "filename": {
                    "type": "string",
                    "description": "Original filename for the image",
                    "example": "whiteboard_diagram.png"
                  },
                  "content_type": {
                    "type": "string",
                    "description": "MIME type of the image",
                    "enum": [
                      "image/jpeg",
                      "image/png",
                      "image/gif",
                      "image/webp",
                      "image/svg+xml",
                      "image/heic",
                      "image/heif",
                      "image/tiff"
                    ],
                    "example": "image/png"
                  },
                  "size_bytes": {
                    "type": "integer",
                    "format": "int64",
                    "description": "File size in bytes (optional, for validation)",
                    "example": 1048576
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned upload URL generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "upload_url",
                    "image_id",
                    "expires_at",
                    "storage_key"
                  ],
                  "properties": {
                    "upload_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Presigned URL for uploading the image file",
                      "example": "https://storage.example.com/upload?signed=..."
                    },
                    "image_id": {
                      "type": "string",
                      "description": "Generated image ID for this photo",
                      "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                      "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Expiration time for the presigned URL (typically 1 hour)",
                      "example": "2025-12-18T17:30:00Z"
                    },
                    "storage_key": {
                      "type": "string",
                      "description": "Internal S3 storage key for the image",
                      "example": "repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png"
                    },
                    "max_size_bytes": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Maximum file size allowed for upload",
                      "example": 104857600
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_filename": {
                    "value": {
                      "success": false,
                      "error": "filename is required"
                    }
                  },
                  "invalid_content_type": {
                    "value": {
                      "success": false,
                      "error": "content_type must be a valid image type (image/jpeg, image/png, image/gif, image/webp)"
                    }
                  },
                  "invalid_repo_id": {
                    "value": {
                      "success": false,
                      "error": "invalid repo_id format"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listRepoPhotos",
        "summary": "List photos in a repository",
        "description": "Retrieves a paginated list of photos in a repository.\nSupports optional filtering by recording ID.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "description": "Repository ID (repo_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          },
          {
            "name": "recording_id",
            "in": "query",
            "required": false,
            "description": "Filter photos by recording ID",
            "schema": {
              "type": "string",
              "example": "rec_01934f5c-1234-7def"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of photos to return (default 50, max 100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "example": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of photos to skip for pagination (default 0)",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "example": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Photos retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "photos",
                    "pagination"
                  ],
                  "properties": {
                    "photos": {
                      "type": "array",
                      "items": {
                        "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1photos~1%7Bimg_id%7D/get/responses/200/content/application~1json/schema"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/PaginationMeta"
                    }
                  }
                },
                "examples": {
                  "success": {
                    "value": {
                      "photos": [
                        {
                          "id": "img_01934f5b-9d3e-7abc-a012-3456789abcde",
                          "repo_id": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                          "filename": "diagram.png",
                          "content_type": "image/png",
                          "size_bytes": 524288,
                          "width": 1920,
                          "height": 1080,
                          "url": "https://storage.example.com/repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png",
                          "created_at": "2025-12-18T16:30:00Z",
                          "updated_at": "2025-12-18T16:30:00Z",
                          "created_by": "user_abc123xyz"
                        }
                      ],
                      "pagination": {
                        "total": 42,
                        "limit": 20,
                        "offset": 0,
                        "hasMore": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/repos/{repo_id}/photos/{img_id}": {
      "post": {
        "operationId": "createRepoPhoto",
        "summary": "Create photo metadata after upload",
        "description": "Creates a photo metadata record after the image file has been uploaded\nvia the presigned URL from POST /api/v1/repos/{repo_id}/photos.\n\nThis endpoint finalizes the photo creation, allowing you to add metadata\nsuch as title, description, and metadata. If OCR is enabled, processing\nis triggered asynchronously.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "description": "Repository ID (repo_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          },
          {
            "name": "img_id",
            "in": "path",
            "required": true,
            "description": "Image ID returned from upload URL request (img_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "description": "Original filename (optional, uses request value if provided)",
                    "example": "whiteboard_design.png"
                  },
                  "content_type": {
                    "type": "string",
                    "description": "MIME type of the image",
                    "example": "image/png"
                  },
                  "size_bytes": {
                    "type": "integer",
                    "format": "int64",
                    "description": "File size in bytes",
                    "example": 1048576
                  },
                  "width": {
                    "type": "integer",
                    "description": "Image width in pixels",
                    "example": 1920
                  },
                  "height": {
                    "type": "integer",
                    "description": "Image height in pixels",
                    "example": 1080
                  },
                  "storage_key": {
                    "type": "string",
                    "description": "S3 storage key (from upload response)",
                    "example": "repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png"
                  },
                  "recording_id": {
                    "type": "string",
                    "description": "Associated recording ID if photo was captured during a recording",
                    "example": "rec_01934f5c-1234-7def"
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Capture timestamp (from EXIF or manual entry)",
                    "example": "2025-12-18T16:25:00Z"
                  },
                  "metadata": {
                    "type": "object",
                    "description": "Custom metadata (flexible key-value pairs)",
                    "additionalProperties": true,
                    "example": {
                      "category": "whiteboard",
                      "session": "design-review"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Photo metadata created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1photos~1%7Bimg_id%7D/get/responses/200/content/application~1json/schema"
                },
                "example": {
                  "id": "img_01934f5b-9d3e-7abc-a012-3456789abcde",
                  "repo_id": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                  "filename": "whiteboard_design.png",
                  "content_type": "image/png",
                  "size_bytes": 1048576,
                  "width": 1920,
                  "height": 1080,
                  "storage_key": "repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png",
                  "url": "https://storage.example.com/repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png",
                  "metadata": {
                    "category": "whiteboard",
                    "session": "design-review"
                  },
                  "created_by": "user_abc123xyz",
                  "created_at": "2025-12-18T16:30:00Z",
                  "updated_at": "2025-12-18T16:30:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or image ID format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_img_id": {
                    "value": {
                      "success": false,
                      "error": "invalid img_id format (expected img_<uuidv7>)"
                    }
                  },
                  "invalid_dimensions": {
                    "value": {
                      "success": false,
                      "error": "width and height must be greater than 0"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Photo already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getRepoPhoto",
        "summary": "Get photo details",
        "description": "Retrieves a photo by ID, including metadata, download URL, and OCR text\nif available.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "description": "Repository ID (repo_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          },
          {
            "name": "img_id",
            "in": "path",
            "required": true,
            "description": "Image ID (img_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Photo retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "content_type",
                    "size_bytes",
                    "width",
                    "height",
                    "url",
                    "created_at",
                    "updated_at",
                    "created_by"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Photo ID (img_<uuidv7>)",
                      "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                      "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
                    },
                    "repo_id": {
                      "type": "string",
                      "description": "Repository ID (if repo-scoped)",
                      "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                      "nullable": true
                    },
                    "team_id": {
                      "type": "string",
                      "description": "Team ID (if team-scoped)",
                      "example": "team_abc123xyz",
                      "nullable": true
                    },
                    "recording_id": {
                      "type": "string",
                      "description": "Associated recording ID if photo was captured during a recording",
                      "example": "rec_01934f5c-1234-7def",
                      "nullable": true
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Capture timestamp from EXIF or manual entry",
                      "example": "2025-12-18T16:25:00Z",
                      "nullable": true
                    },
                    "filename": {
                      "type": "string",
                      "description": "Original filename",
                      "example": "whiteboard_diagram.png"
                    },
                    "content_type": {
                      "type": "string",
                      "description": "MIME type of the image",
                      "enum": [
                        "image/jpeg",
                        "image/png",
                        "image/gif",
                        "image/webp",
                        "image/svg+xml",
                        "image/heic",
                        "image/heif",
                        "image/tiff"
                      ],
                      "example": "image/png"
                    },
                    "size_bytes": {
                      "type": "integer",
                      "format": "int64",
                      "description": "File size in bytes",
                      "example": 1048576
                    },
                    "width": {
                      "type": "integer",
                      "description": "Image width in pixels",
                      "example": 1920
                    },
                    "height": {
                      "type": "integer",
                      "description": "Image height in pixels",
                      "example": 1080
                    },
                    "storage_key": {
                      "type": "string",
                      "description": "Internal S3 storage key",
                      "example": "repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Download URL for the image",
                      "example": "https://storage.example.com/repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png"
                    },
                    "metadata": {
                      "type": "object",
                      "description": "Custom metadata and extracted content.\nMay include ocr_text, exif data, and other system-extracted fields.\n",
                      "additionalProperties": true,
                      "example": {
                        "category": "whiteboard",
                        "ocr_text": "System Architecture Components...",
                        "exif": {
                          "make": "Camera Manufacturer",
                          "model": "Camera Model",
                          "iso_speed": 400
                        }
                      }
                    },
                    "created_by": {
                      "type": "string",
                      "description": "User ID of the photo uploader",
                      "example": "user_abc123xyz"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Creation timestamp",
                      "example": "2025-12-18T16:30:00Z"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Last update timestamp",
                      "example": "2025-12-18T16:30:00Z"
                    }
                  }
                },
                "example": {
                  "id": "img_01934f5b-9d3e-7abc-a012-3456789abcde",
                  "repo_id": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                  "filename": "whiteboard_design.png",
                  "content_type": "image/png",
                  "size_bytes": 1048576,
                  "width": 1920,
                  "height": 1080,
                  "storage_key": "repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png",
                  "url": "https://storage.example.com/repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png",
                  "metadata": {
                    "category": "whiteboard",
                    "ocr_text": "System Architecture\\nComponents: API, Database, Cache"
                  },
                  "created_by": "user_abc123xyz",
                  "created_at": "2025-12-18T16:30:00Z",
                  "updated_at": "2025-12-18T16:30:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Photo not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateRepoPhoto",
        "summary": "Update photo metadata",
        "description": "Updates photo metadata such as filename, custom metadata, or recording association.\nPartial updates are supported - only provided fields are modified.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "description": "Repository ID (repo_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          },
          {
            "name": "img_id",
            "in": "path",
            "required": true,
            "description": "Image ID (img_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "description": "Updated filename",
                    "example": "architecture_diagram_v2.png"
                  },
                  "recording_id": {
                    "type": "string",
                    "description": "Associated recording ID",
                    "example": "rec_01934f5c-1234-7def"
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Updated capture timestamp",
                    "example": "2025-12-18T16:25:00Z"
                  },
                  "metadata": {
                    "type": "object",
                    "description": "Updated custom metadata (merged with existing)",
                    "additionalProperties": true,
                    "example": {
                      "category": "architecture",
                      "version": 2,
                      "status": "approved"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Photo metadata updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1photos~1%7Bimg_id%7D/get/responses/200/content/application~1json/schema"
                },
                "example": {
                  "id": "img_01934f5b-9d3e-7abc-a012-3456789abcde",
                  "repo_id": "repo_01934f5a-8b9c-7def-b012-3456789abcde",
                  "filename": "architecture_diagram_v2.png",
                  "content_type": "image/png",
                  "size_bytes": 1048576,
                  "width": 1920,
                  "height": 1080,
                  "storage_key": "repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png",
                  "url": "https://storage.example.com/repos/repo_01934f5a-8b9c-7def/img_01934f5b-9d3e-7abc.png",
                  "metadata": {
                    "category": "architecture",
                    "version": 2,
                    "status": "approved"
                  },
                  "created_by": "user_abc123xyz",
                  "created_at": "2025-12-18T16:30:00Z",
                  "updated_at": "2025-12-18T16:35:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Photo not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteRepoPhoto",
        "summary": "Delete a photo",
        "description": "Deletes a photo and its associated data from the repository.\nThis operation is permanent.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "repo_id",
            "in": "path",
            "required": true,
            "description": "Repository ID (repo_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^repo_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "repo_01934f5a-8b9c-7def-b012-3456789abcde"
            }
          },
          {
            "name": "img_id",
            "in": "path",
            "required": true,
            "description": "Image ID (img_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Photo deleted successfully (no content)"
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Photo not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/photos": {
      "post": {
        "operationId": "requestTeamPhotoUploadURL",
        "summary": "Request upload URL for a team photo",
        "description": "Generates a presigned URL for uploading a photo to a team.\n\nThe returned URL can be used to directly upload an image file.\nAfter successful upload, call POST /api/v1/teams/{team_id}/photos/{img_id}\nto create the photo metadata record.\n\nSupported image types: JPEG, PNG, GIF, WebP, SVG, HEIC, HEIF, TIFF\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "description": "Team ID",
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "filename",
                  "content_type"
                ],
                "properties": {
                  "filename": {
                    "type": "string",
                    "description": "Original filename for the image",
                    "example": "team_whiteboard.png"
                  },
                  "content_type": {
                    "type": "string",
                    "description": "MIME type of the image",
                    "enum": [
                      "image/jpeg",
                      "image/png",
                      "image/gif",
                      "image/webp",
                      "image/svg+xml",
                      "image/heic",
                      "image/heif",
                      "image/tiff"
                    ],
                    "example": "image/png"
                  },
                  "size_bytes": {
                    "type": "integer",
                    "format": "int64",
                    "description": "File size in bytes (optional, for validation)",
                    "example": 1048576
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned upload URL generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "upload_url",
                    "image_id",
                    "expires_at",
                    "storage_key"
                  ],
                  "properties": {
                    "upload_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Presigned URL for uploading the image file",
                      "example": "https://storage.example.com/upload?signed=..."
                    },
                    "image_id": {
                      "type": "string",
                      "description": "Generated image ID for this photo",
                      "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                      "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Expiration time for the presigned URL (typically 1 hour)",
                      "example": "2025-12-18T17:30:00Z"
                    },
                    "storage_key": {
                      "type": "string",
                      "description": "Internal S3 storage key for the image",
                      "example": "teams/team_abc123xyz/img_01934f5b-9d3e-7abc.png"
                    },
                    "max_size_bytes": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Maximum file size allowed for upload",
                      "example": 104857600
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_filename": {
                    "value": {
                      "success": false,
                      "error": "filename is required"
                    }
                  },
                  "invalid_content_type": {
                    "value": {
                      "success": false,
                      "error": "content_type must be a valid image type (image/jpeg, image/png, image/gif, image/webp)"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTeamPhotos",
        "summary": "List photos in a team",
        "description": "Retrieves a paginated list of photos in a team.\nSupports optional filtering by recording ID.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "description": "Team ID",
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "recording_id",
            "in": "query",
            "required": false,
            "description": "Filter photos by recording ID",
            "schema": {
              "type": "string",
              "example": "rec_01934f5c-1234-7def"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of photos to return (default 50, max 100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "example": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of photos to skip for pagination (default 0)",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "example": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Photos retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "photos",
                    "pagination"
                  ],
                  "properties": {
                    "photos": {
                      "type": "array",
                      "items": {
                        "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1photos~1%7Bimg_id%7D/get/responses/200/content/application~1json/schema"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/PaginationMeta"
                    }
                  }
                },
                "examples": {
                  "success": {
                    "value": {
                      "photos": [
                        {
                          "id": "img_01934f5b-9d3e-7abc-a012-3456789abcde",
                          "team_id": "team_abc123xyz",
                          "filename": "team_meeting_notes.png",
                          "content_type": "image/png",
                          "size_bytes": 524288,
                          "width": 1920,
                          "height": 1080,
                          "url": "https://storage.example.com/teams/team_abc123xyz/img_01934f5b-9d3e-7abc.png",
                          "created_at": "2025-12-18T16:30:00Z",
                          "updated_at": "2025-12-18T16:30:00Z",
                          "created_by": "user_abc123xyz"
                        }
                      ],
                      "pagination": {
                        "total": 15,
                        "limit": 20,
                        "offset": 0,
                        "hasMore": false
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams/{team_id}/photos/{img_id}": {
      "post": {
        "operationId": "createTeamPhoto",
        "summary": "Create team photo metadata after upload",
        "description": "Creates a photo metadata record after the image file has been uploaded\nvia the presigned URL from POST /api/v1/teams/{team_id}/photos.\n\nThis endpoint finalizes the photo creation, allowing you to add metadata\nsuch as title, description, and recording association. If OCR is enabled,\nprocessing is triggered asynchronously.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "description": "Team ID",
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "img_id",
            "in": "path",
            "required": true,
            "description": "Image ID returned from upload URL request (img_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "description": "Original filename (optional, uses request value if provided)",
                    "example": "meeting_notes.png"
                  },
                  "content_type": {
                    "type": "string",
                    "description": "MIME type of the image",
                    "example": "image/png"
                  },
                  "size_bytes": {
                    "type": "integer",
                    "format": "int64",
                    "description": "File size in bytes",
                    "example": 1048576
                  },
                  "width": {
                    "type": "integer",
                    "description": "Image width in pixels",
                    "example": 1920
                  },
                  "height": {
                    "type": "integer",
                    "description": "Image height in pixels",
                    "example": 1080
                  },
                  "storage_key": {
                    "type": "string",
                    "description": "S3 storage key (from upload response)",
                    "example": "teams/team_abc123xyz/img_01934f5b-9d3e-7abc.png"
                  },
                  "recording_id": {
                    "type": "string",
                    "description": "Associated recording ID if photo was captured during a recording",
                    "example": "rec_01934f5c-1234-7def"
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Capture timestamp (from EXIF or manual entry)",
                    "example": "2025-12-18T16:25:00Z"
                  },
                  "metadata": {
                    "type": "object",
                    "description": "Custom metadata (flexible key-value pairs)",
                    "additionalProperties": true,
                    "example": {
                      "meeting_type": "standup",
                      "project": "platform-redesign"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Photo metadata created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1photos~1%7Bimg_id%7D/get/responses/200/content/application~1json/schema"
                },
                "example": {
                  "id": "img_01934f5b-9d3e-7abc-a012-3456789abcde",
                  "team_id": "team_abc123xyz",
                  "filename": "meeting_notes.png",
                  "content_type": "image/png",
                  "size_bytes": 1048576,
                  "width": 1920,
                  "height": 1080,
                  "storage_key": "teams/team_abc123xyz/img_01934f5b-9d3e-7abc.png",
                  "url": "https://storage.example.com/teams/team_abc123xyz/img_01934f5b-9d3e-7abc.png",
                  "metadata": {
                    "meeting_type": "standup",
                    "project": "platform-redesign"
                  },
                  "created_by": "user_abc123xyz",
                  "created_at": "2025-12-18T16:30:00Z",
                  "updated_at": "2025-12-18T16:30:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or image ID format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_img_id": {
                    "value": {
                      "success": false,
                      "error": "invalid img_id format (expected img_<uuidv7>)"
                    }
                  },
                  "invalid_dimensions": {
                    "value": {
                      "success": false,
                      "error": "width and height must be greater than 0"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Photo already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getTeamPhoto",
        "summary": "Get team photo details",
        "description": "Retrieves a team photo by ID, including metadata, download URL, and OCR text\nif available.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "description": "Team ID",
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "img_id",
            "in": "path",
            "required": true,
            "description": "Image ID (img_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Photo retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1photos~1%7Bimg_id%7D/get/responses/200/content/application~1json/schema"
                },
                "example": {
                  "id": "img_01934f5b-9d3e-7abc-a012-3456789abcde",
                  "team_id": "team_abc123xyz",
                  "filename": "meeting_notes.png",
                  "content_type": "image/png",
                  "size_bytes": 1048576,
                  "width": 1920,
                  "height": 1080,
                  "storage_key": "teams/team_abc123xyz/img_01934f5b-9d3e-7abc.png",
                  "url": "https://storage.example.com/teams/team_abc123xyz/img_01934f5b-9d3e-7abc.png",
                  "metadata": {
                    "meeting_type": "standup",
                    "ocr_text": "Action Items: Review API design, Test payment flow, Deploy v2.0"
                  },
                  "created_by": "user_abc123xyz",
                  "created_at": "2025-12-18T16:30:00Z",
                  "updated_at": "2025-12-18T16:30:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Photo not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateTeamPhoto",
        "summary": "Update team photo metadata",
        "description": "Updates team photo metadata such as filename, custom metadata, or recording association.\nPartial updates are supported - only provided fields are modified.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "description": "Team ID",
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "img_id",
            "in": "path",
            "required": true,
            "description": "Image ID (img_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "description": "Updated filename",
                    "example": "standup_dec18_final.png"
                  },
                  "recording_id": {
                    "type": "string",
                    "description": "Associated recording ID",
                    "example": "rec_01934f5c-1234-7def"
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Updated capture timestamp",
                    "example": "2025-12-18T10:30:00Z"
                  },
                  "metadata": {
                    "type": "object",
                    "description": "Updated custom metadata (merged with existing)",
                    "additionalProperties": true,
                    "example": {
                      "meeting_type": "standup",
                      "status": "completed",
                      "attendees": 5
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Photo metadata updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1api~1v1~1repos~1%7Brepo_id%7D~1photos~1%7Bimg_id%7D/get/responses/200/content/application~1json/schema"
                },
                "example": {
                  "id": "img_01934f5b-9d3e-7abc-a012-3456789abcde",
                  "team_id": "team_abc123xyz",
                  "filename": "standup_dec18_final.png",
                  "content_type": "image/png",
                  "size_bytes": 1048576,
                  "width": 1920,
                  "height": 1080,
                  "storage_key": "teams/team_abc123xyz/img_01934f5b-9d3e-7abc.png",
                  "url": "https://storage.example.com/teams/team_abc123xyz/img_01934f5b-9d3e-7abc.png",
                  "metadata": {
                    "meeting_type": "standup",
                    "status": "completed",
                    "attendees": 5
                  },
                  "created_by": "user_abc123xyz",
                  "created_at": "2025-12-18T16:30:00Z",
                  "updated_at": "2025-12-18T16:35:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Photo not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTeamPhoto",
        "summary": "Delete a team photo",
        "description": "Deletes a team photo and its associated data.\nThis operation is permanent.\n",
        "tags": [
          "Photos"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "team_id",
            "in": "path",
            "required": true,
            "description": "Team ID",
            "schema": {
              "type": "string",
              "example": "team_abc123xyz"
            }
          },
          {
            "name": "img_id",
            "in": "path",
            "required": true,
            "description": "Image ID (img_<uuidv7>)",
            "schema": {
              "type": "string",
              "pattern": "^img_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
              "example": "img_01934f5b-9d3e-7abc-a012-3456789abcde"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Photo deleted successfully (no content)"
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Photo not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "HealthResponse": {
        "type": "object",
        "description": "Response from the `/live` health endpoint confirming the service is running.",
        "required": [
          "status",
          "timestamp"
        ],
        "properties": {
          "status": {
            "type": "string",
            "description": "Service status. Returns `ok` when the service process is alive and accepting connections.",
            "example": "ok"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "UTC timestamp of when the health check was performed. RFC 3339 format.",
            "example": "2025-12-03T10:30:00Z"
          }
        }
      },
      "ReadyResponse": {
        "type": "object",
        "description": "Response from the `/ready` endpoint confirming all dependencies are available.",
        "required": [
          "ready",
          "timestamp",
          "checks"
        ],
        "properties": {
          "ready": {
            "type": "boolean",
            "description": "`true` when all dependency checks pass. `false` if any check fails — the service should not receive traffic.",
            "example": true
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "UTC timestamp of when the readiness check was performed.",
            "example": "2025-12-03T10:30:00Z"
          },
          "checks": {
            "type": "object",
            "description": "Individual dependency check results.",
            "required": [
              "database"
            ],
            "properties": {
              "database": {
                "type": "string",
                "description": "PostgreSQL connection status. `ok` indicates a successful ping to the database.",
                "example": "ok"
              }
            }
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Standard error response returned by all endpoints on failure.",
        "required": [
          "success",
          "error"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Always `false` for error responses.",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "string",
            "description": "Human-readable error message describing what went wrong. Do not parse this programmatically — use HTTP status codes for control flow.",
            "example": "Invalid request parameters"
          }
        }
      },
      "SuccessResponse": {
        "type": "object",
        "description": "Generic success wrapper. Most endpoints return more specific response types, but this serves as the base shape.",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Always `true` for successful responses.",
            "enum": [
              true
            ]
          },
          "data": {
            "type": "object",
            "description": "Response payload. Shape varies by endpoint — see individual endpoint documentation."
          }
        }
      },
      "User": {
        "type": "object",
        "description": "Core user identity returned in session lookups and team membership responses.",
        "required": [
          "id",
          "email",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique user identifier. Format: `usr_<cuid2>` (10 character suffix).",
            "example": "user_2n3k4m5l6j7h8g9f"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Primary email address associated with the account.",
            "example": "user@example.com"
          },
          "name": {
            "type": "string",
            "description": "Display name. May be set by the user or populated from the OAuth provider.",
            "example": "John Doe"
          }
        }
      },
      "Session": {
        "type": "object",
        "description": "Active session metadata. Sessions are issued by Better Auth and validated by api-go on each request.",
        "required": [
          "id",
          "expiresAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique session identifier issued by Better Auth.",
            "example": "session_1a2b3c4d5e6f7g8h"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "UTC timestamp when this session expires. After expiration, the client must re-authenticate.",
            "example": "2025-12-10T10:30:00Z"
          }
        }
      },
      "SessionResponse": {
        "type": "object",
        "description": "Combined session and user data returned by `/api/v1/auth/session`. Use this to bootstrap the client with identity and session state.",
        "required": [
          "session",
          "user"
        ],
        "properties": {
          "session": {
            "$ref": "#/components/schemas/Session",
            "description": "The active session."
          },
          "user": {
            "$ref": "#/components/schemas/User",
            "description": "The authenticated user."
          }
        }
      },
      "NotificationDTO": {
        "type": "object",
        "description": "A user notification. Notifications are created by workflows, recordings, and system events, and delivered via polling or SSE streaming.",
        "required": [
          "id",
          "userId",
          "agentId",
          "type",
          "priority",
          "title",
          "message",
          "read",
          "timestamp",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique notification identifier. Format: `notif_<cuid2>`.",
            "example": "notif_9h8g7f6e5d4c3b2a"
          },
          "userId": {
            "type": "string",
            "description": "The recipient user's ID.",
            "example": "user_2n3k4m5l6j7h8g9f"
          },
          "agentId": {
            "type": "string",
            "description": "ID of the agent or workflow that created this notification.",
            "example": "agent_5k6l7m8n9o0p1q2r"
          },
          "agentName": {
            "type": "string",
            "nullable": true,
            "description": "Display name of the originating agent. `null` for system-generated notifications.",
            "example": "AI Assistant"
          },
          "type": {
            "type": "string",
            "description": "Notification category. Common values: `info`, `warning`, `error`, `success`.",
            "example": "info"
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "urgent"
            ],
            "description": "Delivery priority. `urgent` notifications bypass quiet hours and deliver immediately.",
            "example": "medium"
          },
          "title": {
            "type": "string",
            "description": "Short notification headline displayed in the notification list.",
            "example": "Task completed"
          },
          "message": {
            "type": "string",
            "description": "Full notification body. May contain markdown formatting.",
            "example": "Your task has been successfully completed"
          },
          "read": {
            "type": "boolean",
            "description": "`true` once the user has viewed or dismissed the notification.",
            "example": false
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "description": "Arbitrary key-value data attached by the originating workflow. Use for deep-linking, action buttons, or context.",
            "additionalProperties": true
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When the notification was created. UTC, RFC 3339.",
            "example": "2025-12-03T10:30:00Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Last modification time. Updates when read status changes.",
            "example": "2025-12-03T10:30:00Z"
          }
        }
      },
      "PaginationMeta": {
        "type": "object",
        "description": "Pagination metadata included in all list responses. Use `offset + limit` for the next page; stop when `hasMore` is `false`.",
        "required": [
          "total",
          "limit",
          "offset",
          "hasMore"
        ],
        "properties": {
          "total": {
            "type": "integer",
            "description": "Total number of records matching the query (ignoring limit/offset).",
            "example": 100
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of records returned in this page. Matches the `limit` query parameter.",
            "example": 20
          },
          "offset": {
            "type": "integer",
            "description": "Number of records skipped. Matches the `offset` query parameter.",
            "example": 0
          },
          "hasMore": {
            "type": "boolean",
            "description": "`true` if more records exist beyond this page. When `false`, this is the last page.",
            "example": true
          }
        }
      },
      "CreateEnvironmentResponse": {
        "type": "object",
        "description": "Response after creating a new environment for a repository.",
        "required": [
          "id",
          "owner"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique environment identifier.",
            "example": "env_3c4d5e6f7g8h9i0j"
          },
          "owner": {
            "type": "string",
            "description": "User ID of the environment owner.",
            "example": "user_2n3k4m5l6j7h8g9f"
          }
        }
      },
      "InitRunResponse": {
        "type": "object",
        "description": "Response after initializing a new execution run.",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique run identifier. Use this to track run status and retrieve results.",
            "example": "run_7g8h9i0j1k2l3m4n"
          }
        }
      },
      "ChatMessage": {
        "type": "object",
        "description": "A single message in a chat completion conversation. Follows the OpenAI chat format.",
        "required": [
          "role",
          "content"
        ],
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "system",
              "user",
              "assistant"
            ],
            "description": "The role of the message author. `system` sets behavior, `user` provides input, `assistant` contains model responses.",
            "example": "user"
          },
          "content": {
            "type": "string",
            "description": "The message text content.",
            "example": "Hello, how can I help you today?"
          }
        }
      },
      "ChatCompletionRequest": {
        "type": "object",
        "description": "Request body for the OpenAI-compatible chat completion endpoint. Supports streaming and temperature control.",
        "required": [
          "model",
          "messages"
        ],
        "properties": {
          "model": {
            "type": "string",
            "description": "Model identifier to use for completion. Available models depend on server configuration.",
            "example": "gpt-4"
          },
          "messages": {
            "type": "array",
            "description": "Conversation history. Must contain at least one message.",
            "items": {
              "$ref": "#/components/schemas/ChatMessage"
            }
          },
          "stream": {
            "type": "boolean",
            "nullable": true,
            "description": "When `true`, the response is streamed as Server-Sent Events. Each event contains a partial response delta. Default: `false`.",
            "example": false
          },
          "temperature": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "minimum": 0,
            "maximum": 2,
            "description": "Sampling temperature between 0 and 2. Lower values produce more focused output; higher values increase randomness. Default varies by model.",
            "example": 0.7
          },
          "max_tokens": {
            "type": "integer",
            "nullable": true,
            "description": "Maximum number of tokens to generate. `null` uses the model's default limit.",
            "example": 1000
          }
        }
      },
      "ChatCompletionResponse": {
        "type": "object",
        "description": "Chat completion response following the OpenAI format. Contains one or more generated choices with usage statistics.",
        "required": [
          "id",
          "object",
          "created",
          "model",
          "choices",
          "usage"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique completion identifier.",
            "example": "chatcmpl-123"
          },
          "object": {
            "type": "string",
            "description": "Object type. Always `chat.completion` for non-streamed responses.",
            "example": "chat.completion"
          },
          "created": {
            "type": "integer",
            "format": "int64",
            "description": "Unix timestamp (seconds) when the completion was generated.",
            "example": 1677652288
          },
          "model": {
            "type": "string",
            "description": "The model that generated the completion. May differ from the requested model if routing occurred.",
            "example": "gpt-4"
          },
          "choices": {
            "type": "array",
            "description": "Generated completion choices. Standard requests return a single choice.",
            "items": {
              "type": "object",
              "required": [
                "index",
                "message",
                "finish_reason"
              ],
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "Zero-based index of this choice.",
                  "example": 0
                },
                "message": {
                  "$ref": "#/components/schemas/ChatMessage",
                  "description": "The generated message."
                },
                "finish_reason": {
                  "type": "string",
                  "description": "Why generation stopped. `stop` means natural completion; `length` means max_tokens was reached.",
                  "example": "stop"
                }
              }
            }
          },
          "usage": {
            "type": "object",
            "description": "Token usage statistics for this completion.",
            "required": [
              "prompt_tokens",
              "completion_tokens",
              "total_tokens"
            ],
            "properties": {
              "prompt_tokens": {
                "type": "integer",
                "description": "Number of tokens in the prompt (input).",
                "example": 10
              },
              "completion_tokens": {
                "type": "integer",
                "description": "Number of tokens in the generated completion (output).",
                "example": 20
              },
              "total_tokens": {
                "type": "integer",
                "description": "Sum of prompt and completion tokens. Use for cost tracking.",
                "example": 30
              }
            }
          }
        }
      },
      "OpenAIError": {
        "type": "object",
        "description": "Error response following the OpenAI error format. Returned by LLM endpoints.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "description": "Error details object.",
            "required": [
              "message",
              "type"
            ],
            "properties": {
              "message": {
                "type": "string",
                "description": "Human-readable error description.",
                "example": "Invalid API key"
              },
              "type": {
                "type": "string",
                "description": "Error category. Common values: `invalid_request_error`, `authentication_error`, `rate_limit_error`.",
                "example": "invalid_request_error"
              },
              "code": {
                "type": "string",
                "nullable": true,
                "description": "Machine-readable error code for programmatic handling. `null` when no specific code applies.",
                "example": "invalid_api_key"
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT token obtained from the auth service (/api/auth/token).\nToken is validated using JWKS from the auth service.\nRequired claims: sub (user_id), email, name, tier.\n"
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Health",
      "description": "Service health and readiness endpoints for orchestration platforms. The `/live` endpoint returns service liveness; `/ready` confirms database connectivity and dependency availability.\n"
    },
    {
      "name": "Logs",
      "description": "Collect frontend application logs for centralized error tracking and debugging. Accepts batches of structured log entries from web and CLI clients with severity levels and metadata.\n"
    },
    {
      "name": "Auth",
      "description": "Session management and token lifecycle. Validates JWT tokens issued by Better Auth, returns session details and user identity. Used by both web app and CLI for authentication verification.\n"
    },
    {
      "name": "Users",
      "description": "Manage user profiles, preferences, API keys, and account settings. Preferences control notification delivery, theme, and feature opt-ins. API keys authenticate CLI and programmatic access.\n"
    },
    {
      "name": "Teams",
      "description": "Create and manage teams with hierarchical membership (owner, admin, member). Handles invitations via email with role assignment, team-wide conventions and norms, and child-team relationships. Teams are the primary organizational unit in SageOx.\n"
    },
    {
      "name": "Notifications",
      "description": "Read, manage, and stream real-time notifications. Supports SSE (Server-Sent Events) for live delivery, bulk operations (mark read, delete), and preference-based filtering. Notifications originate from workflows, recordings, and system events.\n"
    },
    {
      "name": "Recordings",
      "description": "Full lifecycle management for discussion recordings: chunked upload, transcription, speaker identification, AI-generated summaries, decisions, and action items. Recordings feed into the repository Ledger. Supports both audio upload and real-time recording sessions via Temporal workflows.\n"
    },
    {
      "name": "Git",
      "description": "Browse repository files, view commits, compare branches, and manage the Ledger. The Ledger stores historical context (decisions, discussions, AI-generated summaries) as version-controlled files in a GitLab-backed repository. Also handles repository uninstall and permanent deletion workflows.\n"
    },
    {
      "name": "Photos",
      "description": "Upload and manage photos with automatic OCR text extraction. Photos can be scoped to a repository (linked to recordings/discussions) or a team (shared resources). Uses presigned URLs for direct-to-storage uploads.\n"
    },
    {
      "name": "CLI",
      "description": "Integration endpoints for the `ox` CLI tool. Includes device flow authentication (code request → polling → token exchange), server-side diagnostics, repository initialization, and friction event tracking for UX telemetry.\n"
    },
    {
      "name": "Public",
      "description": "Unauthenticated endpoints for public-facing data. Returns team profiles, public recording metadata, shared conventions, and repository status without requiring authentication. Rate limited per IP.\n"
    },
    {
      "name": "Runs",
      "description": "Track and manage execution runs for agents and workflows. Each run captures start time, status, configuration, and output artifacts. Runs are associated with repositories and provide audit trails for automated operations.\n"
    },
    {
      "name": "LLM",
      "description": "OpenAI-compatible chat completion endpoints. Proxies requests to configured LLM providers (Bedrock, OpenAI) with model routing, token usage tracking, and streaming support. Follows the OpenAI `/v1/chat/completions` format.\n"
    },
    {
      "name": "Repository",
      "description": "Repository initialization and merge operations. `initRepo` creates or reconnects a repository with SageOx (idempotent). `mergeRepos` combines ledger data when repositories are merged.\n"
    },
    {
      "name": "Guidance",
      "description": "AI-generated guidance content and statistics. Provides contextual recommendations, best practices, and insights derived from team context and recording analysis.\n"
    },
    {
      "name": "Config",
      "description": "Feature flags and application configuration. Returns client-relevant feature toggles and runtime settings. Feature flags follow the `FEATURE_` prefix convention.\n"
    },
    {
      "name": "Admin",
      "description": "Administrative analytics, session management, and system operations. Includes active session counts, user analytics, and management endpoints restricted to admin roles.\n"
    },
    {
      "name": "AgentX",
      "description": "Multi-tenant telemetry platform for CLI tools and AI agents. Register applications,\ningest events via API key authentication, and query analytics through the dashboard API.\n\n**Two authentication models:**\n- **Capture endpoint** (`POST /agentx/capture`): API key (`axk_...`) in `Authorization: Bearer` header. Designed for embedding in open-source CLIs.\n- **Dashboard + CRUD**: JWT authentication with team membership verification per app.\n\n**Key concepts:**\n- **Events** are the core data unit — named, timestamped, with arbitrary JSONB properties\n- **`distinct_id`** identifies a device/machine (SDK-generated UUID, not PII)\n- **`$user_id`** (optional, in properties) correlates events to a logical user\n- **Friction events** follow a convention: `friction.*` event names with `kind`, `actor`, `command` properties\n"
    }
  ]
}