Skip to content

Directus (Billing Backend)

Сервис биллинга на базе Directus с PostgreSQL. Расположен в billing/ в корне монорепозитория.

Бизнес-модель

Privacy-first: никакого трекинга использования, телеметрии, сбора данных об устройствах или объёме хранилища.

Нет тарифов и переключения планов. Пользователь покупает конкретные продукты по мере необходимости.

При установке приложения пользователь получает все функции бесплатно: P2P синхронизация, E2E шифрование, неограниченные устройства и пространства. Никакой записи в биллинге не создаётся.

Продукты, которые можно купить:

КатегорияПримерТип оплатыЧто даёт
Cloud StorageCloud 1 GB, Cloud 1 TBПодписка ($/мес или $/год)Kontinuum-managed S3 хранилище определённого объёма
Relay VPSRelay ServerПодписка ($/мес или $/год)Managed relay-сервер для P2P соединений
App LicenseKontinuum 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.

Коллекции

plantuml Diagram

products

Каталог продуктов. Не создаётся автоматически — заполняется администратором.

ПолеТипОписание
namestringОтображаемое имя (Cloud 1 GB, Relay VPS, Kontinuum Pro)
slugstringУникальный идентификатор (cloud_1gb, relay_vps, pro)
categoryenumcloud_storage / relay_vps / app_license
billing_intervalenummonthly / yearly
pricedecimalЦена за интервал
currencyenumUSD / EUR / RUB
cloud_storage_gbintegerОбъём хранилища в GB (только для cloud_storage)

customers

Клиенты, привязанные к Kontinuum identity.

ПолеТипОписание
kontinuum_identity_idstringПубличный ключ Ed25519 из Identity (уникальный)
namestringИмя пользователя
emailstringEmail для счетов и уведомлений
statusenumactive / suspended
metadatajsonПроизвольные данные (ID у внешнего платёжного провайдера и т.д.)

purchases

Подписки клиентов на продукты. Все продукты — рекуррентные, с биллинговым циклом.

ПолеТипОписание
customer_idFK → customersКлиент
product_idFK → productsПродукт
coupon_idFK → couponsПрименённый купон (опционально)
statusenumactive / expired / cancelled
activated_attimestampДата начала подписки
current_period_starttimestampНачало текущего биллингового периода
current_period_endtimestampКонец текущего периода (дата следующего платежа)
cancelled_attimestampДата отмены (если отменена)
s3_credentialsjsonПровиженные S3 credentials (endpoint, bucket, access_key_id)
vps_detailsjsonАдрес и порт relay-сервера (host, port, region)

invoices

Счета с детализацией.

ПолеТипОписание
invoice_numberstringУникальный номер (INV-2026-0001)
customer_idFK → customersКлиент
purchase_idFK → purchasesСвязанная подписка
subtotal / discount / totaldecimalСуммы
currencyenumВалюта
statusenumdraft / open / paid / overdue / void
line_itemsjsonДетализация [{description, quantity, unit_price, amount}]

payments

Платёжные транзакции.

ПолеТипОписание
invoice_idFK → invoicesСчёт
customer_idFK → customersКлиент
payment_method_idFK → payment_methodsМетод оплаты
amount / currencydecimal / enumСумма и валюта
statusenumpending / succeeded / failed / refunded
providerstringПлатёжный провайдер (stripe, creem и т.д.)
provider_transaction_idstringID транзакции у провайдера

payment_methods

Методы оплаты клиента.

ПолеТипОписание
customer_idFK → customersКлиент
typeenumcard / bank_transfer / crypto
last_fourstringПоследние 4 цифры карты
provider / provider_payment_method_idstringПровайдер и его ID
is_defaultbooleanМетод оплаты по умолчанию

coupons

Промокоды и скидки.

ПолеТипОписание
codestringУникальный код
discount_typeenumpercentage / fixed
discount_valuedecimalРазмер скидки (0-100% или фиксированная сумма)
max_redemptionsintegerМакс. использований (null = безлимит)
valid_from / valid_untiltimestampПериод действия
applicable_productsjsonМассив 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

bash
# 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 / admin

API

Directus автоматически предоставляет API для всех коллекций:

  • REST: http://localhost:8055/items/{collection}
  • GraphQL: http://localhost:8055/graphql
  • Admin UI: http://localhost:8055/admin

Примеры запросов

bash
# Получить токен
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 изменения схемы

  1. Внеси изменения через админку Directus (Data Model)
  2. Экспортируй схему:
    bash
    nx run billing:snapshot:export
  3. Проверь diff в billing/snapshots/billing-schema.yaml
  4. Закоммить обновлённый snapshot