{
  "openapi": "3.1.0",
  "info": {
    "title": "Phorge HTTP API",
    "version": "1.0.0",
    "summary": "Clone-free Git repository API for coding agents.",
    "description": "Phorge gives coding agents a clone-free repository API while preserving standard Git over HTTPS. Every request is scoped to a namespace by its hostname: `https://{namespace}.api.phorge.net`. Repository names occupy one URL segment, so percent-encode grouped names (`team/storefront` becomes `team%2Fstorefront`). File paths and ref names used in path segments must also be percent-encoded.\n\nAuthenticate with a customer-signed ES256 or RS256 JWT sent as `Authorization: Bearer <jwt>`. The JWT carries `iss` (namespace), `repo` (repository name or `*`), `scopes`, `iat`, `exp`, and optionally `actor`, `kid`, `ops`, and `refPolicies`. Public repository reads may omit the token.\n\nList endpoints accept `cursor` and `limit` (default 20, maximum 100) and return `items`, `next_cursor`, and `has_more`. Treat cursors as opaque.\n\nEvery error is a JSON object with a stable `code`, a human-readable `message`, and optional structured `details`. Mutating ref operations accept `expectedHeadSha`; when the ref has moved the API returns HTTP 412 with code `HEAD_MOVED` and the expected and actual SHAs in `details`.\n\nStandard Git clone, fetch, and push remain available at `https://{namespace}.phorge.net/{repo}.git` using the literal username `t` and a JWT as the password.",
    "termsOfService": "https://phorge.net/docs",
    "contact": {
      "name": "The San Francisco Tooling Company",
      "url": "https://phorge.net/",
      "email": "hi@sf.tools"
    }
  },
  "externalDocs": {
    "description": "Phorge HTTP API reference",
    "url": "https://phorge.net/docs/http"
  },
  "servers": [
    {
      "url": "https://{namespace}.api.phorge.net",
      "description": "Namespace-scoped API origin. The namespace is the lowercase DNS label chosen when the namespace was created.",
      "variables": {
        "namespace": {
          "default": "your-org",
          "description": "Your Phorge namespace."
        }
      }
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Service",
      "description": "Service health."
    },
    {
      "name": "Repositories",
      "description": "Create, list, inspect, and delete repositories."
    },
    {
      "name": "Reads",
      "description": "Read files, history, and diffs without cloning. Reads require the `git:read` scope unless the repository is public."
    },
    {
      "name": "Writes",
      "description": "Create commits and manage refs without a working tree. Writes require the `repo:write` scope and return HTTP 201."
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "Service"
        ],
        "operationId": "getHealth",
        "summary": "Service health",
        "description": "Returns 200 with `{\"status\":\"ready\"}` only when the database responds. This endpoint is available on every API hostname and needs no authentication.",
        "security": [],
        "responses": {
          "200": {
            "description": "The service is ready.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                },
                "example": {
                  "status": "ready"
                }
              }
            }
          },
          "404": {
            "description": "The hostname does not belong to a Phorge namespace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "UNKNOWN_ORIGIN",
                  "message": "hostname does not match a tenant origin"
                }
              }
            }
          },
          "503": {
            "description": "The database is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "NOT_READY",
                  "message": "database is unavailable"
                }
              }
            }
          }
        }
      }
    },
    "/repos": {
      "post": {
        "tags": [
          "Repositories"
        ],
        "operationId": "createRepository",
        "summary": "Create a repository",
        "description": "Creates a repository in the namespace. Creation is idempotent: repeating the request for a repository the namespace already owns returns HTTP 200 with the existing repository. Requires the `repo:write` scope with the JWT `repo` claim set to the repository name.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRepositoryRequest"
              },
              "example": {
                "name": "workspace",
                "ttl_seconds": 86400,
                "private": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The repository already existed and is owned by this namespace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Repository"
                }
              }
            }
          },
          "201": {
            "description": "The repository was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Repository"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "A repository with this name exists and belongs to another tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "REPO_EXISTS",
                  "message": "repository already exists"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "tags": [
          "Repositories"
        ],
        "operationId": "listRepositories",
        "summary": "List repositories",
        "description": "Lists repositories owned by the namespace. Requires the `org:read` scope with the JWT `repo` claim set to `*`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of repositories.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RepositoryPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "get": {
        "tags": [
          "Repositories"
        ],
        "operationId": "getRepository",
        "summary": "Repository metadata",
        "description": "Returns repository metadata. Public repositories may be read without a token.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "Repository metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Repository"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "tags": [
          "Repositories"
        ],
        "operationId": "deleteRepository",
        "summary": "Delete a repository",
        "description": "Permanently deletes the repository, including cold and bundle copies. Requires the `repo:delete` scope.",
        "responses": {
          "204": {
            "description": "The repository was deleted."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/files": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "listFiles",
        "summary": "List files",
        "description": "Lists tree entries at a ref. `recursive` defaults to true; set `recursive=false` for one directory level. `metadata=true` adds the last commit that touched each entry.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ref"
          },
          {
            "name": "path",
            "in": "query",
            "description": "Directory to list. Defaults to the repository root.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "recursive",
            "in": "query",
            "description": "List nested entries. Defaults to true.",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "metadata",
            "in": "query",
            "description": "Include `last_commit` for each entry.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of tree entries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FilePage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/files/{path}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        },
        {
          "name": "path",
          "in": "path",
          "required": true,
          "description": "Percent-encoded file path within the repository, for example `src%2Fmain.ts`.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "getFile",
        "summary": "Stream a file",
        "description": "Streams file bytes at a ref. Supports one `Range` header (HTTP 206) and `If-None-Match` against the returned `ETag`. Text files are served as `text/plain; charset=utf-8`; other files as `application/octet-stream`. A short-lived signed `access_token` query parameter issued by the SDK's `getFileURL` may replace the bearer token for exactly one file and ref.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ref"
          },
          {
            "name": "Range",
            "in": "header",
            "description": "A single byte range such as `bytes=0-1023`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "description": "Return 304 when the ETag still matches.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The complete file.",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                }
              },
              "Accept-Ranges": {
                "schema": {
                  "type": "string",
                  "const": "bytes"
                }
              }
            },
            "content": {
              "text/plain; charset=utf-8": {
                "schema": {
                  "type": "string"
                }
              },
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "The requested byte range.",
            "headers": {
              "Content-Range": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "304": {
            "description": "The file is unchanged since the supplied ETag."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "416": {
            "description": "The byte range is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "INVALID_RANGE",
                  "message": "range is not satisfiable"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "head": {
        "tags": [
          "Reads"
        ],
        "operationId": "headFile",
        "summary": "File headers",
        "description": "Returns the same headers as `GET` (including `ETag`, `Content-Length`, and `Content-Type`) without a body.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ref"
          }
        ],
        "responses": {
          "200": {
            "description": "File headers.",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/repos/{repo}/archive": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "getArchive",
        "summary": "Stream a tar.gz archive",
        "description": "Streams a gzip-compressed tar archive of the tree at a ref, optionally limited to one subdirectory.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ref"
          },
          {
            "name": "path",
            "in": "query",
            "description": "Subdirectory to archive. Defaults to the repository root.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The archive.",
            "content": {
              "application/gzip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/grep": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "grep",
        "summary": "Search file contents",
        "description": "Runs a content search at a ref and returns matching lines with optional context.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "The search pattern.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ref"
          },
          {
            "name": "context",
            "in": "query",
            "description": "Lines of context around each match, from 0 to 20.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 20,
              "default": 0
            }
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of matches.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GrepPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/blame": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "blame",
        "summary": "Blame a file",
        "description": "Returns `git blame --porcelain` output for one file at a ref.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "File path within the repository.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ref"
          }
        ],
        "responses": {
          "200": {
            "description": "Porcelain blame output.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Blame"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/branches": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "listBranches",
        "summary": "List branches",
        "description": "Lists branches sorted by name with their head SHA, committer date, and subject.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of branches.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BranchPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "tags": [
          "Writes"
        ],
        "operationId": "createBranch",
        "summary": "Create a branch",
        "description": "Creates a branch at `startPoint`. `expectedHeadSha` must equal the SHA that `startPoint` resolves to.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBranchRequest"
              },
              "example": {
                "name": "agent-7",
                "startPoint": "main",
                "expectedHeadSha": "0123456789abcdef0123456789abcdef01234567"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/RefResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/branches/{branch}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        },
        {
          "name": "branch",
          "in": "path",
          "required": true,
          "description": "Percent-encoded branch name.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "delete": {
        "tags": [
          "Writes"
        ],
        "operationId": "deleteBranch",
        "summary": "Delete a branch",
        "description": "Deletes a branch only when its head still equals `expectedHeadSha`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/expectedHeadShaQuery"
          }
        ],
        "responses": {
          "201": {
            "$ref": "#/components/responses/RefResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/commits": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "listCommits",
        "summary": "List commits",
        "description": "Lists commits reachable from a ref, newest first.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ref"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of commits.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommitPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "tags": [
          "Writes"
        ],
        "operationId": "createCommit",
        "summary": "Commit file operations",
        "description": "Creates a commit from upsert and delete operations. The request is `multipart/form-data`: the first part is named `metadata` and holds the JSON body; each upsert names a later raw file part through `content_part`. File bytes are not Base64 encoded. Delete operations have no file part. The complete request is limited to 128 MiB and remains subject to repository quotas. `expectedHeadSha` is optional but recommended for concurrent agents.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "metadata"
                ],
                "properties": {
                  "metadata": {
                    "$ref": "#/components/schemas/CommitMetadata"
                  }
                },
                "additionalProperties": {
                  "type": "string",
                  "format": "binary",
                  "description": "Raw file content for one upsert operation, named by that operation's `content_part`."
                }
              },
              "encoding": {
                "metadata": {
                  "contentType": "application/json"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/RefResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "description": "The multipart request exceeds 128 MiB or its metadata exceeds 1 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "COMMIT_TOO_LARGE",
                  "message": "multipart commit exceeds 128 MiB"
                }
              }
            }
          },
          "415": {
            "description": "The request is not `multipart/form-data`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "MULTIPART_REQUIRED",
                  "message": "file-operation commits require multipart/form-data"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/commits/apply-diff": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "post": {
        "tags": [
          "Writes"
        ],
        "operationId": "applyDiff",
        "summary": "Commit a unified diff",
        "description": "Applies a unified diff to `branch` and commits the result. `expectedHeadSha` is required.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApplyDiffRequest"
              },
              "example": {
                "branch": "main",
                "expectedHeadSha": "0123456789abcdef0123456789abcdef01234567",
                "message": "Apply generated patch",
                "diff": "diff --git a/a.txt b/a.txt\n--- a/a.txt\n+++ b/a.txt\n@@ -1 +1 @@\n-old\n+new\n",
                "author": {
                  "name": "Agent",
                  "email": "agent@example.com"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/RefResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/commits/{sha}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        },
        {
          "$ref": "#/components/parameters/sha"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "getCommit",
        "summary": "Get a commit",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "The commit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Commit"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/commits/{sha}/diff": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        },
        {
          "$ref": "#/components/parameters/sha"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "getCommitDiff",
        "summary": "Commit patch",
        "description": "Returns the commit's patch as `text/x-diff`.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "The patch.",
            "content": {
              "text/x-diff; charset=utf-8": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/diff": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "getBranchDiff",
        "summary": "Diff two refs",
        "description": "Returns the three-dot diff (`base...head`) as `text/x-diff`.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "name": "base",
            "in": "query",
            "required": true,
            "description": "Base branch, tag, or commit SHA.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "head",
            "in": "query",
            "required": true,
            "description": "Head branch, tag, or commit SHA.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The diff.",
            "content": {
              "text/x-diff; charset=utf-8": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/merges/preview": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "post": {
        "tags": [
          "Writes"
        ],
        "operationId": "previewMerge",
        "summary": "Preview a merge",
        "description": "Computes the merge result without moving the target ref. A conflicting merge returns HTTP 409.",
        "requestBody": {
          "$ref": "#/components/requestBodies/Merge"
        },
        "responses": {
          "200": {
            "description": "The merge can be performed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MergePreview"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/MergeConflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/merges": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "post": {
        "tags": [
          "Writes"
        ],
        "operationId": "merge",
        "summary": "Merge a branch",
        "description": "Merges `source` into `target`. `fast-forward-only` fails with HTTP 409 when a merge commit would be required; `fast-forward-preferred` creates a merge commit when necessary.",
        "requestBody": {
          "$ref": "#/components/requestBodies/Merge"
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/RefResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/MergeConflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/tags": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "post": {
        "tags": [
          "Writes"
        ],
        "operationId": "createTag",
        "summary": "Create a tag",
        "description": "Creates a lightweight tag, or an annotated tag when `message` is present. `expectedHeadSha` must equal the SHA that `target` resolves to.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTagRequest"
              },
              "example": {
                "name": "v1.0.0",
                "target": "main",
                "expectedHeadSha": "0123456789abcdef0123456789abcdef01234567",
                "message": "Release v1.0.0",
                "tagger": {
                  "name": "Release Bot",
                  "email": "releases@example.com"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/RefResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/tags/{tag}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        },
        {
          "name": "tag",
          "in": "path",
          "required": true,
          "description": "Percent-encoded tag name.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "delete": {
        "tags": [
          "Writes"
        ],
        "operationId": "deleteTag",
        "summary": "Delete a tag",
        "description": "Deletes a tag only when it still points at `expectedHeadSha`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/expectedHeadShaQuery"
          }
        ],
        "responses": {
          "201": {
            "$ref": "#/components/responses/RefResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/repos/{repo}/bundle-uri": {
      "parameters": [
        {
          "$ref": "#/components/parameters/repo"
        }
      ],
      "get": {
        "tags": [
          "Reads"
        ],
        "operationId": "getBundleURI",
        "summary": "Signed clone bundle URI",
        "description": "Returns a short-lived signed URL for the repository's published clone bundle. The SDK's `clone` helper uses it automatically. Returns HTTP 404 with code `BUNDLE_NOT_READY` until a bundle has been published.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "A signed bundle URI.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BundleURI"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "A customer-signed ES256 or RS256 JWT. Claims: `iss` (namespace), `repo` (repository name, or `*` for listing), `scopes` (`git:read`, `git:write`, `repo:write`, `repo:delete`, `org:read`), `iat`, `exp`, and optionally `actor`, `kid`, `ops`, and `refPolicies`. The `phorge` npm package signs these tokens locally; the private key never leaves the caller."
      }
    },
    "parameters": {
      "repo": {
        "name": "repo",
        "in": "path",
        "required": true,
        "description": "Repository name as one percent-encoded path segment. `team/storefront` becomes `team%2Fstorefront`.",
        "schema": {
          "type": "string"
        }
      },
      "sha": {
        "name": "sha",
        "in": "path",
        "required": true,
        "description": "Full or abbreviated commit SHA.",
        "schema": {
          "type": "string"
        }
      },
      "ref": {
        "name": "ref",
        "in": "query",
        "description": "Branch, tag, or commit SHA. Defaults to `HEAD`.",
        "schema": {
          "type": "string",
          "default": "HEAD"
        }
      },
      "cursor": {
        "name": "cursor",
        "in": "query",
        "description": "Opaque cursor from a previous response's `next_cursor`.",
        "schema": {
          "type": "string"
        }
      },
      "limit": {
        "name": "limit",
        "in": "query",
        "description": "Page size. Defaults to 20; values above 100 are clamped to 100.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "expectedHeadShaQuery": {
        "name": "expectedHeadSha",
        "in": "query",
        "required": true,
        "description": "The SHA the ref must currently point at. Omitting it returns HTTP 428; a mismatch returns HTTP 412.",
        "schema": {
          "type": "string"
        }
      }
    },
    "requestBodies": {
      "Merge": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/MergeRequest"
            },
            "example": {
              "source": "agent-7",
              "target": "main",
              "expectedHeadSha": "0123456789abcdef0123456789abcdef01234567",
              "mode": "fast-forward-preferred",
              "message": "Merge agent work",
              "author": {
                "name": "Agent",
                "email": "agent@example.com"
              }
            }
          }
        }
      }
    },
    "responses": {
      "RefResult": {
        "description": "The ref was updated. For deletions `sha` is the all-zero object ID.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RefResult"
            },
            "example": {
              "sha": "0123456789abcdef0123456789abcdef01234567",
              "ref": "refs/heads/main"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Malformed JSON, cursor, path, query input, revision, or multipart body. Codes include `INVALID_JSON`, `INVALID_CURSOR`, `INVALID_PATH`, `INVALID_REF`, `INVALID_CONTEXT`, `QUERY_REQUIRED`, `INVALID_MULTIPART`, `MISSING_CONTENT_PART`, `UNEXPECTED_CONTENT_PART`, and `DUPLICATE_CONTENT_PART`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "INVALID_CURSOR",
              "message": "cursor is invalid"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "The bearer token is missing, expired, or has an invalid signature.",
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string",
              "const": "Bearer realm=\"phorge\""
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "UNAUTHORIZED",
              "message": "token is invalid"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The token lacks the required scope or repository claim, the ref is outside the token's `refPolicies`, or a quota was exceeded. Codes include `FORBIDDEN`, `REF_POLICY_VIOLATION`, `FORCE_PUSH_FORBIDDEN`, `REPO_QUOTA_EXCEEDED`, `REPO_SIZE_QUOTA_EXCEEDED`, `TENANT_STORAGE_QUOTA_EXCEEDED`, `OBJECT_COUNT_QUOTA_EXCEEDED`, `REF_COUNT_QUOTA_EXCEEDED`, and `EGRESS_QUOTA_EXCEEDED`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "REF_POLICY_VIOLATION",
              "message": "token does not permit this branch"
            }
          }
        }
      },
      "NotFound": {
        "description": "The repository, file, ref, commit, branch, tag, bundle, or route does not exist. Codes include `NOT_FOUND`, `REPO_NOT_FOUND`, `FILE_NOT_FOUND`, `REF_NOT_FOUND`, `COMMIT_NOT_FOUND`, `BRANCH_NOT_FOUND`, `TAG_NOT_FOUND`, and `BUNDLE_NOT_READY`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "REPO_NOT_FOUND",
              "message": "repository not found"
            }
          }
        }
      },
      "MergeConflict": {
        "description": "The merge conflicts (`MERGE_CONFLICT`) or is not a fast-forward in `fast-forward-only` mode (`NON_FAST_FORWARD`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "NON_FAST_FORWARD",
              "message": "merge is not a fast-forward"
            }
          }
        }
      },
      "PreconditionFailed": {
        "description": "The ref no longer matches `expectedHeadSha`. Fetch the new head, reconsider the change, and retry deliberately.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "HEAD_MOVED",
              "message": "ref has moved",
              "details": {
                "ref": "refs/heads/main",
                "expected": "0123456789abcdef0123456789abcdef01234567",
                "actual": "89abcdef0123456789abcdef0123456789abcdef"
              }
            }
          }
        }
      },
      "PreconditionRequired": {
        "description": "`expectedHeadSha` is required for this operation and was omitted.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "EXPECTED_HEAD_REQUIRED",
              "message": "expectedHeadSha is required"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "The input is well-formed but invalid. Codes include `INVALID_REPO_NAME`, `INVALID_TTL`, `INVALID_REF`, `INVALID_COMMIT`, `INVALID_OPERATION`, `INVALID_CONTENT`, `INVALID_CONTENT_PART`, `INVALID_MODE`, `INVALID_AUTHOR`, `INVALID_COMMITTER`, `INVALID_TAGGER`, and `INVALID_MERGE_MODE`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "INVALID_MERGE_MODE",
              "message": "mode must be fast-forward-only or fast-forward-preferred"
            }
          }
        }
      },
      "RateLimited": {
        "description": "The tenant or client IP exceeded its per-minute request rate.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "RATE_LIMITED",
              "message": "rate limit exceeded"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Every error response has this shape. `code` is stable and safe to branch on; `message` is for humans; `details` carries structured context such as the expected and actual SHAs for `HEAD_MOVED`.",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable machine-readable error code in SCREAMING_SNAKE_CASE, for example `HEAD_MOVED`, `EXPECTED_HEAD_REQUIRED`, `REF_POLICY_VIOLATION`, `RATE_LIMITED`, or `REPO_NOT_FOUND`.",
            "pattern": "^[A-Z][A-Z0-9_]*$"
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation."
          },
          "details": {
            "type": "object",
            "description": "Optional structured context.",
            "additionalProperties": true
          }
        },
        "examples": [
          {
            "code": "HEAD_MOVED",
            "message": "ref has moved",
            "details": {
              "ref": "refs/heads/main",
              "expected": "0123…",
              "actual": "89ab…"
            }
          }
        ]
      },
      "Health": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "ready"
          }
        }
      },
      "Repository": {
        "type": "object",
        "required": [
          "id",
          "name",
          "namespace",
          "state",
          "private",
          "expires_at",
          "size_bytes",
          "content_version",
          "git_url",
          "api_url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable repository identifier."
          },
          "name": {
            "type": "string",
            "description": "Repository name within the namespace."
          },
          "namespace": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "description": "Storage tier state, for example `hot` or `cold`. Cold repositories are thawed transparently on access."
          },
          "private": {
            "type": "boolean"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Scheduled deletion time, or null when the repository does not expire."
          },
          "size_bytes": {
            "type": "integer",
            "minimum": 0
          },
          "content_version": {
            "type": "integer",
            "minimum": 0,
            "description": "Increments on every content change."
          },
          "git_url": {
            "type": "string",
            "format": "uri",
            "description": "Stock Git smart-HTTP remote URL."
          },
          "api_url": {
            "type": "string",
            "format": "uri",
            "description": "This repository's API base URL."
          }
        },
        "examples": [
          {
            "id": "repo_01j9",
            "name": "workspace",
            "namespace": "your-org",
            "state": "hot",
            "private": true,
            "expires_at": null,
            "size_bytes": 27648,
            "content_version": 3,
            "git_url": "https://your-org.phorge.net/workspace.git",
            "api_url": "https://your-org.api.phorge.net/repos/workspace"
          }
        ]
      },
      "CreateRepositoryRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "description": "Repository name. Lowercase segments separated by `/` are allowed and are percent-encoded in URLs."
          },
          "ttl_seconds": {
            "type": "integer",
            "minimum": 0,
            "description": "Seconds until scheduled deletion. Omit or pass 0 for no expiry. Cannot exceed the service maximum (default 90 days)."
          },
          "private": {
            "type": "boolean",
            "default": true,
            "description": "Private repositories require a token for reads."
          }
        }
      },
      "Page": {
        "type": "object",
        "required": [
          "items",
          "next_cursor",
          "has_more"
        ],
        "properties": {
          "next_cursor": {
            "type": "string",
            "description": "Opaque cursor for the next page. Empty when `has_more` is false."
          },
          "has_more": {
            "type": "boolean"
          }
        }
      },
      "RepositoryPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Page"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Repository"
                }
              }
            }
          }
        ]
      },
      "FileCommit": {
        "type": "object",
        "required": [
          "sha",
          "date",
          "author",
          "message"
        ],
        "properties": {
          "sha": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "author": {
            "type": "string"
          },
          "message": {
            "type": "string",
            "description": "Commit subject line."
          }
        }
      },
      "FileEntry": {
        "type": "object",
        "required": [
          "path",
          "mode",
          "type",
          "sha",
          "size"
        ],
        "properties": {
          "path": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "description": "Git tree mode such as `100644`, `100755`, `120000`, or `040000`."
          },
          "type": {
            "type": "string",
            "description": "`blob` or `tree`."
          },
          "sha": {
            "type": "string"
          },
          "size": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Blob size in bytes; null for trees."
          },
          "last_commit": {
            "$ref": "#/components/schemas/FileCommit"
          }
        }
      },
      "FilePage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Page"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FileEntry"
                }
              }
            }
          }
        ]
      },
      "Commit": {
        "type": "object",
        "required": [
          "sha",
          "parents",
          "author",
          "date",
          "message"
        ],
        "properties": {
          "sha": {
            "type": "string"
          },
          "parents": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "author": {
            "type": "string",
            "description": "`Name <email>`."
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "CommitPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Page"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Commit"
                }
              }
            }
          }
        ]
      },
      "Branch": {
        "type": "object",
        "required": [
          "name",
          "sha",
          "date",
          "message"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "sha": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "type": "string",
            "description": "Head commit subject line."
          }
        }
      },
      "BranchPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Page"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Branch"
                }
              }
            }
          }
        ]
      },
      "GrepMatch": {
        "type": "object",
        "required": [
          "path",
          "line",
          "text"
        ],
        "properties": {
          "path": {
            "type": "string"
          },
          "line": {
            "type": "integer",
            "minimum": 1
          },
          "text": {
            "type": "string"
          }
        }
      },
      "GrepPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Page"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/GrepMatch"
                }
              }
            }
          }
        ]
      },
      "Blame": {
        "type": "object",
        "required": [
          "porcelain"
        ],
        "properties": {
          "porcelain": {
            "type": "string",
            "description": "Raw `git blame --porcelain` output."
          }
        }
      },
      "BundleURI": {
        "type": "object",
        "required": [
          "uri",
          "size_bytes",
          "expires_at"
        ],
        "properties": {
          "uri": {
            "type": "string",
            "format": "uri",
            "description": "Signed bundle URL. Treat it as a secret until it expires."
          },
          "size_bytes": {
            "type": "integer",
            "minimum": 0
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CommitIdentity": {
        "type": "object",
        "required": [
          "name",
          "email"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          }
        }
      },
      "FileOperation": {
        "type": "object",
        "required": [
          "operation",
          "path"
        ],
        "additionalProperties": false,
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "upsert",
              "delete"
            ]
          },
          "path": {
            "type": "string"
          },
          "content_part": {
            "type": "string",
            "description": "Name of the multipart file part carrying this upsert's bytes. Required for `upsert`; forbidden for `delete`."
          },
          "mode": {
            "type": "string",
            "enum": [
              "100644",
              "100755",
              "120000"
            ],
            "default": "100644"
          }
        }
      },
      "CommitMetadata": {
        "type": "object",
        "required": [
          "branch",
          "message",
          "operations"
        ],
        "additionalProperties": false,
        "description": "JSON body of the `metadata` multipart part.",
        "properties": {
          "branch": {
            "type": "string"
          },
          "expectedHeadSha": {
            "type": "string",
            "description": "Optional but recommended. Omit only when no other writer can race this commit."
          },
          "message": {
            "type": "string"
          },
          "operations": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/FileOperation"
            }
          },
          "author": {
            "$ref": "#/components/schemas/CommitIdentity"
          },
          "committer": {
            "$ref": "#/components/schemas/CommitIdentity"
          }
        },
        "examples": [
          {
            "branch": "main",
            "expectedHeadSha": "0123456789abcdef0123456789abcdef01234567",
            "message": "Update worker",
            "author": {
              "name": "Agent",
              "email": "agent@example.com"
            },
            "operations": [
              {
                "operation": "upsert",
                "path": "src/worker.ts",
                "content_part": "file-0",
                "mode": "100644"
              },
              {
                "operation": "delete",
                "path": "src/old-worker.ts"
              }
            ]
          }
        ]
      },
      "ApplyDiffRequest": {
        "type": "object",
        "required": [
          "branch",
          "expectedHeadSha",
          "message",
          "diff"
        ],
        "additionalProperties": false,
        "properties": {
          "branch": {
            "type": "string"
          },
          "expectedHeadSha": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "diff": {
            "type": "string",
            "description": "A unified diff."
          },
          "author": {
            "$ref": "#/components/schemas/CommitIdentity"
          },
          "committer": {
            "$ref": "#/components/schemas/CommitIdentity"
          }
        }
      },
      "CreateBranchRequest": {
        "type": "object",
        "required": [
          "name",
          "startPoint",
          "expectedHeadSha"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "startPoint": {
            "type": "string",
            "description": "Branch, tag, or commit SHA the new branch starts from."
          },
          "expectedHeadSha": {
            "type": "string",
            "description": "Must equal the SHA that `startPoint` resolves to."
          }
        }
      },
      "MergeRequest": {
        "type": "object",
        "required": [
          "source",
          "target",
          "expectedHeadSha",
          "mode"
        ],
        "additionalProperties": false,
        "properties": {
          "source": {
            "type": "string"
          },
          "target": {
            "type": "string"
          },
          "expectedHeadSha": {
            "type": "string",
            "description": "Current head of `target`."
          },
          "mode": {
            "type": "string",
            "enum": [
              "fast-forward-only",
              "fast-forward-preferred"
            ]
          },
          "message": {
            "type": "string",
            "description": "Merge commit message. Defaults to `Merge <source> into <target>`."
          },
          "author": {
            "$ref": "#/components/schemas/CommitIdentity"
          },
          "committer": {
            "$ref": "#/components/schemas/CommitIdentity"
          }
        }
      },
      "MergePreview": {
        "type": "object",
        "required": [
          "fast_forward",
          "mergeable",
          "result_sha",
          "target_sha",
          "source_sha"
        ],
        "properties": {
          "fast_forward": {
            "type": "boolean"
          },
          "mergeable": {
            "type": "boolean",
            "const": true
          },
          "result_sha": {
            "type": "string",
            "description": "The source head for a fast-forward, otherwise the merged tree SHA."
          },
          "target_sha": {
            "type": "string"
          },
          "source_sha": {
            "type": "string"
          }
        }
      },
      "CreateTagRequest": {
        "type": "object",
        "required": [
          "name",
          "target",
          "expectedHeadSha"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "target": {
            "type": "string",
            "description": "Branch, tag, or commit SHA to tag."
          },
          "expectedHeadSha": {
            "type": "string",
            "description": "Must equal the SHA that `target` resolves to."
          },
          "message": {
            "type": "string",
            "description": "Creates an annotated tag when present."
          },
          "tagger": {
            "$ref": "#/components/schemas/CommitIdentity"
          }
        }
      },
      "RefResult": {
        "type": "object",
        "required": [
          "sha",
          "ref"
        ],
        "properties": {
          "sha": {
            "type": "string",
            "description": "The new object the ref points at, or the all-zero ID after a deletion."
          },
          "ref": {
            "type": "string",
            "description": "Fully qualified ref such as `refs/heads/main`."
          }
        }
      }
    }
  }
}
