From 8ddb7c2846aa210579f1c4d263b206c4a9812bfc Mon Sep 17 00:00:00 2001 From: lyn Date: Tue, 14 Apr 2026 09:10:55 +0000 Subject: [PATCH] Initial: project plan --- PROJECT_PLAN.md | 169 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 PROJECT_PLAN.md diff --git a/PROJECT_PLAN.md b/PROJECT_PLAN.md new file mode 100644 index 0000000..3b29bd2 --- /dev/null +++ b/PROJECT_PLAN.md @@ -0,0 +1,169 @@ +# GiteaCustomApi + +Gitea repository metadata cache + query API for git.hangman-lab.top. + +## Overview + +A lightweight Go service that: +- Caches repository metadata (id, name, owner, visibility, url) from Gitea MySQL database +- Refreshes every 5 hours via full sync +- Listens for Gitea webhook events (repo create/delete) for real-time cache updates +- Exposes a `/list?username=xxx` endpoint that queries cached repos + live collaborator permissions from MySQL + +## Architecture + +``` +┌─────────────────────────────────────────────────────────────┐ +│ VPS.git │ +│ ┌──────────────┐ ┌─────────────┐ ┌──────────────────┐ │ +│ │ Gitea DB │ │ go-server │ │ Nginx │ │ +│ │ (MySQL) │◄──│ (cache+api) │ │ /c-api -> :8080 │ │ +│ └──────────────┘ └─────────────┘ └──────────────────┘ │ +│ ▲ │ +│ ┌────────┴────────┐ │ +│ │ Gitea Webhook │ │ +│ │ (create/delete)│ │ +│ └─────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Tech Stack + +- **Language**: Go +- **Database**: SQLite (local cache) +- **Source DB**: Gitea MySQL (read-only, same docker network) +- **HTTP**: Standard library `net/http` +- **Deployment**: Docker + Docker Compose on vps.git + +## API + +### `GET /list?username={username}` + +Returns all repositories visible to the given Gitea user. + +**Response** (JSON): +```json +[ + { + "name": "ClawSkills", + "owner": "lyn", + "url": "https://git.hangman-lab.top/lyn/ClawSkills.git", + "is_private": false, + "can_write": true + } +] +``` + +`can_write` is determined at query time by checking: +- User is the repo owner, OR +- User has explicit access via `access` table, OR +- User is a member of a team that has access to the repo + +### `POST /webhook/gitea` + +Receives Gitea webhook events (requires `X-Gitea-Event` header). + +Supported events: +- `repository.create` — insert new repo into cache +- `repository.delete` — remove repo from cache + +### `GET /health` + +Returns `{"status": "ok"}`. + +## Data Model + +### SQLite cache table: `repos` + +| Column | Type | Notes | +|--------------|---------|------------------------------| +| id | INTEGER | Gitea repo ID (primary key) | +| name | TEXT | | +| owner | TEXT | Gitea username of owner | +| is_private | INTEGER | 0 or 1 | +| url | TEXT | Full .git HTTPS URL | +| updated_at | INTEGER | Unix timestamp of last sync | + +## Configuration + +Environment variables: + +| Variable | Default | Description | +|---------------|---------|------------------------------| +| `DB_HOST` | `mysql` | MySQL container hostname | +| `DB_USER` | `root` | MySQL username | +| `DB_PASS` | — | MySQL password | +| `DB_NAME` | `giteadb` | MySQL database name | +| `SQLITE_PATH` | `cache.db` | SQLite file path | +| `WEBHOOK_SECRET` | — | Gitea webhook secret token | +| `PORT` | `8080` | HTTP listen port | + +## Docker + +### Dockerfile + +```dockerfile +FROM golang:1.22-alpine AS build +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download +COPY *.go ./ +RUN CGO_ENABLED=0 GOOS=linux go build -o server . +CMD ["./server"] +``` + +### docker-compose.yml (fragment to merge into vps.git compose) + +```yaml +services: + gitea-custom-api: + build: ./gitea-custom-api + container_name: gitea-custom-api + restart: unless-stopped + environment: + DB_HOST: mysql + DB_USER: root + DB_PASS: ${MYSQL_ROOT_PASSWORD} + DB_NAME: giteadb + SQLITE_PATH: /data/cache.db + WEBHOOK_SECRET: ${GITEA_WEBHOOK_SECRET} + PORT: 8080 + volumes: + - ./gitea-custom-api/data:/data + networks: + - git-network + +networks: + git-network: + external: true +``` + +### Nginx location (merge into vps.git nginx config) + +```nginx +location /c-api/ { + proxy_pass http://localhost:8080/; +} +``` + +## Gitea Webhook Setup + +In Gitea admin panel → Webhooks → Add webhook: +- **URL**: `https://git.hangman-lab.top/c-api/webhook/gitea` +- **HTTP Method**: POST +- **Content Type**: `application/json` +- **Secret**: set a strong token, pass via `WEBHOOK_SECRET` +- **Events**: Repository: Create, Repository: Delete + +## Refresh Strategy + +1. **Startup**: full sync of all non-archived repos from `repository` table +2. **Every 5 hours**: full sync (upsert based on repo id) +3. **Webhook**: incremental create/delete for real-time updates +4. **On cache miss during query**: fall back to live MySQL query + +## Out of Scope + +- Authentication on the API endpoint (internal service, only accessible via nginx on vps.git) +- Caching collaborator permissions (queried live per request) +- Handling repo rename/transfer (caught by 5h refresh)