# AGENTS.md This file provides guidance to Qoder (qoder.com) when working with code in this repository. ## Project Overview Cluster is a lightweight OCI (Open Container Initiative) registry implementation with a Go backend (Fiber v3) and React/TypeScript frontend. It provides Docker registry v2 API compliance for container image storage and management. ## Build and Development Commands ### Backend (Go) ```bash # Build the binary go build -o cluster . # Run with default settings ./cluster # Run with custom configuration ./cluster -debug -address 0.0.0.0:8080 -data-dir ./x-storage # Run tests go test ./pkg/tool/... # Update dependencies go mod tidy ``` **Command-line flags:** - `-debug`: Enable debug logging - `-address` / `-A`: Server listen address (default: 0.0.0.0:9119) - `-data-dir` / `-D`: Data directory for storage (default: ./x-storage) ### Frontend (React/TypeScript) **Package Manager:** This project uses `pnpm` exclusively. Do not use npm or yarn. ```bash cd frontend # Install dependencies pnpm install # Development server (runs on http://localhost:3000) pnpm dev # Lint TypeScript/React code pnpm lint # Production build pnpm run build # Preview production build pnpm preview ``` ### Full Stack Development ```bash # Run both backend and frontend concurrently ./dev.sh ``` The `dev.sh` script starts the Go backend and Vite dev server together, handling graceful shutdown on Ctrl+C. ## Architecture ### Request Flow 1. **Entry Point** (`main.go`): Initializes signal handling and delegates to cobra command 2. **Command Layer** (`internal/cmd/cmd.go`): Manages application lifecycle - Initializes configuration (`internal/opt`) - Initializes SQLite database (`pkg/database/db`) at `{data-dir}/cluster.db` - Initializes filesystem storage (`pkg/store`) for blobs/manifests - Starts Fiber HTTP server (`internal/api`) 3. **API Layer** (`internal/api/api.go`): Routes requests to handlers - OCI Registry v2 endpoints: `/v2/*` routes to `internal/module/registry` - Custom API v1 endpoints: `/api/v1/registry/*` for image listing and config 4. **Handler Layer** (`internal/module/registry/`): Implements OCI registry operations - `registry.go`: Main routing logic - `blob.go`: Blob upload/download/chunked upload - `manifest.go`: Manifest storage and retrieval - `tag.go`: Tag management - `catalog.go`: Repository listing ### Storage Architecture **Database** (`pkg/database/db`): - SQLite via GORM - Stores: repositories, tags, manifest metadata, registry config - Location: `{data-dir}/cluster.db` **Filesystem Storage** (`pkg/store`): - Content-addressed storage with SHA256 - Structure: - `registry/blobs/sha256/{2-char-prefix}/{2-char-prefix}/{full-hash}` - Blob files - `registry/manifests/sha256/{2-char-prefix}/{2-char-prefix}/{full-hash}` - Manifest files - `registry/uploads/{uuid}` - Temporary upload files - All write operations verify SHA256 digest before finalizing ### Frontend Architecture **Tech Stack:** - React 18 + TypeScript - Vite build tool - Zustand state management (`src/stores/`) - Material-UI (MUI) components - React Router for routing **API Proxy:** Dev server proxies `/api/*` requests to backend (configured in `vite.config.ts`) ### Key Packages - `pkg/tool/`: Utility functions (UUID generation, password hashing, file helpers, table formatting, etc.) - `pkg/resp/`: HTTP response helpers and i18n - `internal/middleware/`: CORS, logging, recovery, repository context injection - `internal/model/`: GORM database models ## Code Conventions ### Go - Use GORM for database operations via `db.Default` singleton - Use `pkg/store.Default` for filesystem operations - Handlers receive `(ctx context.Context, db *gorm.DB, store store.Store)` and return `fiber.Handler` - Middleware uses Fiber v3 context - Digest format is always `sha256:hexstring` - All blob/manifest writes must verify digest before finalizing ### Frontend - Use Zustand for state management - Follow MUI theming patterns defined in `src/theme.ts` - TypeScript strict mode enabled - Components in `src/components/`, pages in `src/pages/` ## Testing ```bash # Run Go tests go test ./pkg/tool/... # Frontend linting (no test framework currently configured) cd frontend && pnpm lint ``` ## OCI Registry v2 API Endpoints - `GET /v2/` - Registry version check - `POST /v2/{repo}/blobs/uploads/` - Initiate blob upload, returns upload UUID - `PATCH /v2/{repo}/blobs/uploads/{uuid}` - Upload blob chunk (chunked upload) - `PUT /v2/{repo}/blobs/uploads/{uuid}?digest={digest}` - Finalize blob upload - `GET /v2/{repo}/blobs/{digest}` - Download blob - `HEAD /v2/{repo}/blobs/{digest}` - Check blob existence - `PUT /v2/{repo}/manifests/{tag}` - Store manifest - `GET /v2/{repo}/manifests/{tag}` - Retrieve manifest - `DELETE /v2/{repo}/manifests/{tag}` - Delete manifest - `GET /v2/{repo}/tags/list` - List repository tags - `GET /v2/_catalog` - List all repositories ## Custom API v1 Endpoints - `GET /api/v1/registry/image/list` - List images with metadata - `GET /api/v1/registry/image/download/*` - Download images - `GET /api/v1/registry/config` - Get registry configuration - `POST /api/v1/registry/config` - Set registry configuration