feat: sync multilayer td integration

This commit is contained in:
A 2026-07-15 13:32:06 +08:00
parent 20a310f6ca
commit 766c5db992
491 changed files with 26235 additions and 35340 deletions

View file

@ -13,6 +13,11 @@ var (
// ErrAuthKeyProtocolMetadataConflict 表示同一 cryptographic auth_key_id
// 被尝试改写为另一 key body 或另一 permanent/temp 类型/寿命。
ErrAuthKeyProtocolMetadataConflict = errors.New("auth key protocol metadata conflict")
// ErrAuthKeyNotFound prevents client metadata writes from silently succeeding
// after the protocol key row has already disappeared. auth_keys is the
// authoritative Layer source; an authorization mirror must never advance on
// its own when that primary write did not happen.
ErrAuthKeyNotFound = errors.New("auth key not found")
// ErrAuthKeyNotPermanent 防止 authorization 落到 temporary/legacy-unknown key。
ErrAuthKeyNotPermanent = errors.New("auth key is not permanent")
// ErrAuthKeyBindingInvalid 表示 temp/perm 引用缺失、类型错误,或 binding
@ -38,17 +43,25 @@ type AuthKeyData struct {
// 0 只允许表示 permanent key-1 仅表示 migration 0086 无法证明类型的历史 key
// edge 必须用 -404 拒绝并迫使客户端重握手。key 类型是握手事实,不能由
// authorization 是否存在推断。
ExpiresAt int
Layer int
DeviceModel string
Platform string
SystemVersion string
APIID int
AppVersion string
ExpiresAt int
Layer int
// LayerObservationID globally orders durable explicit Layer observations
// across sessions, processes and restarts. Zero means legacy/no ordered
// evidence; it is still a usable inherited default but cannot outrank a
// positive observation during temp-to-perm identity merge.
LayerObservationID int64
DeviceModel string
Platform string
SystemVersion string
APIID int
AppVersion string
// 用户绑定不在此处auth_key 是协议产物授权auth_key↔user + 设备信息)由 authorization 承载P2
}
type AuthKeyClientInfo struct {
// Layer is the durable last-known default. The RPC boundary validates it
// against the generated profile set before use; stores must preserve the
// exact value and must never clamp a future unsupported Layer.
Layer int
DeviceModel string
Platform string
@ -57,13 +70,44 @@ type AuthKeyClientInfo struct {
AppVersion string
}
// MergeAuthKeyLayerObservations resolves the inherited default when a raw
// temporary key is bound to its permanent identity. Positive observation IDs
// are globally ordered durable evidence. Equal positive IDs must describe the
// same Layer; zero is legacy/unordered and therefore defers to the permanent
// identity. Both rows must be written to the returned tuple atomically.
func MergeAuthKeyLayerObservations(
tempLayer int,
tempObservationID int64,
permLayer int,
permObservationID int64,
) (layer int, observationID int64, err error) {
if tempLayer < 0 || permLayer < 0 || tempObservationID < 0 || permObservationID < 0 ||
(tempObservationID > 0 && tempLayer == 0) ||
(permObservationID > 0 && permLayer == 0) {
return 0, 0, ErrAuthKeySessionLayerInvalid
}
switch {
case tempObservationID > permObservationID:
return tempLayer, tempObservationID, nil
case permObservationID > tempObservationID:
return permLayer, permObservationID, nil
case tempObservationID > 0 && tempLayer != permLayer:
return 0, 0, ErrAuthKeySessionLayerConflict
case tempObservationID > 0:
return tempLayer, tempObservationID, nil
default:
return permLayer, 0, nil
}
}
// AuthKeyStore 持久化 auth key。实现见 store/memory测试替身、store/postgres。
type AuthKeyStore interface {
// Save 保存一条 auth key 记录;同 ID 重试只能保持 key body 与协议类型/寿命不变。
Save(ctx context.Context, k AuthKeyData) error
// Get 按 auth_key_id 查询;不存在时 found=false。
Get(ctx context.Context, id [8]byte) (data AuthKeyData, found bool, err error)
// UpdateClientInfo 合并更新 auth key 的客户端协商元数据。
// UpdateClientInfo 合并更新 auth key 的客户端协商元数据。目标 key 不存在时
// 必须返回 ErrAuthKeyNotFound禁止把缺失 primary 当成成功后继续更新 mirror。
// 空字段不覆盖已有值layer/api_id 为 0 时不覆盖。
UpdateClientInfo(ctx context.Context, id [8]byte, info AuthKeyClientInfo) error
// Delete 删除一条 auth key 记录destroy_auth_key。不存在时静默成功。