openapi: 3.0.0 info: title: Image Factory - Build Execution API description: Real-time build execution and monitoring API with WebSocket support version: 1.0.0 contact: name: API Support email: support@imagefactory.io license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html servers: - url: http://localhost:8080/api/v1 description: Local development server - url: https://api.imagefactory.io/api/v1 description: Production server security: - BearerAuth: [] tags: - name: Builds description: Build execution and management endpoints - name: Build Logs description: Build log retrieval and real-time streaming - name: Build Status description: Build status and progress monitoring paths: /builds: post: tags: - Builds summary: Create a new build description: | Creates a new build for a project. The request must include a valid project ID and Git reference (branch, tag, or commit). **Permissions Required:** `build:create` operationId: createBuild requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateBuildRequest' examples: basic: summary: Basic build request value: project_id: 550e8400-e29b-41d4-a716-446655440000 git_branch: main with_commit: summary: Build specific commit value: project_id: 550e8400-e29b-41d4-a716-446655440000 git_branch: feature/api git_commit: abc123def456 responses: '201': description: Build created successfully content: application/json: schema: $ref: '#/components/schemas/Build' example: id: 660e8400-e29b-41d4-a716-446655440001 project_id: 550e8400-e29b-41d4-a716-446655440000 build_number: 42 git_branch: main status: queued created_at: "2024-01-15T10:30:00Z" updated_at: "2024-01-15T10:30:00Z" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' '500': $ref: '#/components/responses/InternalServerError' get: tags: - Builds summary: List all builds description: | Retrieves a paginated list of builds for the current tenant. **Permissions Required:** `build:list` operationId: listBuilds parameters: - name: page in: query description: Page number (1-indexed) schema: type: integer default: 1 minimum: 1 - name: limit in: query description: Number of builds per page schema: type: integer default: 20 minimum: 1 maximum: 100 - name: status in: query description: Filter by build status schema: type: string enum: - queued - in_progress - success - failed - cancelled - name: project_id in: query description: Filter by project ID schema: type: string format: uuid - name: sort_by in: query description: Sort field schema: type: string enum: - created_at - updated_at - build_number default: created_at - name: sort_order in: query description: Sort order schema: type: string enum: - asc - desc default: desc responses: '200': description: List of builds content: application/json: schema: $ref: '#/components/schemas/BuildList' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalServerError' /builds/{id}: get: tags: - Builds summary: Get build details description: | Retrieves detailed information about a specific build. **Permissions Required:** `build:read` operationId: getBuild parameters: - name: id in: path required: true description: Build ID (UUID) schema: type: string format: uuid responses: '200': description: Build details content: application/json: schema: $ref: '#/components/schemas/Build' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' delete: tags: - Builds summary: Delete a build description: | Deletes a build and its associated resources. **Permissions Required:** `build:delete` **Note:** Currently not implemented (501 Not Implemented) operationId: deleteBuild parameters: - name: id in: path required: true description: Build ID (UUID) schema: type: string format: uuid responses: '204': description: Build deleted successfully '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '501': description: Not implemented content: application/json: schema: $ref: '#/components/schemas/Error' '500': $ref: '#/components/responses/InternalServerError' /builds/{id}/start: post: tags: - Builds summary: Start a build description: | Transitions a build from 'queued' to 'in_progress' status. **Permissions Required:** `build:create` operationId: startBuild parameters: - name: id in: path required: true description: Build ID (UUID) schema: type: string format: uuid responses: '200': description: Build started successfully content: application/json: schema: $ref: '#/components/schemas/Build' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': description: Build cannot be started from current status content: application/json: schema: $ref: '#/components/schemas/Error' '500': $ref: '#/components/responses/InternalServerError' /builds/{id}/cancel: post: tags: - Builds summary: Cancel a build description: | Cancels an in-progress build. The build must be in 'in_progress' status. **Permissions Required:** `build:cancel` operationId: cancelBuild parameters: - name: id in: path required: true description: Build ID (UUID) schema: type: string format: uuid requestBody: content: application/json: schema: type: object properties: reason: type: string description: Reason for cancellation example: "User requested cancellation" responses: '200': description: Build cancelled successfully content: application/json: schema: $ref: '#/components/schemas/Build' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': description: Build cannot be cancelled from current status content: application/json: schema: $ref: '#/components/schemas/Error' '500': $ref: '#/components/responses/InternalServerError' /builds/{id}/retry: post: tags: - Builds summary: Retry a failed build description: | Creates a new build with the same configuration as a failed build. **Permissions Required:** `build:create` operationId: retryBuild parameters: - name: id in: path required: true description: Build ID (UUID) of the failed build schema: type: string format: uuid responses: '200': description: New build created for retry content: application/json: schema: $ref: '#/components/schemas/Build' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': description: Build cannot be retried from current status content: application/json: schema: $ref: '#/components/schemas/Error' '500': $ref: '#/components/responses/InternalServerError' /builds/{id}/status: get: tags: - Build Status summary: Get build status description: | Retrieves current status and progress information for a build. **Permissions Required:** `build:read` operationId: getBuildStatus parameters: - name: id in: path required: true description: Build ID (UUID) schema: type: string format: uuid responses: '200': description: Build status content: application/json: schema: $ref: '#/components/schemas/BuildStatus' example: build_id: 660e8400-e29b-41d4-a716-446655440001 status: in_progress progress: current_step: 5 total_steps: 10 percentage: 50 started_at: "2024-01-15T10:35:00Z" estimated_completion: "2024-01-15T11:05:00Z" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' /builds/{id}/logs: get: tags: - Build Logs summary: Get build logs description: | Retrieves complete build logs for a finished build. **Permissions Required:** `build:read` operationId: getBuildLogs parameters: - name: id in: path required: true description: Build ID (UUID) schema: type: string format: uuid - name: offset in: query description: Line offset for pagination schema: type: integer default: 0 minimum: 0 - name: limit in: query description: Maximum lines to return schema: type: integer default: 100 minimum: 1 maximum: 1000 responses: '200': description: Build logs content: application/json: schema: $ref: '#/components/schemas/BuildLogs' example: build_id: 660e8400-e29b-41d4-a716-446655440001 logs: - timestamp: "2024-01-15T10:35:00Z" level: INFO message: "Build started" - timestamp: "2024-01-15T10:36:00Z" level: INFO message: "Pulling base image..." total_lines: 245 offset: 0 limit: 100 '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' /builds/{id}/logs/stream: get: tags: - Build Logs summary: Stream build logs (WebSocket) description: | Opens a WebSocket connection to stream real-time build logs. **Upgrade:** This endpoint requires HTTP upgrade to WebSocket **Permissions Required:** `build:read` **WebSocket Message Format:** ```json { "build_id": "660e8400-e29b-41d4-a716-446655440001", "timestamp": "2024-01-15T10:35:00Z", "level": "INFO|WARN|ERROR|DEBUG", "message": "Log message content", "metadata": { "step": "build", "container": "builder" } } ``` operationId: streamBuildLogs parameters: - name: id in: path required: true description: Build ID (UUID) schema: type: string format: uuid responses: '101': description: WebSocket upgrade accepted '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' components: schemas: Build: type: object description: Build execution resource required: - id - project_id - build_number - status - created_at - updated_at properties: id: type: string format: uuid description: Unique build identifier project_id: type: string format: uuid description: Associated project identifier build_number: type: integer description: Sequential build number within project minimum: 0 git_branch: type: string nullable: true description: Git branch name example: "main" git_commit: type: string nullable: true description: Git commit hash example: "abc123def456..." git_author_name: type: string nullable: true description: Git commit author name git_author_email: type: string nullable: true format: email description: Git commit author email status: type: string enum: - queued - in_progress - success - failed - cancelled description: Current build status error_message: type: string nullable: true description: Error message if build failed started_at: type: string format: date-time nullable: true description: Build start timestamp completed_at: type: string format: date-time nullable: true description: Build completion timestamp created_at: type: string format: date-time description: Resource creation timestamp updated_at: type: string format: date-time description: Last update timestamp CreateBuildRequest: type: object required: - project_id - git_branch properties: project_id: type: string format: uuid description: Project ID git_branch: type: string description: Git branch to build minLength: 1 maxLength: 255 git_commit: type: string nullable: true description: Optional specific commit hash minLength: 7 maxLength: 40 build_args: type: object nullable: true description: Build configuration arguments additionalProperties: type: string BuildList: type: object properties: builds: type: array items: $ref: '#/components/schemas/Build' total_count: type: integer description: Total number of builds page: type: integer description: Current page number limit: type: integer description: Items per page has_more: type: boolean description: Whether more pages exist BuildStatus: type: object description: Build status and progress information properties: build_id: type: string format: uuid status: type: string enum: - queued - in_progress - success - failed - cancelled progress: type: object nullable: true properties: current_step: type: integer minimum: 0 total_steps: type: integer minimum: 0 percentage: type: number minimum: 0 maximum: 100 started_at: type: string format: date-time nullable: true estimated_completion: type: string format: date-time nullable: true error: type: string nullable: true BuildLogs: type: object description: Build logs response properties: build_id: type: string format: uuid logs: type: array items: $ref: '#/components/schemas/LogEntry' total_lines: type: integer description: Total number of log lines minimum: 0 offset: type: integer description: Current offset minimum: 0 limit: type: integer description: Requested limit minimum: 1 LogEntry: type: object description: Single log entry required: - timestamp - level - message properties: timestamp: type: string format: date-time description: Log entry timestamp level: type: string enum: - DEBUG - INFO - WARN - ERROR description: Log level message: type: string description: Log message metadata: type: object nullable: true description: Additional metadata additionalProperties: type: string Error: type: object required: - error - code - timestamp properties: error: type: string description: Error message code: type: string description: Error code enum: - INVALID_REQUEST - UNAUTHORIZED - FORBIDDEN - NOT_FOUND - CONFLICT - INTERNAL_SERVER_ERROR timestamp: type: string format: date-time trace_id: type: string nullable: true description: Request trace ID for debugging details: type: object nullable: true description: Additional error details additionalProperties: type: string responses: BadRequest: description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' example: error: "Invalid request body" code: "INVALID_REQUEST" timestamp: "2024-01-15T10:30:00Z" Unauthorized: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' example: error: "Missing or invalid authentication token" code: "UNAUTHORIZED" timestamp: "2024-01-15T10:30:00Z" Forbidden: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error' example: error: "You do not have permission to access this resource" code: "FORBIDDEN" timestamp: "2024-01-15T10:30:00Z" NotFound: description: Not found content: application/json: schema: $ref: '#/components/schemas/Error' example: error: "Build not found" code: "NOT_FOUND" timestamp: "2024-01-15T10:30:00Z" Conflict: description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error' example: error: "Build already exists" code: "CONFLICT" timestamp: "2024-01-15T10:30:00Z" InternalServerError: description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: error: "Internal server error" code: "INTERNAL_SERVER_ERROR" timestamp: "2024-01-15T10:30:00Z" trace_id: "abc123def456" securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: | JWT token obtained from `/api/v1/auth/login` endpoint. Format: `Authorization: Bearer `