## Why

Photos currently save to the app's local `static/uploads/` (Phase 3). That's lost on a fresh deploy or multi-instance setup, and the admin can't manage them. Phase 6 moves photos to **MinIO** (S3-compatible object storage) — a self-hosted Docker service on .13, consistent with the infra pattern and requiring no cloud dependency.

## What Changes

- **MinIO** container on .13 (API :9000, console :9001, volume-backed) with a `wherewoof` bucket; credentials in a local `.env` (never in the repo).
- **Go frontend**: `UploadPhoto` now PUTs the object to MinIO (`tags/{id}.{ext}`) and stores the serve URL (`/photos/tags/{id}.{ext}`) in `tags.photo_url`. A new `GET /photos/{key...}` route streams the object back (content-type + cache headers). External photo URLs still work unchanged.
- **Laravel admin**: S3 disk (flysystem) pointing at MinIO; Filament `FileUpload` on the Tag resource stores to the same bucket and sets `photo_url` via the frontend's `/photos/` URL.
- **Migration**: copy any existing `static/uploads/*` into MinIO (one-off script).
- **Deploy**: MinIO on .13 (Docker, same host as both apps — no new firewall ports), frontend binary + env (`MINIO_*`), admin `.env` S3 config.

## Capabilities

### New Capabilities

- `photo-object-storage`: MinIO-backed photo storage; uploads + serving via the Go app; photos persist across deploys.

### Modified Capabilities

- `database`: none required (photo_url already exists).
- `tag-management` / admin: photo upload available in the Filament admin.

## Impact

- **On .13**: `/home/sam/Docker/Containers/wherewoof-minio/` (compose + env + volume), bucket `wherewoof`.
- **Go**: `frontend/internal/handlers/tags.go` (UploadPhoto → MinIO), `photo.go` (serve route), `internal/config` (MINIO_* env), `go.mod` (+minio-go), `main.go` (route).
- **Admin**: `config/filesystems.php` s3 disk, `composer require league/flysystem-aws-s3-v3`, TagResource photo field.
- Env: `MINIO_ENDPOINT/ACCESS/SECRET/BUCKET` in `~/.config/where-woof.env` (.13) and `admin/.env`.
