Files
ds-galo/openspec/changes/shared-album/tasks.md
T
iu 2b2b342492 feat: implement shared-album multi-user photo album
Backend (Go/Gin/pgx): env config, pgx pool with retries, Garage S3 client
(path-style, region garage), embedded golang-migrate migrations, JWT auth with
refresh rotation, albums CRUD, members/roles/invites with no-escalation matrix,
photo upload + async imaging/goexif WebP variants, cursor pagination, presigned
URLs, likes/comments, SSE hub (album + personal), notifications, share links.

Frontend (SvelteKit 2 + Svelte 5 + Tailwind v4): API wrapper with 401 refresh,
auth store, all screens, Uploader/PhotoGrid/Lightbox/Comments, SSE client with
reconnect + REST catch-up, three themes + system via data-theme.

Deploy without Docker: Makefile builds the frontend into backend/static and
embeds it (go:embed) into a single statically linked binary; systemd unit and
nginx SSE example included.

Use gen2brain/webp (-tags nodynamic) instead of cgo kolesa-team/go-webp to keep
CGO_ENABLED=0 static builds; design.md/proposal.md updated accordingly.
2026-10-10 12:50:33 +03:00

69 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks
## 1. Скелет проекта и подключения
- [x] 1.1 Создать структуру `backend/` (cmd/server, internal/*) и `frontend/` (SvelteKit 2 + Svelte 5 + adapter-static + Tailwind), Makefile, `.env.example`, `deploy/shared-album.service`; проверить наличие ожидаемых файлов и что `make frontend` собирает статику
- [x] 1.2 Реализовать `internal/config` — чтение всех env (PG_*, S3_*, JWT_*, HTTP_*, SSE_*); проверить парсинг запуском бинарника с `.env.example`
- [x] 1.3 Подключение к `pg.localnet` через pgx с ретраями; проверить `GET /api/health` возвращает 200 при доступной БД
- [x] 1.4 Клиент S3 к Garage (AWS SDK v2, `region=garage`, `UsePathStyle=true`, BaseEndpoint) и создание бакета при отсутствии; проверить health-check пингует S3
## 2. Миграции и репозитории
- [x] 2.1 Добавить golang-migrate и миграции для таблиц: users, albums, album_members, invites, photos, comments, likes, notifications, share_links, refresh_tokens; проверить `make migrate` применяет схему к pg.localnet
- [x] 2.2 Реализовать базовые репозитории на pgx (users, albums); проверить юнит-тесты CRUD на тестовой БД
- [x] 2.3 Репозитории album_members, invites, share_links, refresh_tokens; проверить тесты на инвайт-токены и роли
## 3. Аутентификация
- [x] 3.1 `POST /api/auth/register` и `/login` с bcrypt и выдачей access (15 мин) + refresh (30 дней, хэш в refresh_tokens); проверить curl-сценарии регистрации/входа
- [x] 3.2 `POST /api/auth/refresh` с ротацией refresh-токена и `POST /api/auth/logout` с отзывом; проверить повторный refresh отозванным токеном возвращает 401
- [x] 3.3 JWT-middleware для защиты эндпоинтов, кроме `/api/auth/*` и share; проверить доступ без/с токеном
## 4. Альбомы и участники
- [x] 4.1 CRUD альбомов (`GET/POST /api/albums`, `GET/PATCH/DELETE /api/albums/:id`) с владельцем из owner_id; проверить сценарии создания и удаления альбома
- [x] 4.2 Инвайты (`POST /api/albums/:id/invites`, `POST /api/invites/:token/accept`) с ролями и лимитом использований; проверить принятие и истечение инвайта
- [x] 4.3 Роли и права на уровне сервиса (матрица прав, правило «нет эскалации», `PATCH/DELETE /api/albums/:id/members/:user_id`); проверить отклонение эскалации прав тестами
## 5. Загрузка и просмотр фото
- [x] 5.1 Загрузка фото в Garage (single + batch) со стримингом и генерацией thumb/preview/original; проверить загрузку одного и пачки файлов
- [x] 5.2 Конвейер изображений: imaging (resize) + go-webp (WebP-энкод) + goexif (EXIF); проверить создание thumb 200px и preview 1200px с EXIF-полями
- [x] 5.3 Листинг `GET /api/albums/:id/photos?cursor=&limit=` и `GET /api/photos/:id` с presigned URL (1 час); проверить cursor-пагинацию и выдачу свежих URL
- [x] 5.4 Скачивание `GET /api/photos/:id/download` и удаление `DELETE /api/photos/:id`; проверить права на удаление (своё/чужое)
## 6. Лайки и комментарии
- [x] 6.1 Лайки (`POST/DELETE /api/photos/:id/likes`); проверить поставить/убрать лайк
- [x] 6.2 Комментарии (`GET/POST /api/photos/:id/comments`, `DELETE /api/comments/:id`); проверить добавление, список и удаление комментария
## 7. SSE real-time
- [x] 7.1 SSE-хаб на каналах (map по album_id, неблокирующая публикация, backpressure) и `GET /api/sse/albums/:id`; проверить подключение и heartbeat 25 сек
- [x] 7.2 Публикация событий photo.created/photo.deleted/comment.created/like.added/like.removed/member.joined/member.left/album.updated из сервисов; проверить получение события при новом фото
- [x] 7.3 Авторизация SSE через `?token=` и проверка доступа к альбому; проверить отклонение подписки на чужой альбом
## 8. Уведомления
- [x] 8.1 Создание уведомлений при комментариях/лайках/добавлении в альбом; проверить запись в таблицу notifications
- [x] 8.2 `GET /api/sse/me` (персональный поток) и отметка уведомлений прочитанными; проверить получение персонального события и смену статуса read_at
## 9. Ссылки для просмотра
- [x] 9.1 Создание/отзыв share-ссылок (`POST/DELETE /api/albums/:id/share`) с expires_at и несколькими ссылками; проверить создание и точечный отзыв
- [x] 9.2 Публичные эндпоинты `/api/share/:token` (просмотр, листинг, скачивание одиночного) без авторизации; проверить доступ по действующему и отклонение по истёкшему/отозванному токену
## 10. Frontend SvelteKit
- [x] 10.1 API-обёртка (fetch) и auth-store с автообновлением при 401; проверить логин/регистрацию в браузере
- [x] 10.2 Экраны: список альбомов, страница альбома, участники, настройки, принятие инвайта; проверить навигацию по альбомам
- [x] 10.3 Uploader (drag&drop, прогресс), PhotoGrid (ленивая загрузка), Lightbox (свайпы); проверить загрузку и просмотр фото
- [x] 10.4 SSE-клиент (EventSource + reconnect/backoff + догон по REST) и live-обновление сетки/комментариев; проверить live-появление фото
- [x] 10.5 Три темы (light/dark/neutral) + system через data-theme, store на runes, ThemeSwitcher; проверить переключение без вспышки
## 11. Сборка и деплой
- [x] 11.1 Сборка frontend в статику, копирование в `backend/static`, `go:embed`, сборка одного бинарника (`CGO_ENABLED=0`); проверить `make build` даёт один артефакт
- [x] 11.2 systemd-юнит с EnvironmentFile и харденингом, пример nginx для SSE (`proxy_buffering off`); проверить запуск бинарника и подключение к нему
- [x] 11.3 README с инструкцией сборки, деплоя и запуска через systemd; проверить команды из README выполняются