Remove the Go reference server; keep only Rust
CI / Rust (fmt / clippy / test / build) (push) Successful in 1m41s
CI / HTTP/JSON reference + SQLite persistence (push) Successful in 1m16s
CI / Rust (fmt / clippy / test / build) (pull_request) Successful in 47s
CI / HTTP/JSON reference + SQLite persistence (pull_request) Successful in 1m34s

The Go implementation is preserved in the v1.0.0 tag. Its observable
behaviour stays the API reference: responses recorded from the Go server
live in tools/compatibility_expected.txt, and tools/compatibility.py now
compares the Rust server against them (--update re-records after an
intentional change). The Go SQLite schema is frozen in
tests/fixtures/go_schema_v1.sql for the existing-database test.

Move the web client from internal/httpapi/web to web/, drop the Go CI job
and Go version pin, and update README, AGENTS.md and docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
wtandClaude Opus 5.5 committed 2026-10-30 16:27:33 +07:00
1 parent 16dd2a3b3c
commit 10272f3851
33 files changed
+890 -1438

No files matched your search

+2 -9
View File
@@ -23,16 +23,9 @@ Android ───────────┘
## Исходный код
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.
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. Статические файлы из `web/` встроены при компиляции.
Пути сохранённой Go-реализации:
```text
- internal/auth
- internal/config
- internal/database
- internal/httpapi
```
Исходная Go-реализация удалена после v1.0.0 (исходники остались в теге `v1.0.0`). Её наблюдаемое поведение зафиксировано в `tools/compatibility_expected.txt`, а SQLite-схема — в `tests/fixtures/go_schema_v1.sql`; Rust сверяется с обоими в CI.
Конкретные границы package/handler/service/repository нужно сохранять при рефакторинге: перенос кода между слоями не должен менять внешний API.
+5 -20
View File
@@ -2,27 +2,12 @@
Ниже описана серверная модель на основании исходного кода проекта. При изменении schema обновляйте этот документ.
## Найденные определения моделей/schema
## Где определена schema
- internal/database/database.go
- internal/database/database.go
- internal/database/database.go
- internal/config/config.go
- internal/auth/tokens.go
- internal/auth/tokens.go
- internal/httpapi/auth_handlers.go
- internal/httpapi/auth_handlers.go
- internal/httpapi/auth_handlers.go
- internal/httpapi/server.go
- internal/httpapi/server.go
- internal/httpapi/server.go
- internal/httpapi/sync_handler.go
- internal/httpapi/sync_handler.go
- internal/httpapi/sync_handler.go
- internal/httpapi/web.go
- internal/httpapi/server_test.go
- internal/httpapi/server_test.go
- internal/httpapi/server_test.go
- `src/database.rs` — создание и открытие схемы SQLite;
- `tests/fixtures/go_schema_v1.sql` — исходная схема Go-сервера v1.0.0; Rust обязан открывать такие базы без изменений;
- `src/sync.rs` — валидация и сериализация синхронизируемых записей;
- `src/auth.rs` — пользователи, пароли и refresh-сессии.
## Общие сущности
+11 -11
View File
@@ -3,9 +3,9 @@
## Runtime and configuration
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`.
--release`. SQLite is bundled into the executable. The original Go implementation
was removed after v1.0.0; the `v1.0.0` tag still contains its sources for the
migration and rollback below (`go build -o balance-server-go ./cmd/balance-server`).
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
@@ -65,8 +65,9 @@ required. Do not start both implementations against the same database at once.
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.
login, refresh and sync again. Before the Go sources were removed, the
compatibility suite verified takeover and rollback in both directions; Rust still
writes the same schema (`tests/fixtures/go_schema_v1.sql`).
For database corruption or an unrelated failed migration, stop all writers before
restoring the complete backup directory. Restoring an older backup discards
@@ -77,12 +78,11 @@ an active database or delete a Compose volume as part of an upgrade.
## Validation and operations
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.
and `python3 tools/compatibility.py --binary target/release/balance-server`.
The suite uses temporary databases and loopback listeners, compares
API/errors/security headers/assets with the recorded Go reference, tests browser
cookies, pagination, LWW, tombstones, concurrent pushes, token expiration, refresh
rotation, rate limiting, and SQLite persistence across restarts.
Keep regular encrypted backups with retention and restore drills. Monitor HTTP
5xx, sync errors, authentication failures, latency, database/change-log growth
+8 -9
View File
@@ -2,28 +2,26 @@
## Требования
Production-сервер использует Rust 1.90+ и bundled SQLite. Go 1.25+ нужен для сохранённой эталонной реализации; differential-проверки (`tools/compatibility.py`) требуют Go 1.27.3, как в CI: поведение `net/http` (например, код редиректа ServeMux 301/307) зависит от версии Go. Python 3 используется без сторонних пакетов.
Сервер использует Rust 1.90+ и bundled SQLite. Python 3 нужен для `tools/compatibility.py` и используется без сторонних пакетов. Go больше не нужен.
Проверить локальную версию:
```bash
rustc --version
cargo --version
go version
python3 --version
```
## Установка зависимостей
```bash
cargo fetch --locked
go mod download
```
## Сборка
```bash
cargo build --locked
go build ./...
```
## Тесты
@@ -32,13 +30,15 @@ go build ./...
cargo test --locked
cargo build --locked
python3 tools/compatibility.py
go test ./...
```
С race detector:
`tools/compatibility.py` запускает сервер на временных портах и базах и сравнивает
ответы API и статику с ответами исходного Go-сервера, записанными в
`tools/compatibility_expected.txt`. Расхождение означает изменение, видимое
клиентам. Если изменение намеренное, проверьте diff и перезапишите эталон:
```bash
go test -race ./...
python3 tools/compatibility.py --update
```
## Static checks
@@ -46,7 +46,6 @@ go test -race ./...
```bash
cargo fmt --check
cargo clippy --locked --all-targets -- -D warnings
go vet ./...
```
Если в проекте есть Makefile/CI, его команды имеют приоритет как canonical build pipeline.
@@ -89,7 +88,7 @@ cargo clippy --locked --all-targets -- -D warnings
↓
cargo build --locked --release
↓
python3 tools/compatibility.py --rust-binary target/release/balance-server
python3 tools/compatibility.py --binary target/release/balance-server
↓
container/package
↓
+1 -1
View File
@@ -14,7 +14,7 @@
<rect width="512" height="512" fill="url(#bg)"/>
<!-- Wallet, scaled up from internal/httpapi/web/icon.svg -->
<!-- Wallet, scaled up from web/icon.svg -->
<g transform="translate(-34 -46) scale(1.12)">
<path d="M141 173c0-25 20-45 45-45h140c25 0 45 20 45 45v18H186c-25 0-45 20-45 45v-63Z" fill="#fff" opacity=".5"/>
<path d="M116 222c0-28 23-51 51-51h179c28 0 51 23 51 51v126c0 28-23 51-51 51H167c-28 0-51-23-51-51V222Z" fill="url(#shine)"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

+1 -1
View File
@@ -45,7 +45,7 @@
<g transform="translate(297 400)"><rect x="-48" y="-19" width="96" height="38" rx="19" fill="#1f1f2b" stroke="#3b3b55"/><text y="6">Web</text></g>
</g>
<!-- App icon (internal/httpapi/web/icon.svg) -->
<!-- App icon (web/icon.svg) -->
<g transform="translate(384 272) scale(.5)" filter="url(#shadow)">
<rect x="28" y="28" width="456" height="456" rx="128" fill="url(#iconbg)"/>
<path d="M141 173c0-25 20-45 45-45h140c25 0 45 20 45 45v18H186c-25 0-45 20-45 45v-63Z" fill="#fff" opacity=".5"/>

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

+1 -1
View File
@@ -45,7 +45,7 @@
<g transform="translate(114 320)"><rect x="-44" y="-17" width="88" height="34" rx="17" fill="#1f1f2b" stroke="#3b3b55"/><text y="5">Web</text></g>
</g>
<!-- App icon (internal/httpapi/web/icon.svg) -->
<!-- App icon (web/icon.svg) -->
<g transform="translate(180 200) scale(.46875)" filter="url(#shadow)">
<rect x="28" y="28" width="456" height="456" rx="128" fill="url(#iconbg)"/>
<path d="M141 173c0-25 20-45 45-45h140c25 0 45 20 45 45v18H186c-25 0-45 20-45 45v-63Z" fill="#fff" opacity=".5"/>

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB