# AGENTS.md — ForgeBucket AI Agent Guide

This file is for AI coding agents (Claude Code, GitHub Copilot, etc.) working in this repository. Read it before making changes.

---

## Mission

ForgeBucket is a **unified operating system for software delivery** — not a Git repository viewer with CI attached. The guiding philosophy:

> Repositories are runtime systems. The dashboard is a command center. GitOps is first-class.

Every feature decision should answer: does this reduce cognitive load? Does this improve operational awareness? Does this improve developer flow?

The full product vision lives in [`ai_agent_master_prompt_for_building_modern_git_platform.md`](ai_agent_master_prompt_for_building_modern_git_platform.md).

---

## Architecture Map

```
cmd/forgebucket/          — binary entry point (main.go)
internal/
  api/
    router.go             — Chi router, all route definitions (~26 routes)
    middleware/           — auth, CSRF, RBAC, logging
    handlers/             — one file per domain (repo, pr, issue, auth, user, ssh...)
  domain/
    git/                  — sanitized git binary wrapper (exec.Command only, no shell)
    federation/           — ActivityPub / ForgeFed (DATA LAYER ONLY — no handlers yet)
    ci/                   — CI orchestrator (EMPTY — Phase 2 stub)
  models/                 — XORM structs + 7 migration files
  config/                 — ENV-driven config, fails fast on missing secrets
web/                      — //go:embed target for the built React SPA
frontend/
  src/
    pages/                — 20 route-level page components
    components/           — shared UI (AppShell, Sidebar, Header, DiffViewer, etc.)
    ui/
      tokens.ts           — SINGLE SOURCE OF TRUTH for all design tokens
    hooks/                — custom React hooks
    api/                  — typed API client (fetch wrappers)
```

**Middleware chain — this order is fixed, do not reorder:**
```
Logger → RealIP → Recoverer → CORS → CSRF → SessionAuth → RBAC → Handler
```

---

## Current Phase Status

Understand the phases before adding code — don't build Phase 3 infrastructure when Phase 2 is incomplete.

| Phase | Scope | Status |
|-------|-------|--------|
| 1 | Auth, Git HTTP, repos, PRs, issues, RBAC, webhooks, LFS, design system, 20-page SPA | **Complete** |
| 2A | NATS event bus, WebSocket hub upgrade, audit log | **Complete** |
| 2B | CI orchestrator, runner manager, Docker executor, artifact registry | **Complete** |
| 2C | Pipeline DAG visualization, dashboard CI upgrade, command palette wiring | **Complete** |
| 3A | Environment model + deployment tracking | **Active** |
| 3B | Unified operational timeline | Planned |
| 3C | Secret management hierarchy | Planned |
| 3D | GitOps controller + drift detection | Planned |
| 3E | Observability (Prometheus, health sparklines) | Planned |
| 3F | Federation handlers (ActivityPub inbox/outbox) | Planned |
| 4 | AI diagnostics, signed artifacts, OCI registry, secret/dep scanning | Planned |

Do not implement Phase 3+ features without explicit discussion. The `domain/federation/` directory is an intentional stub — the data model exists but no HTTP handlers should be wired until Phase 3F.

### Phase 3A — What to Build

Backend and frontend are both net-new for Phase 3A. Nothing exists yet.

**Backend:**
1. `internal/models/environment.go` — `Environment` (id, repoId, name, url, protectionRules JSON) + `Deployment` (id, envId, repoId, sha, ref, status, triggeredBy, description, runId, startedAt, finishedAt)
2. `internal/models/migrations/010_environments.go` — `Run010()` syncing both structs; call from `001_init.go`
3. `internal/api/handlers/environment.go` — `ListEnvironments`, `CreateEnvironment`, `GetEnvironment`, `UpdateEnvironment`, `DeleteEnvironment`, `ListDeployments`, `CreateDeployment`, `UpdateDeploymentStatus`; publish `deployment.*` NATS events
4. `internal/api/router.go` — wire routes under `/{owner}/{repo}/environments` and `/{owner}/{repo}/environments/{envName}/deployments`

**Frontend:**
5. `frontend/src/types/api.ts` — add `Environment`, `Deployment`, `DeployStatus` types
6. `frontend/src/api/queries/environments.ts` — `useEnvironments`, `useEnvironment`, `useCreateEnvironment`, `useUpdateEnvironment`, `useDeleteEnvironment`, `useDeployments`, `useCreateDeployment`, `useUpdateDeploymentStatus`
7. `frontend/src/pages/EnvironmentsPage.tsx` — environment cards each showing latest deployment status, SHA, who deployed, time; "New environment" flow; deployment history per env
8. `frontend/src/components/layout/Sidebar.tsx` — add `Environments` nav item between Pipelines and Settings in `RepoSubNav`
9. `frontend/src/pages/RepoPage.tsx` — surface deployment status badges in the repo header (latest deploy per env at a glance)
10. `frontend/src/App.tsx` — add route `repos/:owner/:repo/environments`

