Directus (Billing Backend)
Сервис биллинга на базе Directus с PostgreSQL. Расположен в
billing/в корне монорепозитория.
Бизнес-модель
Privacy-first: никакого трекинга использования, телеметрии, сбора данных об устройствах или объёме хранилища.
Нет тарифов и переключения планов. Пользователь покупает конкретные продукты по мере необходимости.
При установке приложения пользователь получает все функции бесплатно: P2P синхронизация, E2E шифрование, неограниченные устройства и пространства. Никакой записи в биллинге не создаётся.
Продукты, которые можно купить:
| Категория | Пример | Тип оплаты | Что даёт |
|---|---|---|---|
| Cloud Storage | Cloud 1 GB, Cloud 1 TB | Подписка ($/мес или $/год) | Kontinuum-managed S3 хранилище определённого объёма |
| Relay VPS | Relay Server | Подписка ($/мес или $/год) | Managed relay-сервер для P2P соединений |
| App License | Kontinuum Pro | Подписка ($/мес или $/год) | Профессиональная версия: подключение своих облачных провайдеров |
Бесшовный переход
- Установил приложение → всё работает бесплатно (P2P sync, шифрование)
- Нужно облачное хранилище? → Оформил подписку «Cloud 10 GB» — получил S3 credentials
- Нужен relay? → Оформил подписку «Relay VPS» — получил адрес сервера
- Нужны свои облака (AWS, Timeweb)? → Оформил подписку Pro
Покупки независимы друг от друга. Можно оформить только хранилище, только relay, или и то и другое.
Что НЕ ограничивается
- Количество устройств
- Количество пространств (Spaces)
- Объём локальных данных
- P2P синхронизация между устройствами
- End-to-end шифрование
Схема данных
Схема хранится в billing/snapshots/billing-schema.yaml и управляется через Directus snapshot mechanism.
Коллекции
products
Каталог продуктов. Не создаётся автоматически — заполняется администратором.
| Поле | Тип | Описание |
|---|---|---|
name | string | Отображаемое имя (Cloud 1 GB, Relay VPS, Kontinuum Pro) |
slug | string | Уникальный идентификатор (cloud_1gb, relay_vps, pro) |
category | enum | cloud_storage / relay_vps / app_license |
billing_interval | enum | monthly / yearly |
price | decimal | Цена за интервал |
currency | enum | USD / EUR / RUB |
cloud_storage_gb | integer | Объём хранилища в GB (только для cloud_storage) |
customers
Клиенты, привязанные к Kontinuum identity.
| Поле | Тип | Описание |
|---|---|---|
kontinuum_identity_id | string | Публичный ключ Ed25519 из Identity (уникальный) |
name | string | Имя пользователя |
email | string | Email для счетов и уведомлений |
status | enum | active / suspended |
metadata | json | Произвольные данные (ID у внешнего платёжного провайдера и т.д.) |
purchases
Подписки клиентов на продукты. Все продукты — рекуррентные, с биллинговым циклом.
| Поле | Тип | Описание |
|---|---|---|
customer_id | FK → customers | Клиент |
product_id | FK → products | Продукт |
coupon_id | FK → coupons | Применённый купон (опционально) |
status | enum | active / expired / cancelled |
activated_at | timestamp | Дата начала подписки |
current_period_start | timestamp | Начало текущего биллингового периода |
current_period_end | timestamp | Конец текущего периода (дата следующего платежа) |
cancelled_at | timestamp | Дата отмены (если отменена) |
s3_credentials | json | Провиженные S3 credentials (endpoint, bucket, access_key_id) |
vps_details | json | Адрес и порт relay-сервера (host, port, region) |
invoices
Счета с детализацией.
| Поле | Тип | Описание |
|---|---|---|
invoice_number | string | Уникальный номер (INV-2026-0001) |
customer_id | FK → customers | Клиент |
purchase_id | FK → purchases | Связанная подписка |
subtotal / discount / total | decimal | Суммы |
currency | enum | Валюта |
status | enum | draft / open / paid / overdue / void |
line_items | json | Детализация [{description, quantity, unit_price, amount}] |
payments
Платёжные транзакции.
| Поле | Тип | Описание |
|---|---|---|
invoice_id | FK → invoices | Счёт |
customer_id | FK → customers | Клиент |
payment_method_id | FK → payment_methods | Метод оплаты |
amount / currency | decimal / enum | Сумма и валюта |
status | enum | pending / succeeded / failed / refunded |
provider | string | Платёжный провайдер (stripe, creem и т.д.) |
provider_transaction_id | string | ID транзакции у провайдера |
payment_methods
Методы оплаты клиента.
| Поле | Тип | Описание |
|---|---|---|
customer_id | FK → customers | Клиент |
type | enum | card / bank_transfer / crypto |
last_four | string | Последние 4 цифры карты |
provider / provider_payment_method_id | string | Провайдер и его ID |
is_default | boolean | Метод оплаты по умолчанию |
coupons
Промокоды и скидки.
| Поле | Тип | Описание |
|---|---|---|
code | string | Уникальный код |
discount_type | enum | percentage / fixed |
discount_value | decimal | Размер скидки (0-100% или фиксированная сумма) |
max_redemptions | integer | Макс. использований (null = безлимит) |
valid_from / valid_until | timestamp | Период действия |
applicable_products | json | Массив product ID (null = все продукты) |
Инфраструктура
Стек
- Directus 11 — headless CMS с REST и GraphQL API
- PostgreSQL 16 (PostGIS) — основная БД
- Redis 7 — кэш и pub/sub
- Docker Compose для локальной разработки
Структура проекта
billing/
├── docker-compose.yml # Directus + PostgreSQL + Redis
├── snapshots/
│ └── billing-schema.yaml # Directus schema snapshot (source of truth)
├── extensions/ # Directus extensions (hooks, endpoints, flows)
├── uploads/ # Загруженные файлы (gitignored)
├── scripts/
│ └── init.sh # Инициализация: ожидание готовности, схема, project owner
├── .env.example # Шаблон переменных окружения
├── .gitignore
├── project.json # Nx project config
└── README.md # Краткий readme со ссылкой на эту страницуNx Commands
| Команда | Описание |
|---|---|
nx run billing:up | Запустить все контейнеры |
nx run billing:down | Остановить контейнеры |
nx run billing:init | Применить схему + настроить project owner (ждёт готовности) |
nx run billing:restart | Перезапустить Directus |
nx run billing:logs | Логи Directus (follow) |
nx run billing:snapshot:export | Экспорт текущей схемы в YAML |
nx run billing:snapshot:apply | Применить схему из YAML |
nx run billing:reset | Пересоздать контейнеры и данные + применить схему |
Quick Start
# 1. Создать .env из примера
cp billing/.env.example billing/.env
# 2. Запустить сервисы
nx run billing:up
# 3. Дождаться запуска и применить схему
nx run billing:init
# 4. Открыть админку
open http://localhost:8055
# Логин: admin@kontinuum.dev / adminAPI
Directus автоматически предоставляет API для всех коллекций:
- REST:
http://localhost:8055/items/{collection} - GraphQL:
http://localhost:8055/graphql - Admin UI:
http://localhost:8055/admin
Примеры запросов
# Получить токен
TOKEN=$(curl -s -X POST http://localhost:8055/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"admin@kontinuum.dev","password":"admin"}' \
| jq -r '.data.access_token')
# Список продуктов
curl -s http://localhost:8055/items/products \
-H "Authorization: Bearer $TOKEN"
# Создать продукт
curl -s -X POST http://localhost:8055/items/products \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "Cloud 10 GB",
"slug": "cloud_10gb",
"category": "cloud_storage",
"billing_interval": "monthly",
"price": 1.99,
"currency": "USD",
"cloud_storage_gb": 10
}'
# Подписки клиента (с данными продукта)
curl -s 'http://localhost:8055/items/purchases?filter[customer_id][_eq]=CUSTOMER_UUID&fields=*,product_id.*' \
-H "Authorization: Bearer $TOKEN"Workflow изменения схемы
- Внеси изменения через админку Directus (Data Model)
- Экспортируй схему:bash
nx run billing:snapshot:export - Проверь diff в
billing/snapshots/billing-schema.yaml - Закоммить обновлённый snapshot