# P1-8 — Gitea Actions CI workflow

Branch: `feat/p1-8-gitea-ci`
Worktree: `.worktrees/feat-p1-8-gitea-ci`

## Why

The repo had one Gitea Actions workflow — `build-push.yaml` — that
builds and pushes a Docker image on push to `main`. There's no test
gate. PRs can land broken code because nothing runs typecheck, lint,
Vitest, or Playwright before merge.

P1-8 from the readiness audit asked for a CI pipeline that runs the
test stack on every PR. This PR adds one.

## Changes

### `.gitea/workflows/ci.yml` (new)

Three jobs:

1. **`server-checks`** — installs `server/`, runs `typecheck`, `lint`,
   `vitest`. Pre-seeds the DB before vitest so the existing test
   suite (which talks to the real DB) has demo data.
2. **`client-checks`** — installs `client/`, runs `typecheck`, `lint`,
   `vitest`. No DB needed.
3. **`e2e`** — depends on both, boots server + client, runs Playwright
   E2E. `continue-on-error: true` for now because the existing
   Playwright suite has one pre-existing failure on dev
   (`paynow-webhook.test.js` "paid_amount undefined" — independent of
   these gates). The flag can come off once that baseline failure is
   fixed.

Triggers on:

- push to `dev`
- pull_request to `main` or `dev`

## Notes / gaps

- The `e2e` job is the only real consumer of secrets; for now it
  uses a CI-only `JWT_SECRET` and `ALLOWED_ORIGINS` since the test
  flows don't depend on real client/auth state beyond the demo
  accounts. Production secrets live elsewhere.
- I've intentionally NOT called the docker `build-push.yaml`. The two
  workflows are independent: `ci` runs on PR, `build-push` runs on
  push to `main`. Promoting dev → main still requires manual approval.

## Verification

- Workflow file passes a YAML lint (no .yamllint in this repo, but
  the structure mirrors the existing `build-push.yaml`).
- All bash steps use `working-directory` consistently — the previous
  build-push workflow assumed `cd` semantics that don't exist in
  Gitea Actions jobs.