---

## Go Conventions

### Git commands — critical rule
Always use `exec.Command("git", arg1, arg2, ...)` with **discrete arguments**. Never build a shell string from user input.

```go
// CORRECT
cmd := exec.Command("git", "clone", "--bare", repoURL, destPath)

// WRONG — never do this
cmd := exec.Command("sh", "-c", "git clone "+userInput)
```

This rule is non-negotiable. It prevents command injection.

### Router / handlers
- Chi router. Route definitions in `internal/api/router.go`.
- One handler file per domain area. Keep handlers thin — business logic belongs in domain packages.
- All POST/PUT/DELETE routes require `X-CSRF-Token` header matching the session cookie. The middleware enforces this, but don't remove it from routes.

### Database
- XORM for all DB access. Structs in `internal/models/`.
- Migrations are numbered files in `internal/models/migrations/`. Always add a new migration file; never edit existing ones.
- No raw SQL strings built from user input.

### Secrets and config
- All secrets come from environment variables via `internal/config/`.
- Never hardcode secrets, tokens, or credentials anywhere.
- `SESSION_SECRET` ≥ 32 chars. `CSRF_SECRET` = exactly 32 chars.

### Error handling
- Return errors up the call stack. Don't swallow them silently.
- HTTP handlers use consistent JSON error responses — follow the pattern in existing handlers.

---

## TypeScript / React Conventions

### Design tokens — critical rule
All spacing, color, and sizing values must come from `frontend/src/ui/tokens.ts`. Do not introduce new hardcoded pixel values or color hex codes.

```tsx
// CORRECT — use token classes via Tailwind
<div className="p-sm gap-xs">

// WRONG — arbitrary values
<div style={{ padding: "12px" }}>
```

### Grid system
- Base unit: 8px. All spacing is multiples of 4px (`xs`) or 8px (`sm`).
- Touch targets: 44px minimum height/width on all interactive elements (buttons, links, icon buttons).

### Dark mode
- Use Tailwind v4 `@variant dark` — not hardcoded dark: classes unless inside a component that explicitly handles both.
- Colors must work in both light and dark modes. Test both.

### Component patterns
- `AppShell` wraps all authenticated pages. Don't bypass it.
- `Sidebar` has three states: expanded (320px), collapsed (56px), mobile bottom bar. Respect all three.
- Mobile-first: design for 375px, enhance for 1440px. Use the `BottomTabBar` for mobile nav — don't add new nav patterns.
- Loading states: use `Skeleton` components for perceived performance, not spinners.
- Mobile code review: use the `MobileComment` bottom-sheet pattern — not modals.

### API calls
- Use the typed API client in `frontend/src/api/` — don't write raw `fetch` calls in components.
- Always include `X-CSRF-Token` header on mutating requests.

---

## What NOT to Do

- **No shell string injection** — see Go conventions above
- **No hardcoded secrets** — everything via env
- **No skipping CSRF** — all mutating routes require it
- **No arbitrary design values** — tokens.ts is the law
- **No Phase 3+ features without discussion** — don't wire up GitOps, federation handlers, or the command palette until Phase 2 is complete
- **No new color tokens** — if the design requires a new color, discuss it; don't invent one
- **No modal-heavy UX** — this platform uses progressive disclosure; avoid deep modal chains
- **No YAML-centric UI** — pipeline and environment config should feel operational, not config-file editing

---

## Testing

```bash
make test     # Go tests (go test ./...) + Vitest (frontend unit tests)
make lint     # go vet + ESLint
```

- Go: test files live alongside source files (`*_test.go`)
- Frontend: Vitest for unit tests, component tests alongside components
- All UI changes must be manually verified at 1440px desktop and 375px mobile

---

## Key Files Reference

| File | Purpose |
|------|---------|
| `internal/api/router.go` | All route definitions — start here for backend |
| `internal/models/` | XORM models + migrations — all DB schemas |
| `internal/config/config.go` | Env-driven config, required vars |
| `internal/domain/git/` | Git binary wrapper — safe exec patterns |
| `frontend/src/ui/tokens.ts` | Design token source of truth |
| `frontend/src/components/AppShell.tsx` | Root layout wrapper |
| `frontend/src/components/Sidebar.tsx` | 3-state navigation sidebar |
| `frontend/src/pages/` | All 20 route-level pages |
| `frontend/src/api/` | Typed API client |
| `.env.example` | All required environment variables |
| `CLAUDE.md` | Developer guide (rules overlap with this file — CLAUDE.md takes precedence on conflicts) |

---

## Running Locally

```bash
cp .env.example .env     # fill SESSION_SECRET and CSRF_SECRET
make docker-up           # PostgreSQL via Docker Compose
make migrate             # run XORM migrations
make dev                 # Go :8080 + Vite :5173
```
