{ "swagger": "2.0", "info": { "description": "HTTP API for package enrichment, vulnerability lookup, cache stats, and source browsing.", "title": "git-pkgs proxy API", "contact": {}, "version": "0.1.0" }, "basePath": "/", "paths": { "/_internal/scan-fetch": { "get": { "description": "Streams the exact bytes staged in storage for a pre-cache security scan.\nRequires a short-lived HMAC-signed token minted by the proxy itself and\ndelivered via the fetch_url field of the scan notify request (see the\nArtifact Scanning section of docs/configuration.md). Not part of the\npublic API; restrict access to the scanner network at the ingress layer.", "produces": [ "application/octet-stream" ], "tags": [ "scanning" ], "summary": "Fetch a staged artifact for scanning", "parameters": [ { "type": "string", "description": "Storage path of the staged artifact", "name": "path", "in": "query", "required": true }, { "type": "integer", "description": "Token expiry, Unix seconds", "name": "exp", "in": "query", "required": true }, { "type": "string", "description": "HMAC-SHA256 signature over the string path|exp", "name": "sig", "in": "query", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "403": { "description": "invalid, expired, or tampered token", "schema": { "type": "string" } }, "404": { "description": "object not found in storage, or scanning is not configured", "schema": { "type": "string" } } } } }, "/api/bulk": { "post": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "api" ], "summary": "Bulk package lookup by PURL", "parameters": [ { "description": "PURLs", "name": "request", "in": "body", "required": true, "schema": { "$ref": "#/definitions/server.BulkRequest" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/server.BulkResponse" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } }, "/api/hosted/{ecosystem}/{name}": { "get": { "produces": [ "application/json" ], "tags": [ "hosted" ], "summary": "List pushed package archives", "parameters": [ { "type": "string", "description": "Ecosystem", "name": "ecosystem", "in": "path", "required": true }, { "type": "string", "description": "Package name", "name": "name", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/server.HostedListResponse" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } }, "/api/hosted/{ecosystem}/{name}/{version}": { "put": { "security": [ { "BearerAuth": [] } ], "description": "Stores the request body as the archive for name@version. It is served in place of the upstream archive with the same version and is never evicted.", "consumes": [ "application/octet-stream" ], "produces": [ "application/json" ], "tags": [ "hosted" ], "summary": "Push a package archive", "parameters": [ { "type": "string", "description": "Ecosystem (npm or composer)", "name": "ecosystem", "in": "path", "required": true }, { "type": "string", "description": "Package name, including an npm scope or the Composer vendor", "name": "name", "in": "path", "required": true }, { "type": "string", "description": "Version", "name": "version", "in": "path", "required": true } ], "responses": { "201": { "description": "Created", "schema": { "$ref": "#/definitions/server.HostedPushResponse" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "401": { "description": "Unauthorized", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "403": { "description": "Forbidden", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "413": { "description": "Request Entity Too Large", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } }, "delete": { "security": [ { "BearerAuth": [] } ], "description": "Removes the archives pushed for name@version. If the upstream has the version, clients get the upstream archive again.", "tags": [ "hosted" ], "summary": "Delete a pushed version", "parameters": [ { "type": "string", "description": "Ecosystem", "name": "ecosystem", "in": "path", "required": true }, { "type": "string", "description": "Package name", "name": "name", "in": "path", "required": true }, { "type": "string", "description": "Version", "name": "version", "in": "path", "required": true } ], "responses": { "204": { "description": "No Content" }, "401": { "description": "Unauthorized", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } }, "/api/outdated": { "post": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "api" ], "summary": "Check outdated packages", "parameters": [ { "description": "Packages to check", "name": "request", "in": "body", "required": true, "schema": { "$ref": "#/definitions/server.OutdatedRequest" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/server.OutdatedResponse" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } }, "/api/packages": { "get": { "produces": [ "application/json" ], "tags": [ "api" ], "summary": "List cached packages", "parameters": [ { "type": "string", "description": "Ecosystem", "name": "ecosystem", "in": "query" }, { "enum": [ "hits", "name", "size", "cached_at", "ecosystem", "vulns" ], "type": "string", "description": "Sort", "name": "sort", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/server.PackagesListResponse" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } }, "/api/search": { "get": { "produces": [ "application/json" ], "tags": [ "api" ], "summary": "Search cached packages", "parameters": [ { "type": "string", "description": "Query", "name": "q", "in": "query", "required": true }, { "type": "string", "description": "Ecosystem", "name": "ecosystem", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/server.SearchResponse" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } }, "/health": { "get": { "produces": [ "application/json" ], "tags": [ "meta" ], "summary": "Health check", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/server.HealthResponse" } }, "503": { "description": "Service Unavailable", "schema": { "$ref": "#/definitions/server.HealthResponse" } } } } }, "/stats": { "get": { "produces": [ "application/json" ], "tags": [ "meta" ], "summary": "Cache statistics", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/server.StatsResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } }, "/ui/api/browse/{ecosystem}/{name}/{version}": { "get": { "description": "Lists files from the first cached artifact for a package version.", "produces": [ "application/json" ], "tags": [ "browse" ], "summary": "List files inside a cached artifact", "parameters": [ { "type": "string", "description": "Ecosystem", "name": "ecosystem", "in": "path", "required": true }, { "type": "string", "description": "Package name", "name": "name", "in": "path", "required": true }, { "type": "string", "description": "Version", "name": "version", "in": "path", "required": true }, { "type": "string", "description": "Directory path inside the archive", "name": "path", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/server.BrowseListResponse" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } }, "/ui/api/browse/{ecosystem}/{name}/{version}/file/{filepath}": { "get": { "description": "Streams a single file from the cached artifact. The file path may contain slashes.", "produces": [ "application/octet-stream" ], "tags": [ "browse" ], "summary": "Fetch a file inside a cached artifact", "parameters": [ { "type": "string", "description": "Ecosystem", "name": "ecosystem", "in": "path", "required": true }, { "type": "string", "description": "Package name", "name": "name", "in": "path", "required": true }, { "type": "string", "description": "Version", "name": "version", "in": "path", "required": true }, { "type": "string", "description": "File path inside the archive", "name": "filepath", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } }, "/ui/api/compare/{ecosystem}/{name}/{fromVersion}/{toVersion}": { "get": { "description": "Returns a structured diff for two cached versions.", "produces": [ "application/json" ], "tags": [ "browse" ], "summary": "Compare two cached versions", "parameters": [ { "type": "string", "description": "Ecosystem", "name": "ecosystem", "in": "path", "required": true }, { "type": "string", "description": "Package name", "name": "name", "in": "path", "required": true }, { "type": "string", "description": "From version", "name": "fromVersion", "in": "path", "required": true }, { "type": "string", "description": "To version", "name": "toVersion", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "type": "object", "additionalProperties": true } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/server.ErrorResponse" } }, "503": { "description": "Service Unavailable", "schema": { "$ref": "#/definitions/server.ErrorResponse" } } } } } }, "definitions": { "handler.HostedArtifact": { "type": "object", "properties": { "filename": { "type": "string" }, "pushed_at": { "type": "string" }, "sha256": { "type": "string" }, "size": { "type": "integer" }, "version": { "type": "string" } } }, "server.BrowseFileInfo": { "type": "object", "properties": { "is_dir": { "type": "boolean" }, "mod_time": { "type": "string" }, "name": { "type": "string" }, "path": { "type": "string" }, "size": { "type": "integer" } } }, "server.BrowseListResponse": { "type": "object", "properties": { "files": { "type": "array", "items": { "$ref": "#/definitions/server.BrowseFileInfo" } }, "path": { "type": "string" } } }, "server.BulkRequest": { "type": "object", "properties": { "purls": { "type": "array", "items": { "type": "string" } } } }, "server.BulkResponse": { "type": "object", "properties": { "packages": { "type": "object", "additionalProperties": { "$ref": "#/definitions/server.PackageResponse" } } } }, "server.EcosystemStatsEntry": { "type": "object", "properties": { "cache_size_bytes": { "type": "integer" }, "cached_artifacts": { "type": "integer" }, "downloaded": { "type": "string" }, "downloaded_bytes": { "type": "integer" }, "downloads": { "type": "integer" }, "ecosystem": { "type": "string" }, "packages": { "type": "integer" }, "versions": { "type": "integer" } } }, "server.ErrorResponse": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } } }, "server.HealthCheck": { "type": "object", "properties": { "error": { "type": "string" }, "status": { "type": "string" }, "step": { "type": "string" } } }, "server.HealthResponse": { "type": "object", "properties": { "checks": { "type": "object", "additionalProperties": { "$ref": "#/definitions/server.HealthCheck" } }, "circuit_breakers": { "description": "CircuitBreakers reports the state (\"open\" or \"closed\") of each upstream\nregistry's artifact-fetch circuit breaker, keyed by the host fetched from\nor, where the fetch URL has none to read, by an opaque placeholder\nstanding in for it. It is omitted when no breaker has been created yet.\nAn open breaker fails every artifact fetch it covers without contacting\nthe upstream, but says nothing about this proxy's own health, so it does\nnot change Status.", "type": "object", "additionalProperties": { "type": "string" } }, "status": { "type": "string" }, "upstream_holds": { "description": "UpstreamHolds lists upstream hosts that rate limited the proxy and\nthe RFC 3339 time until which it sends them nothing. A held host\nfails cache misses without contacting it and does not change Status.", "type": "object", "additionalProperties": { "type": "string" } } } }, "server.HostedListResponse": { "type": "object", "properties": { "artifacts": { "type": "array", "items": { "$ref": "#/definitions/handler.HostedArtifact" } }, "ecosystem": { "type": "string" }, "name": { "type": "string" } } }, "server.HostedPushResponse": { "type": "object", "properties": { "ecosystem": { "type": "string" }, "filename": { "type": "string" }, "name": { "type": "string" }, "pushed_at": { "type": "string" }, "sha256": { "type": "string" }, "size": { "type": "integer" }, "version": { "type": "string" } } }, "server.OutdatedPackage": { "type": "object", "properties": { "ecosystem": { "type": "string" }, "name": { "type": "string" }, "version": { "type": "string" } } }, "server.OutdatedRequest": { "type": "object", "properties": { "packages": { "type": "array", "items": { "$ref": "#/definitions/server.OutdatedPackage" } } } }, "server.OutdatedResponse": { "type": "object", "properties": { "results": { "type": "array", "items": { "$ref": "#/definitions/server.OutdatedResult" } } } }, "server.OutdatedResult": { "type": "object", "properties": { "ecosystem": { "type": "string" }, "is_outdated": { "type": "boolean" }, "latest_version": { "type": "string" }, "name": { "type": "string" }, "version": { "type": "string" } } }, "server.PackageListResult": { "type": "object", "properties": { "cached_at": { "type": "string" }, "ecosystem": { "type": "string" }, "hits": { "type": "integer" }, "latest_version": { "type": "string" }, "license": { "type": "string" }, "license_category": { "type": "string" }, "name": { "type": "string" }, "size": { "type": "integer" }, "vuln_count": { "type": "integer" } } }, "server.PackageResponse": { "type": "object", "properties": { "description": { "type": "string" }, "ecosystem": { "type": "string" }, "homepage": { "type": "string" }, "latest_version": { "type": "string" }, "license": { "type": "string" }, "license_category": { "type": "string" }, "name": { "type": "string" }, "registry_url": { "type": "string" }, "repository": { "type": "string" } } }, "server.PackagesListResponse": { "type": "object", "properties": { "count": { "type": "integer" }, "ecosystem": { "type": "string" }, "page": { "type": "integer" }, "per_page": { "type": "integer" }, "results": { "type": "array", "items": { "$ref": "#/definitions/server.PackageListResult" } }, "sort_by": { "type": "string" }, "total": { "type": "integer" } } }, "server.SearchPackageResult": { "type": "object", "properties": { "cached_at": { "type": "string" }, "ecosystem": { "type": "string" }, "hits": { "type": "integer" }, "latest_version": { "type": "string" }, "license": { "type": "string" }, "name": { "type": "string" }, "size": { "type": "integer" } } }, "server.SearchResponse": { "type": "object", "properties": { "count": { "type": "integer" }, "query": { "type": "string" }, "results": { "type": "array", "items": { "$ref": "#/definitions/server.SearchPackageResult" } } } }, "server.StatsResponse": { "type": "object", "properties": { "cached_artifacts": { "type": "integer" }, "database_path": { "type": "string" }, "downloaded": { "type": "string" }, "downloaded_bytes": { "description": "DownloadedBytes is the accumulated download volume across every\necosystem: cache hits multiplied by the artifact size they served.", "type": "integer" }, "downloads": { "type": "integer" }, "ecosystems": { "type": "array", "items": { "$ref": "#/definitions/server.EcosystemStatsEntry" } }, "stats_unavailable": { "description": "StatsUnavailable distinguishes a proxy that has served nothing from one\nwhose aggregation failed with no snapshot to fall back on. Without it\nboth report zeros and an empty array.", "type": "boolean" }, "storage_url": { "type": "string" }, "total_size": { "type": "string" }, "total_size_bytes": { "type": "integer" } } } }, "securityDefinitions": { "BearerAuth": { "description": "\"Bearer \" followed by hosted.token", "type": "apiKey", "name": "Authorization", "in": "header" } } }