package operation_setting import "github.com/heicode/manager/setting/config" // DeviceBindingSetting controls the per-request Ed25519 device-signature // auth introduced to stop sk- token resale. See the plan at // ~/.claude/plans/peaceful-sprouting-crane.md for the full rollout. // // Phase rollout: // P0 RequireGlobal=false — desktop clients opt-in automatically, // legacy bare sk- bearer keeps working // P3 RequireGlobal=true — bare sk- bearer rejected (30 days after P0) type DeviceBindingSetting struct { // Hard cap on how many active device-bound tokens one user can own. // Anything beyond this gets rejected at pair time. 5 covers a typical // dev (laptop + desktop + 2 cloud VMs + 1 CI runner) without leaving // enough headroom for casual reselling. MaxDevicesPerUser int `json:"max_devices_per_user"` // How far apart the client-stamped timestamp and the server clock may // drift before we reject. 120s = 2× the typical NTP drift envelope and // long enough to survive a slow corporate proxy. TimestampWindowMs int64 `json:"timestamp_window_ms"` // How long a nonce stays "burned" in Redis. Must be ≥ the timestamp // window — if it were shorter, a request from the past edge of the // window could replay successfully right after the nonce TTL'd out. NonceTTLSec int `json:"nonce_ttl_sec"` // Global enforcement switch. Flip to true on P3 day to require all // /v1/* relay calls to come from a device-bound token. RequireGlobal bool `json:"require_global"` // Per-feature switch in case we want to lock down only the chat relay // before lockdown. EnforceOnRelay bool `json:"enforce_on_relay"` } var deviceBindingSetting = DeviceBindingSetting{ MaxDevicesPerUser: 5, TimestampWindowMs: 120_000, // 2 minutes NonceTTLSec: 300, // 5 minutes RequireGlobal: false, // P3 will flip this EnforceOnRelay: false, } func init() { config.GlobalConfig.Register("device_binding_setting", &deviceBindingSetting) } // GetDeviceBindingSetting returns the live setting struct. The pointer // lets the admin UI write back through the same config registration. func GetDeviceBindingSetting() *DeviceBindingSetting { return &deviceBindingSetting } func GetMaxDevicesPerUser() int { return GetDeviceBindingSetting().MaxDevicesPerUser } func GetDeviceTimestampWindowMs() int64 { return GetDeviceBindingSetting().TimestampWindowMs } func GetDeviceNonceTTLSec() int { return GetDeviceBindingSetting().NonceTTLSec } func DeviceBindingRequiredGlobally() bool { return GetDeviceBindingSetting().RequireGlobal }