# Woodpecker CI Configuration for Mosaic Stack

## Pipeline Architecture

Split per-package pipelines with path filtering. Only affected packages rebuild on push.

```
.woodpecker/
├── api.yml           # @mosaic/api (NestJS)
├── web.yml           # @mosaic/web (Next.js)
├── orchestrator.yml  # @mosaic/orchestrator (NestJS)
├── coordinator.yml   # mosaic-coordinator (Python/FastAPI)
├── infra.yml         # postgres + openbao Docker images
├── codex-review.yml  # AI code/security review (PRs only)
├── README.md
└── schemas/
    ├── code-review-schema.json
    └── security-review-schema.json
```

## Path Filtering

| Pipeline           | Triggers On                                         |
| ------------------ | --------------------------------------------------- |
| `api.yml`          | `apps/api/**`, `packages/**`, root configs          |
| `web.yml`          | `apps/web/**`, `packages/**`, root configs          |
| `orchestrator.yml` | `apps/orchestrator/**`, `packages/**`, root configs |
| `coordinator.yml`  | `apps/coordinator/**`                               |
| `infra.yml`        | `docker/**`                                         |
| `codex-review.yml` | All PRs (no path filter)                            |

**Root configs** = `pnpm-lock.yaml`, `pnpm-workspace.yaml`, `turbo.json`, `package.json`

## Security Chain

Every pipeline follows the full security chain required by the CI/CD guide:

```
source scanning (lint + pnpm audit / bandit + pip-audit)
  -> docker build (Kaniko)
  -> container scanning (Trivy: HIGH,CRITICAL)
  -> package linking (Gitea registry)
```

Docker builds gate on ALL quality + security steps passing.

## Pipeline Dependency Graphs

### Node.js Apps (api, web, orchestrator)

```
install -> [security-audit, lint, prisma-generate*]
prisma-generate* -> [typecheck, prisma-migrate*]
prisma-migrate* -> test
[all quality gates] -> build -> docker-build -> trivy -> link
```

_\*prisma steps: api.yml only_

### Coordinator (Python)

```
install -> [ruff-check, mypy, security-bandit, security-pip-audit, test]
[all quality gates] -> docker-build -> trivy -> link
```

### Infrastructure

```
[docker-build-postgres, docker-build-openbao]
-> [trivy-postgres, trivy-openbao]
-> link
```

## Docker Images

| Image              | Registry Path                                   | Context             |
| ------------------ | ----------------------------------------------- | ------------------- |
| stack-api          | `git.mosaicstack.dev/mosaic/stack-api`          | `.` (monorepo root) |
| stack-web          | `git.mosaicstack.dev/mosaic/stack-web`          | `.` (monorepo root) |
| stack-orchestrator | `git.mosaicstack.dev/mosaic/stack-orchestrator` | `.` (monorepo root) |
| stack-coordinator  | `git.mosaicstack.dev/mosaic/stack-coordinator`  | `apps/coordinator`  |
| stack-postgres     | `git.mosaicstack.dev/mosaic/stack-postgres`     | `docker/postgres`   |
| stack-openbao      | `git.mosaicstack.dev/mosaic/stack-openbao`      | `docker/openbao`    |

## Image Tagging

| Condition        | Tag                        | Purpose                    |
| ---------------- | -------------------------- | -------------------------- |
| Always           | `${CI_COMMIT_SHA:0:8}`     | Immutable commit reference |
| `main` branch    | `latest`                   | Current production release |
| `develop` branch | `dev`                      | Current development build  |
| Git tag          | tag value (e.g., `v1.0.0`) | Semantic version release   |

## Required Secrets

Configure in Woodpecker UI (Settings > Secrets):

| Secret           | Scope             | Purpose                                     |
| ---------------- | ----------------- | ------------------------------------------- |
| `gitea_username` | push, manual, tag | Gitea registry auth                         |
| `gitea_token`    | push, manual, tag | Gitea registry auth (`package:write` scope) |
| `codex_api_key`  | pull_request      | Codex AI reviews                            |

## Codex AI Review Pipeline

The `codex-review.yml` pipeline runs independently on all PRs:

- **Code review**: Correctness, code quality, testing, performance
- **Security review**: OWASP Top 10, hardcoded secrets, injection flaws

Fails on blockers or critical/high severity security findings.

### Local Testing

```bash
~/.claude/scripts/codex/codex-code-review.sh --uncommitted
~/.claude/scripts/codex/codex-security-review.sh --uncommitted
```

## Troubleshooting

### "unauthorized: authentication required"

- Verify `gitea_username` and `gitea_token` secrets in Woodpecker
- Verify token has `package:write` scope

### Trivy scan fails with HIGH/CRITICAL

- Check if the vulnerability is in the base image (not our code)
- Add to `.trivyignore` if it's a known, accepted risk
- Use `--ignore-unfixed` (already set) to skip unfixable CVEs

### Package linking returns 404

- Normal for recently pushed packages — retry logic handles this
- If persistent: verify package name matches exactly (case-sensitive)

### Pipeline runs Docker builds on pull requests

- Docker build steps have `when: branch: [main, develop]` guards
- PRs only run quality gates, not Docker builds
