8dcb50a07c
Предыдущий проход сделал правильным порядок «сначала долговременная запись, потом разрыв сессии» и правильно запретил откат при неудаче разрыва. Способа прийти к согласованному состоянию ПОТОМ он не дал: у двух операций повтор не работал вовсе. Импорт, заменивший auth_id: после неудавшегося /kick старое значение не хранится нигде, повтор того же файла читает из базы уже новое и рвёт его, а cron пропускал незнакомый authID молча — dao.ListPeer просто не возвращала строку. Живая сессия оставалась навсегда. Снижение maxDevices: повтор формы даёт 1 < 1 -> false, разрыва больше нет. Лимит устройств в политику доступа не входит и входить не должен — это свойство сессий, — поэтому механизма схождения у него не было. enforcePeerAccess стал сверкой живых сессий: обход идёт по каждому authID из /online. Нет строки в базе -> kick; peerAccessDenied -> kick; непригодный maxDevices -> kick; устройств больше разрешённого -> kick. Отказ базы при этом не рвёт ничего. Ни таблицы отложенных операций, ни очереди retry: список живых сессий уже есть, и это /online. Отдельно закрыт второй TOCTOU лимита устройств. Учёт выданных разрешений закрыл сравнение двух одинаковых снимков, но сетевой запрос выполнялся вне блокировки, поэтому снимки приходили в резервацию в произвольном порядке и устаревший откатывал lastOnline назад, возвращая уже занятое место. Это не data race — память защищена мьютексом, и -race здесь молчит принципиально. Последовательность «прочитать /online -> занять место» выполняется под замком по authId; глобальный замок не годится, внутри идёт сетевой запрос. Учёт разрешений больше не растёт бесконечно: запись снималась только на ветке отказа, поэтому в карте копились удалённые пиры и переписанные импортом идентификаторы. Уборка идёт по фактической картине подключений. Гейты приёмки доращены под все три инварианта и проверены в обе стороны. Go 1.26.7 -> 1.26.8. Документация приведена в соответствие в двух местах, где описывала снятую архитектуру. Разбор: docs/acceptance/2026-09-02-v1.0.0-rc3-preflight-findings.md
90 lines
4.4 KiB
Modula-2
90 lines
4.4 KiB
Modula-2
module hy2xs-admin
|
||
|
||
// Языковая версия держится ниже GO_VERSION из versions.env: сборка проверяет
|
||
// это шагом verify_go_toolchain_contract. 1.21 здесь стояла с поколения, в
|
||
// котором она ещё поддерживалась; к v1 её линия давно вне поддержки, а вместе
|
||
// с ней в бинарь попадала соответствующая stdlib.
|
||
go 1.25.0
|
||
|
||
// toolchain объявляет, каким компилятором проект собирается на самом деле.
|
||
//
|
||
// Директива `go` выше — это языковой baseline модуля, и она НЕ выбирает
|
||
// компилятор: с ней одной локальный `go build` на 1.25 проходил успешно, хотя
|
||
// релизный бинарь собирается версией из versions.env и наследует её stdlib.
|
||
// Номер здесь не повторяется намеренно — он живёт строкой ниже и в
|
||
// GO_VERSION, а третья копия в прозе устаревала бы на каждом patch-релизе. То
|
||
// есть
|
||
// разработчик и сборка проверяли разный код, а расхождение не было видно ни в
|
||
// одном из выводов.
|
||
//
|
||
// Значение обязано совпадать с GO_VERSION из versions.env; это проверяет
|
||
// verify_go_toolchain_contract, а `tools/dev/doctor` показывает то же
|
||
// расхождение локально, до сборки.
|
||
toolchain go1.26.8
|
||
|
||
require (
|
||
github.com/didip/tollbooth v4.0.2+incompatible
|
||
github.com/gin-gonic/gin v1.12.0
|
||
github.com/glebarez/sqlite v1.11.0
|
||
github.com/go-playground/validator/v10 v10.30.3
|
||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||
github.com/robfig/cron/v3 v3.0.1
|
||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||
github.com/sirupsen/logrus v1.10.2
|
||
github.com/spf13/cobra v1.10.2
|
||
golang.org/x/crypto v0.55.0
|
||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||
gopkg.in/yaml.v3 v3.0.1
|
||
gorm.io/gorm v1.31.2
|
||
)
|
||
|
||
require (
|
||
github.com/bytedance/gopkg v0.1.4 // indirect
|
||
github.com/bytedance/sonic v1.15.3 // indirect
|
||
github.com/bytedance/sonic/loader v0.5.2 // indirect
|
||
github.com/cloudwego/base64x v0.1.7 // indirect
|
||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||
github.com/gabriel-vasile/mimetype v1.4.15 // indirect
|
||
github.com/gin-contrib/sse v1.1.1 // indirect
|
||
github.com/glebarez/go-sqlite v1.23.0 // indirect
|
||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||
github.com/go-playground/locales v0.14.1 // indirect
|
||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||
github.com/goccy/go-json v0.10.6 // indirect
|
||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||
github.com/google/uuid v1.6.0 // indirect
|
||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||
github.com/jinzhu/now v1.1.5 // indirect
|
||
github.com/json-iterator/go v1.1.12 // indirect
|
||
github.com/klauspost/cpuid/v2 v2.4.0 // indirect
|
||
github.com/leodido/go-urn v1.5.0 // indirect
|
||
github.com/mattn/go-isatty v0.0.24 // indirect
|
||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||
github.com/pelletier/go-toml/v2 v2.4.3 // indirect
|
||
github.com/quic-go/qpack v0.6.0 // indirect
|
||
github.com/quic-go/quic-go v0.61.0 // indirect
|
||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||
github.com/spf13/pflag v1.0.10 // indirect
|
||
github.com/tklauser/go-sysconf v0.4.0 // indirect
|
||
github.com/tklauser/numcpus v0.12.0 // indirect
|
||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||
github.com/ugorji/go/codec v1.3.2 // indirect
|
||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||
go.mongodb.org/mongo-driver/v2 v2.8.2 // indirect
|
||
golang.org/x/arch v0.30.0 // indirect
|
||
golang.org/x/net v0.58.0 // indirect
|
||
golang.org/x/sys v0.47.0 // indirect
|
||
golang.org/x/text v0.41.0 // indirect
|
||
golang.org/x/time v0.15.0 // indirect
|
||
google.golang.org/protobuf v1.36.12 // indirect
|
||
modernc.org/libc v1.75.6 // indirect
|
||
modernc.org/mathutil v1.7.1 // indirect
|
||
modernc.org/memory v1.12.1 // indirect
|
||
modernc.org/sqlite v1.57.0 // indirect
|
||
)
|