# Service Center — core Это **core**-сервис модульной платформы сервисного центра: ремонт и продажа техники, заправка картриджей, физ/юр лица. Core владеет только тем, что обязано быть общим — staff-идентичностью (JWT) и реестром модулей. Бизнес-логика (приём в ремонт, склад, заказы) живёт в отдельных модулях-сервисах, которые регистрируются здесь. **Модули (каждый — отдельный репозиторий/рантайм):** | Модуль | Статус | Репозиторий | |--------|--------|-------------| | core (этот репозиторий) | ✅ Фаза 0 | `service-center` | | production (приём в ремонт, Kanban, гарантия) | ✅ первая версия зарегистрирована | `production` | | site (публичный лендинг) | ✅ зарегистрирован, heartbeat здоровый | `site` | | online-store (продажа техники) | ✅ уже в проде, не подключён к реестру | `online-store` | Название/домен всей платформы ещё не выбраны — репозиторий и internal-хосты временно называются `service-center`. ## Стек core - Go + Fiber, PostgreSQL (pgx/v5 + goose), MinIO - Auth: JWT (роли owner/manager/master), без публичной регистрации — первый owner бутстрапится из `OWNER_*` env при пустой `staff_users` ## Контракт модуля Модуль — независимый сервис (свой рантайм, своя БД). Чтобы подключиться к core: 1. Owner создаёт запись модуля: `POST /api/modules` (JWT owner) с телом `{"name", "base_url", "health_path"?, "metadata"?}`. Ответ отдаёт `token` **один раз** — сохранить в `MODULE_TOKEN` модуля, core хранит только его hash. 2. Модуль периодически шлёт `POST /api/modules/:name/heartbeat` с заголовком `X-Module-Token: ` и телом `{"status": "healthy"|"unhealthy"}`. Core не ходит к модулям сам — статус только push (модули могут жить в разных сетях/хостингах, core не обязан до них достучаться). 3. Для проверки staff-токена модуль верифицирует JWT тем же `JWT_SECRET` (HS256, общий секрет, см. `.env.example`) — своего auth-сервиса у модуля нет. 4. Управление: `GET /api/modules` (список+статус), `DELETE /api/modules/:name` (отозвать) — оба owner-only. ## Разработка ```bash docker network create platform_net # once — shared with module repos, see Контракт модуля cp .env.example .env # заполнить секреты + OWNER_* для первого владельца docker compose up -d --build curl http://127.0.0.1:18090/api/health ``` На хосте с несколькими проектами backend слушает только `127.0.0.1:18090` — наружу отдаёт хостовый системный Caddy (`/etc/caddy/Caddyfile`), когда появится домен. `Caddyfile` в корне репо — для отдельного standalone-VPS деплоя, где у этого проекта есть весь хост (порты 80/443) для себя. ## Дорожная карта 0 — Инфраструктура + реестр модулей ✅ (этот коммит) → 1 — модуль `production` (MVP приём в ремонт) → 2 — Документы юрлиц → 3 — Заправка картриджей → 4 — `online-store` регистрируется как модуль → 5 — Склад → 6 — AI-приёмка → 7 — Касса → 8 — Telegram-бот → 9 — Аналитика → 10 — доп.