added rust server
Build Unsigned iOS and macOS Apps / Build Unsigned iOS IPA (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build macOS ZIP (push) Canceled after 0s

This commit is contained in:
wt committed 2026-10-29 18:05:24 +07:00
1 parent a2aa714a83
commit b32eabcd12
21 files changed
+5199 -143

No files matched your search

+2 -2
View File
@@ -23,9 +23,9 @@ Android ───────────┘
## Исходный код
Текущая кодовая база содержит 9 Go-файлов.
Production runtime — один Rust-процесс: `src/main.rs`, `runtime.rs`, `config.rs`, `database.rs`, `auth.rs`, `sync.rs`, `server.rs`, `go_json.rs`. SQLite bundled через rusqlite; HTTP обслуживается axum/hyper. `runtime.rs` сохраняет socket deadlines Go (header 5s, read 15s, write 30s, idle 60s) и ограничивает graceful shutdown десятью секундами. `go_json.rs` сохраняет особенности encoding/json и исходные payload bytes. Статические файлы из `internal/httpapi/web` встроены при компиляции. Go-код сохранён как эталон совместимости и вариант rollback.
Пути:
Пути сохранённой Go-реализации:
```text
- internal/auth
+69 -92
View File
@@ -1,108 +1,85 @@
# Deployment
## Компоненты
## Runtime and configuration
```text
Internet
│
HTTPS
│
▼
Reverse proxy / Load Balancer
│
▼
BalanceServer
│
▼
Database
```
The production executable is the Rust server, built with `cargo build --locked
--release`. SQLite is bundled into the executable. The Go implementation remains
in `cmd/balance-server` and `internal/` as a compatibility reference and rollback
option; build it with `go build -o balance-server-go ./cmd/balance-server`.
## Configuration
The Dockerfile uses a Rust 1.90 Debian Bookworm builder and a Debian Bookworm slim
runtime, running as the unprivileged `balance` user. The image embeds the existing
web client and uses no separate frontend process. Build dependencies and SQLite
are compiled at image build time.
The numeric identity remains UID 100 / GID 101, matching the original Alpine Go
image, so existing volume permissions are preserved across the switch.
Все environment variables и flags должны задаваться через deployment environment, а не hard-code в Go.
`docker compose up -d --build` publishes **http://localhost:8123** (host 8123,
container 8080). `GET /health` is the liveness endpoint. Direct binary execution
uses `:8080` by default. Place a TLS reverse proxy in front of the published port
for remote access; pass `X-Forwarded-Proto: https` to enable Secure session cookies.
Перед production deployment составьте список переменных, которые реально читает текущий код:
| Variable | Default | Purpose |
| --- | --- | --- |
| `BALANCE_ADDR` | `:8080` | HTTP listen address |
| `BALANCE_DB_PATH` | `./data/balance.db` | SQLite file; Docker uses `/data/balance.db` |
| `BALANCE_JWT_SECRET` | required | At least 32 characters; retain across migration |
| `BALANCE_ACCESS_TTL` | `15m` | Go-style duration for access tokens |
| `BALANCE_REFRESH_TTL` | `720h` | Go-style duration for refresh tokens |
| `BALANCE_ALLOW_REGISTRATION` | `true` | Enable creation of accounts |
| `BALANCE_CORS_ORIGINS` | empty | Comma-separated allowed browser origins |
```text
- docker-compose.yml
- docker-compose.yml
- docker-compose.yml
- go.mod
- README.md
- README.md
- README.md
- Dockerfile
- Dockerfile
- Dockerfile
- internal/database/database.go
- internal/database/database.go
- internal/database/database.go
- internal/config/config.go
- internal/config/config.go
- internal/config/config.go
- internal/auth/tokens.go
- internal/auth/tokens.go
- internal/auth/tokens.go
- internal/auth/password.go
```
Inject secrets through the deployment environment or `.env`; never put them in
images or source control. Compose preserves the existing named `balance-data`
volume mounted at `/data`. Keep that volume and its project name when upgrading.
## Docker
## Go to Rust migration
Если репозиторий содержит Dockerfile/compose, используйте их как canonical deployment recipe.
1. Build and validate the Rust binary/image before stopping production. Retain the
previous Go executable/image and exact environment for rollback.
2. Stop the Go service and confirm no other process writes its SQLite database.
3. Back up the entire database directory, including `balance.db` and any
`balance.db-wal`/`balance.db-shm` files. Protect the backup as financial data.
Record the existing environment securely, especially `BALANCE_JWT_SECRET`.
4. Start Rust with the **same database path/volume and JWT secret**. The schema is
unchanged: startup creates missing tables and indexes without rewriting
existing accounts, records, change sequences or refresh-token hashes.
5. Check `/health`, login with an existing account, refresh an existing session,
and sync a device with its saved cursor. Verify another device receives edits
and tombstones. Inspect error rates without logging credentials or tokens.
Не включайте secrets в Docker image.
The existing Argon2id password hashes, HS256 JWT claims, hashed refresh tokens,
RFC3339 timestamps, entity versions and global change sequences are shared with
Go. No export/import, cursor reset, account recreation or forced sign-out is
required. Do not start both implementations against the same database at once.
## Health/readiness
## Rollback
Если проект предоставляет health endpoint, load balancer должен использовать его для readiness.
Stop Rust first. Start the retained Go executable/image with the same current
database directory and secret. Rust-written accounts, password hashes, refresh
sessions, records, tombstones and cursors remain readable by Go. Check health,
login, refresh and sync again. The compatibility suite exercises both directions,
including a second takeover back to the original implementation.
Database connectivity желательно проверять отдельно от liveness.
For database corruption or an unrelated failed migration, stop all writers before
restoring the complete backup directory. Restoring an older backup discards
changes after that backup and may require clients to resynchronize; prefer normal
binary rollback against the current database when it is healthy. Never overwrite
an active database or delete a Compose volume as part of an upgrade.
## Database migrations
## Validation and operations
Migration должна выполняться контролируемо:
Before release run `cargo test --locked`, `cargo build --locked --release`,
`python3 tools/compatibility.py --rust-binary target/release/balance-server`, and
the retained reference checks `go test ./...`, `go vet ./...`, `go build ./...`.
The differential suite uses temporary databases and loopback listeners, compares
API/errors/security headers/assets, tests browser cookies, pagination, LWW,
tombstones, concurrent pushes, token expiration, refresh rotation, rate limiting,
and shared-database takeover/rollback in both directions.
```text
backup
↓
migration
↓
health check
↓
application rollout
```
Не запускайте destructive migration автоматически без backup/rollback plan.
## Backups
Финансовые данные — пользовательские данные высокой ценности.
Минимум:
- регулярные DB backups;
- retention policy;
- периодическая проверка restore;
- encrypted backup storage.
## Observability
Рекомендуется мониторить:
- HTTP 5xx;
- auth failures;
- sync failures;
- latency;
- DB latency/errors;
- active users/devices;
- size/lag of sync change log;
- disk/storage usage.
## Release checklist
- [ ] Tests green.
- [ ] Database migrations проверены.
- [ ] Backup создан.
- [ ] Secrets injected через secure mechanism.
- [ ] HTTPS включён.
- [ ] Health checks работают.
- [ ] Sync tested with both mobile clients.
- [ ] Rollback plan готов.
Keep regular encrypted backups with retention and restore drills. Monitor HTTP
5xx, sync errors, authentication failures, latency, database/change-log growth
and free disk space. The in-memory limiter allows 30 registration/login/refresh
attempts per remote IP per minute and resets on restart; use proxy controls when
operating a public service. Application logs must never include passwords,
Authorization headers or tokens.
+28 -15
View File
@@ -2,29 +2,36 @@
## Требования
Проект использует Go 1.25.0.
Production-сервер использует Rust 1.90+ и bundled SQLite. Go 1.25+ нужен для сохранённой эталонной реализации и differential-проверок. Python 3 используется без сторонних пакетов.
Проверить локальную версию:
```bash
rustc --version
cargo --version
go version
```
## Установка зависимостей
```bash
cargo fetch --locked
go mod download
```
## Сборка
```bash
cargo build --locked
go build ./...
```
## Тесты
```bash
cargo test --locked
cargo build --locked
python3 tools/compatibility.py
go test ./...
```
@@ -37,6 +44,8 @@ go test -race ./...
## Static checks
```bash
cargo fmt --check
cargo clippy --locked --all-targets -- -D warnings
go vet ./...
```
@@ -48,24 +57,24 @@ go vet ./...
Не коммитьте реальные credentials.
Пример общего workflow:
Собрать и запустить Rust-сервер:
```bash
go mod download
go test ./...
go build ./...
./<server-binary>
cargo build --locked --release
export BALANCE_JWT_SECRET="replace-with-a-long-random-secret"
export BALANCE_DB_PATH="./data/balance.db"
./target/release/balance-server
```
Имя binary и обязательные env vars определяются текущей entrypoint/config реализацией.
По умолчанию сервер слушает `:8080`. Файл `.env` читает Docker Compose; при
прямом запуске переменные нужно передать процессу через окружение.
## Database
Перед первым запуском:
1. поднять требуемую БД;
2. применить migrations, если проект их использует;
3. задать connection settings;
4. проверить health/startup logs.
SQLite встроен в executable. При первом запуске сервер создаёт каталог,
таблицы и индексы автоматически. Отдельный процесс БД не нужен. При переходе
с Go сохраните существующий файл БД и `BALANCE_JWT_SECRET`; подробная
процедура и откат описаны в [DEPLOYMENT.md](DEPLOYMENT.md).
## Production
@@ -74,11 +83,13 @@ go build ./...
```text
source
↓
go test ./...
cargo fmt --check && cargo test --locked
↓
go vet ./...
cargo clippy --locked --all-targets -- -D warnings
↓
go build ./...
cargo build --locked --release
↓
python3 tools/compatibility.py --rust-binary target/release/balance-server
↓
container/package
↓
@@ -105,3 +116,5 @@ health check
- concurrent sync с двух устройств;
- login/refresh после истечения access token;
- delete → pull на другом устройстве.
Production build: `cargo build --locked --release`. Прямой запуск: `BALANCE_JWT_SECRET=<secret> target/release/balance-server`, порт 8080. Docker Compose публикует порт 8123 и сохраняет прежний volume `/data`. Процедура миграции Go → Rust и rollback: [DEPLOYMENT.md](DEPLOYMENT.md).