# Gitocean Phase 1 Plan: MVP Phase 1 focuses on building the minimum viable Git hosting platform: CLI + API only, MySQL metadata, repositories stored on disk, HTTP Smart Git transport, public/private repositories, search, forks, and pull requests. This phase intentionally avoids a web UI, SSH Git transport, organizations, teams, CI/CD, and enterprise features. The goal is a working personal Git hosting foundation. ## Goals - Build a Go-based Git repository hosting platform. - Store bare repositories under `storage/repos/{owner}/{repo}.git`. - Use MySQL for metadata. - Support HTTP Smart Git clone/fetch/push. - Provide CLI-based registration, login, repository management, search, forks, and pull requests. - Support public and private repositories. - Use temporary 7-day API/Git auth tokens. - Keep permissions simple: owner-only writes and private access in MVP. --- ## 1. Product decisions ### Platform shape - Gitocean is a CLI + API Git hosting system. - No Web UI in Phase 1. - No SSH Git transport in Phase 1. - Repositories are stored as bare Git repositories on disk. - Metadata is stored in MySQL. ### Registration and login - Registration is open. - Users register with: - email - username - password - Users can log in with either: - email + password - username + password - Login returns a temporary token that expires after 7 days. - The CLI stores the token locally for API calls. - The CLI can approve the token into Git's credential helper for HTTP Git operations. ### Naming defaults - CLI binary name: `gitocean`. - Default branch: `main`. - Repository names allow lowercase letters, numbers, `.`, `_`, and `-`. - Usernames allow lowercase letters, numbers, `_`, and `-`. - Pull request numbers are scoped per target repository. --- ## 2. Permissions ### Repository visibility Public repositories: - Anyone can clone/fetch. - Only the owner can push. - Only the owner can delete or manage settings. Private repositories: - Only the owner can clone/fetch. - Only the owner can push. - Only the owner can delete or manage settings. ### Writes - Phase 1 uses owner-only writes. - No collaborators, organizations, teams, or fine-grained permissions yet. - Outside collaboration happens through pull requests against public repositories. --- ## 3. Storage layout Repositories live under: ```text storage/repos/{owner}/{repo}.git ``` Example: ```text storage/ repos/ alice/ demo.git/ bob/ project.git/ ``` Each repository directory is a bare Git repository created with `git init --bare`. --- ## 4. MySQL schema Core tables: ### `users` - `id` - `email` - `username` - `password_hash` - `created_at` ### `auth_tokens` - `id` - `user_id` - `token_hash` - `expires_at` - `revoked_at` - `created_at` ### `repositories` - `id` - `owner_user_id` - `name` - `visibility`: `public` or `private` - `forked_from_repository_id` nullable - `created_at` - `updated_at` ### `pull_requests` - `id` - `target_repository_id` - `number` - `author_user_id` - `source_repository_id` - `source_branch` - `target_branch` - `title` - `description` - `status`: `open`, `closed`, or `merged` - `closed_at` nullable - `merged_at` nullable - `created_at` - `updated_at` --- ## 5. API routes ### Auth ```http POST /api/register POST /api/login POST /api/logout GET /api/me ``` ### Repositories ```http POST /api/repos GET /api/repos/search?q=demo&scope=all GET /api/repos/search?q=demo&scope=mine GET /api/repos/{owner}/{repo} DELETE /api/repos/{owner}/{repo}?force=false POST /api/repos/{owner}/{repo}/fork ``` ### Pull requests ```http POST /api/repos/{owner}/{repo}/pulls GET /api/repos/{owner}/{repo}/pulls GET /api/repos/{owner}/{repo}/pulls/{number} POST /api/repos/{owner}/{repo}/pulls/{number}/close POST /api/repos/{owner}/{repo}/pulls/{number}/merge ``` ### Git HTTP ```http /{owner}/{repo}.git/info/refs /{owner}/{repo}.git/git-upload-pack /{owner}/{repo}.git/git-receive-pack ``` --- ## 6. CLI commands ### Server ```bash gitocean server --addr :8080 --dsn 'user:pass@tcp(127.0.0.1:3306)/gitocean?parseTime=true' --storage storage ``` ### Auth ```bash gitocean register gitocean login gitocean logout gitocean whoami ``` ### Repositories ```bash gitocean repo create NAME --public gitocean repo create NAME --private gitocean repo delete OWNER/NAME [--force] gitocean repo search QUERY --all gitocean repo search QUERY --mine gitocean repo fork OWNER/NAME [--name NEW_NAME] ``` ### Clone ```bash gitocean clone OWNER/NAME ``` ### Pull requests ```bash gitocean pr create --from OWNER/REPO:BRANCH --to OWNER/REPO:BRANCH --title TITLE --description DESC gitocean pr create --repo OWNER/REPO --from BRANCH --to BRANCH --title TITLE --description DESC gitocean pr list OWNER/REPO gitocean pr view OWNER/REPO NUMBER gitocean pr close OWNER/REPO NUMBER gitocean pr merge OWNER/REPO NUMBER ``` --- ## 7. Git HTTP behavior Use Git's built-in Smart HTTP backend: ```bash git http-backend ``` Required behavior: - Public clone/fetch works without auth. - Private clone/fetch requires owner auth. - Push always requires auth. - Push is owner-only. - Git username is the account username. - Git password is the 7-day token. --- ## 8. Fork behavior - Logged-in users can fork public repositories. - Private repositories can only be forked by the owner in Phase 1. - Forks are copied as bare repositories under the new owner's storage path. - Fork metadata stores `forked_from_repository_id`. --- ## 9. Pull request rules ### Same-repository PRs - Source and target repository are the same. - Only the repository owner can create same-repo PRs. - Source and target branches must both exist. ### Cross-repository PRs - Source repository branch points to target repository branch. - Source repository must be owned by the PR author. - Target repository must be public, unless the author is also the target owner. - Source and target branches must both exist. - Only the target repository owner can close or merge the PR. --- ## 10. Merge behavior Phase 1 merge mode is a normal merge commit: 1. Clone the target repo into a temporary worktree. 2. Checkout the target branch. 3. Add/fetch the source repo branch. 4. Run `git merge --no-ff FETCH_HEAD`. 5. Push the result back to the target branch. 6. Mark the PR as merged. If conflicts occur: - Return an error. - Keep the PR open. - Do not modify PR status. --- ## 11. Implementation milestones 1. Project scaffold and build setup. 2. MySQL migrations. 3. User registration, login, logout, and token auth. 4. Repository create, delete, detail, and search. 5. HTTP Smart Git integration using `git http-backend`. 6. CLI auth and repository commands. 7. Fork support. 8. Pull request create/list/view/close. 9. Pull request merge. 10. Tests, hardening, and UX polish. --- ## Phase 1 completion criteria Phase 1 is complete when: - The server starts with MySQL metadata storage. - Missing MySQL databases can be created automatically. - Users can register, login, logout, and run `whoami`. - Login tokens expire after 7 days. - Users can create public/private repositories. - Public repositories can be cloned/fetched without auth. - Private repositories require owner auth. - Owners can push over HTTP. - Non-owners cannot push. - Users can search visible repositories. - Users can fork allowed repositories. - Users can create, list, view, close, and merge pull requests. - `go test ./...` passes. - `go vet ./...` passes.