# 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 (60+ routes)
    middleware/               — auth.go, csrf.go, rbac.go, audit.go
    handlers/                 — one file per domain area (see Key Files below)
  domain/
    git/                      — sanitized git binary wrapper (exec.Command only, no shell)
      binary.go               — Run, Log, Tree, Diff, BlobCat, RevParse, etc.
      agit.go                 — AGit ref parsing
    ci/                       — CI/CD execution engine (fully built — Phase 2B)
      orchestrator.go         — NATS-driven DAG orchestrator
      runner_manager.go       — job dispatch with Docker executor
      executor.go             — docker run, log streaming, workspace extraction
      dag.go                  — topological sort, ReadyJobs
      parser.go               — .forgebucket/workflows/*.yml parser
      types.go                — WorkflowFile, WorkflowJob, WorkflowStep structs
    sbom/                     — SBOM generator (fully built — Phase 4)
      generator.go            — CycloneDX 1.4 generation, auto on pipeline success + on-demand
      cyclonedx.go            — CycloneDX document model and helpers
      parsers.go              — Manifest parsers: go.mod, package.json, requirements.txt, Cargo.toml, Gemfile.lock, pom.xml
    scanning/                 — Secret scanner (fully built — Phase 4)
      scanner.go              — Push-triggered regex scanning, listing, dismissal
      secrets.go              — 15 high/medium severity secret patterns (AWS, GitHub, SSH, JWT, etc.)
    vulnscan/                 — Vulnerability scanner (fully built — Phase 4)
      scanner.go              — OSV API-backed dependency vulnerability scanning
      osv.go                  — HTTP client for api.osv.dev/v1
    signing/                  — Artifact signing (fully built — Phase 4)
      keystore.go             — ECDSA P-256 signing and verification, self-verifying bundles
    oci/                      — OCI registry (fully built — Phase 4)
      registry.go             — Content-addressable blob store, upload sessions, OCI Distribution Spec v1.1
    gitops/                   — GitOps controller (fully built — Phase 3D)
      controller.go           — NATS subscriptions, startup, periodic ticker
      drift.go                — CheckDrift, handlePush, periodicCheck
      reconciler.go           — TriggerSync, handleDeploymentSucceeded/Failed
    federation/               — ActivityPub / ForgeFed (fully built — Phase 3F)
      actor.go                — GetOrCreate, ActorJSON, APID, RSA-2048 key gen
      signatures.go           — HTTP signature sign/verify (draft-cavage-http-signatures)
      inbox.go                — Receive, handleFollow (auto-accept), handleAccept, handleUndo
      outbox.go               — Collection builder, StubCollection
      remote.go               — FetchActor (cached), DeliverActivity (signed POST)
  observability/              — Prometheus metrics + health (fully built — Phase 3E)
    metrics.go                — metric definitions, HTTP middleware, NATS watcher
    health.go                 — Check() returning HealthStatus (DB ping + NATS)
  models/                     — XORM structs + 20 migration files
  config/                     — ENV-driven config, fails fast on missing secrets
  events/                     — NATS EventBus interface + NATSBus + NoOpBus (Healthy() bool)
web/                          — //go:embed target for the built React SPA
frontend/
  src/
    pages/                    — 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 → Metrics → CORS → CSRF → SessionAuth → AuditLog → Handler
```

---

## Current Phase Status

| Phase | Scope | Status |
|-------|-------|--------|
| 1 | Auth, Git HTTP, repos, PRs, issues, RBAC, webhooks, LFS, design system | **Complete** |
| 2A | NATS event bus, WebSocket hub, audit log | **Complete** |
| 2B | CI orchestrator, runner manager, Docker executor, artifact registry | **Complete** |
| 2C | Pipeline DAG visualization, dashboard CI upgrade, command palette | **Complete** |
| 3A | Environment model + deployment tracking | **Complete** |
| 3B | Unified operational timeline | **Complete** |
| 3C | Workspaces + secret management (Global → Workspace → Repo → Env) | **Complete** |
| 3D | GitOps controller + drift detection + auto-sync | **Complete** |
| 3E | Observability (Prometheus `/metrics`, structured `/health`, repo health API) | **Complete** |
| 3F | Federation handlers (ActivityPub WebFinger, actor, inbox/outbox, HTTP signatures, Follow/Accept) | **Complete** |
| 4 | SBOM generation, secret scanning, vuln scanning, signed artifacts, OCI registry, security page | **Complete** |
| 5 | AI diagnostics, deployment promotions, rollback visualization | Planned |

---

## 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 CSRF middleware enforces this, but don't remove it from route definitions.
- There is a shared `resolveRepoID(db, w, r)` function in `internal/api/handlers/repo_lookup.go` — use it instead of duplicating repo resolution logic.

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

### Events
- Publish to NATS via `bus.Publish(events.SubjectXxx, payload)` where the subject is a constant from `internal/events/subjects.go`.
- Payload types are in `internal/events/types.go` — use them for type-safe unmarshaling in subscribers.
- `NoOpBus` silently drops events when `NATS_URL` is unset — the app must work normally without NATS.

### 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 `jsonError` / `jsonOK` in `internal/api/handlers/helpers.go`.

---

## 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 (the client does this automatically via `getCSRFToken()`).

---

## What NOT to Do

- **No shell string injection** — see Go conventions above; always discrete `exec.Command` args
- **No hardcoded secrets** — everything via env
- **No skipping CSRF** — all mutating routes require it
- **No arbitrary design values** — `tokens.ts` is the law
- **No new color tokens without discussion** — the existing palette covers all cases
- **No modal-heavy UX** — progressive disclosure; avoid deep modal chains
- **No YAML-centric UI** — pipeline and GitOps config should feel operational, not config-file editing
- **No editing existing migration files** — always add a new numbered migration
- **No direct `fmt.Println` for logging** — use `log.Printf` so structured logs work correctly

---

## 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 work |
| `internal/api/handlers/repo_lookup.go` | Shared `resolveRepoID` helper |
| `internal/models/` | All XORM models + 13 migration files |
| `internal/config/config.go` | All env vars, fail-fast validation |
| `internal/events/subjects.go` | All NATS event subject constants |
| `internal/events/types.go` | Typed event payload structs |
| `internal/domain/git/binary.go` | Git binary wrapper — safe exec patterns, `RevParse`, `BlobCat`, etc. |
| `internal/domain/ci/orchestrator.go` | CI DAG orchestrator |
| `internal/domain/ci/executor.go` | Docker job executor + log streaming |
| `internal/domain/gitops/controller.go` | GitOps reconciliation controller |
| `internal/domain/gitops/drift.go` | `CheckDrift`, drift detection logic |
| `internal/observability/metrics.go` | Prometheus metric defs, HTTP middleware, NATS watcher |
| `internal/observability/health.go` | `Check()` — DB ping + NATS liveness |
| `internal/api/handlers/observability.go` | `/health` + `/repos/.../health` handlers |
| `internal/api/handlers/environment.go` | Environment + deployment CRUD |
| `internal/api/handlers/gitops.go` | GitOps config + drift HTTP endpoints |
| `internal/api/handlers/federation.go` | ActivityPub WebFinger, actor, inbox, outbox, followers/following |
| `internal/domain/federation/actor.go` | Actor lifecycle — GetOrCreate, ActorJSON, key generation |
| `internal/domain/federation/signatures.go` | HTTP signature sign/verify |
| `internal/domain/federation/inbox.go` | Receive + Follow/Accept auto-accept flow |
| `internal/domain/federation/remote.go` | FetchActor (cached remote actors), DeliverActivity |
| `internal/api/handlers/secret.go` | Scoped secret management |
| `internal/api/handlers/workspace.go` | Workspace + member management |
| `internal/api/handlers/secret.go` | Scoped secret management |
| `internal/api/handlers/sbom.go` | SBOM generation + download endpoints |
| `internal/api/handlers/scanning.go` | Secret leak list + dismiss endpoints |
| `internal/api/handlers/vulnscan.go` | Vulnerability scan + dismiss endpoints |
| `internal/api/handlers/oci.go` | OCI Distribution Spec v1.1 registry handler |
| `internal/domain/sbom/generator.go` | SBOM generator (CycloneDX 1.4) |
| `internal/domain/scanning/scanner.go` | Push-triggered secret scanner |
| `internal/domain/vulnscan/scanner.go` | OSV API-backed vulnerability scanner |
| `internal/domain/signing/keystore.go` | ECDSA P-256 artifact signing |
| `internal/domain/oci/registry.go` | Content-addressable OCI blob store |
| `internal/api/middleware/audit.go` | Audit log middleware |
| `frontend/src/ui/tokens.ts` | Design token source of truth |
| `frontend/src/components/AppShell.tsx` | Root layout wrapper |
| `frontend/src/api/client.ts` | Typed API client with CSRF handling |
| `.env.example` | All environment variables with documentation |
| `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 + NATS via Docker Compose
make migrate             # run XORM migrations (currently 020)
make dev                 # Go :8080 + Vite :5173
```

CI execution requires Docker to be running locally. If unavailable, the runner logs a warning and CI jobs are queued but not executed.
