fix(router): CloudEdgeRegister 接入频率限流,复用 AuthRegisterRateLimit 死常量 - #2185
Merged
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
DeliciousBuding
force-pushed
the
fix/cloud-edge-register-ratelimit
branch
from
September 1, 2026 16:47
45a7d50 to
618f8ac
Compare
Co-authored-by: Cursor <cursor@vectorcontrol.tech>
DeliciousBuding
force-pushed
the
fix/cloud-edge-register-ratelimit
branch
from
September 1, 2026 16:58
618f8ac to
da20c63
Compare
This was referenced Sep 1, 2026
DeliciousBuding
added a commit
that referenced
this pull request
Sep 1, 2026
#2185 只给 /cloud/edge/register 接了路由级限流,/edge/devices/register (edge 组,已认证 + desktop 设备型检查)仍无频率门禁。按同一形状补齐: middleware.RateLimit(cacheClient, AuthRegisterRateLimit, AuthRateLimitWindow, IPKey)。Redis 故障走非认证路径语义(/edge/* 不在 /client/auth/ 下, AGENTHUB_RATE_LIMIT_FAIL_OPEN 默认 fail-open)。 测试:TestEdgeDeviceRegisterRateLimitedByIP(miniredis + 真 desktop JWT, device_id claim 与请求体一致以过 handler 交叉校验),连打第 4 次 429 + Retry-After,异 IP 放行。openapi 同步 /edge/devices/register 429 响应。 Co-authored-by: Cursor <cursor@vectorcontrol.tech>
DeliciousBuding
added a commit
that referenced
this pull request
Sep 1, 2026
现状:device.Register 无条件 UpsertDevice,device_id 由调用方自选 UUID, 认证用户可无限注册 cloud_edge 设备(#2154 F16 登记项,#2185 路由限流只 管频率不管存量)。 实现: - config:DefaultMaxCloudEdgeDevicesPerUser=50(constants.go)+ AGENTHUB_MAX_CLOUD_EDGE_DEVICES env 覆盖(config_env.go 函数式,同 RateLimitFailOpen 模式);未设/非法回默认(非法带 warn 日志),<= 0 关闭。 - repository:CountDevicesByUserAndType + DeviceExistsForUser(COUNT 现有 devices 表,无迁移/无 schema 变更)+ sqlmock 测试。 - service:Register 在 UpsertDevice 前仅对 cloud_edge 判额——已存在同 device_id 的同用户同型设备(upsert 命中自己)视为刷新不受限;新 device_id 达上限返回新错误码。 - 错误码语义选 403 而非 429:这是「凭证有效但策略拒绝」的存量配额 (codes.go 状态码原则 403 类别),不是时间窗限流,重试无意义, conventions.md 的 429 专属 rate_limited 且必须带 Retry-After。 测试:service(达上限拒绝/刷新不受限/用户间独立/env 覆盖与禁用/ desktop 不受影响)、handler(403 + envelope code 透传两条注册路由)、 config(默认/合法/非法回退)。同步:openapi 403/429 响应 + 配额描述, 05-deployment.md 配置面索引加 env 行。 Co-authored-by: Cursor <cursor@vectorcontrol.tech>
DeliciousBuding
added a commit
that referenced
this pull request
Sep 1, 2026
* fix(router): /edge/devices/register 接入 IP 频率限流,与 CloudEdgeRegister 同型 #2185 只给 /cloud/edge/register 接了路由级限流,/edge/devices/register (edge 组,已认证 + desktop 设备型检查)仍无频率门禁。按同一形状补齐: middleware.RateLimit(cacheClient, AuthRegisterRateLimit, AuthRateLimitWindow, IPKey)。Redis 故障走非认证路径语义(/edge/* 不在 /client/auth/ 下, AGENTHUB_RATE_LIMIT_FAIL_OPEN 默认 fail-open)。 测试:TestEdgeDeviceRegisterRateLimitedByIP(miniredis + 真 desktop JWT, device_id claim 与请求体一致以过 handler 交叉校验),连打第 4 次 429 + Retry-After,异 IP 放行。openapi 同步 /edge/devices/register 429 响应。 Co-authored-by: Cursor <cursor@vectorcontrol.tech> * feat(device): cloud_edge 设备每用户数量上限(新错误码 device_limit_exceeded) 现状:device.Register 无条件 UpsertDevice,device_id 由调用方自选 UUID, 认证用户可无限注册 cloud_edge 设备(#2154 F16 登记项,#2185 路由限流只 管频率不管存量)。 实现: - config:DefaultMaxCloudEdgeDevicesPerUser=50(constants.go)+ AGENTHUB_MAX_CLOUD_EDGE_DEVICES env 覆盖(config_env.go 函数式,同 RateLimitFailOpen 模式);未设/非法回默认(非法带 warn 日志),<= 0 关闭。 - repository:CountDevicesByUserAndType + DeviceExistsForUser(COUNT 现有 devices 表,无迁移/无 schema 变更)+ sqlmock 测试。 - service:Register 在 UpsertDevice 前仅对 cloud_edge 判额——已存在同 device_id 的同用户同型设备(upsert 命中自己)视为刷新不受限;新 device_id 达上限返回新错误码。 - 错误码语义选 403 而非 429:这是「凭证有效但策略拒绝」的存量配额 (codes.go 状态码原则 403 类别),不是时间窗限流,重试无意义, conventions.md 的 429 专属 rate_limited 且必须带 Retry-After。 测试:service(达上限拒绝/刷新不受限/用户间独立/env 覆盖与禁用/ desktop 不受影响)、handler(403 + envelope code 透传两条注册路由)、 config(默认/合法/非法回退)。同步:openapi 403/429 响应 + 配额描述, 05-deployment.md 配置面索引加 env 行。 Co-authored-by: Cursor <cursor@vectorcontrol.tech> --------- Co-authored-by: DeliciousBuding <DeliciousBuding@users.noreply.github.com> Co-authored-by: Cursor <cursor@vectorcontrol.tech>
DeliciousBuding
added a commit
that referenced
this pull request
Sep 3, 2026
…und-NN 8 处删除但保留 issue 与日期锚点、1 处畸形 Windows 路径夹具修正(16 文件净 0 行,历史暴露面已量化未清洗) (#2284) * test(edge): 公开面脱敏:测试夹具中的个人名 Ding/ding 改为中性 Example/example Co-authored-by: Cursor <cursor@vectorcontrol.tech> * chore(edge): 清理测试注释中的 round-NN 内部编号(保留 issue 锚点) Co-authored-by: Cursor <cursor@vectorcontrol.tech> * chore(hub): 注释去除 round-NN 内部编号(保留 #2185 锚点) Co-authored-by: Cursor <cursor@vectorcontrol.tech> * docs(public): 文档移除 round-NN 内部编号(保留 issue/日期锚点) Co-authored-by: Cursor <cursor@vectorcontrol.tech> * test(app): 公开面脱敏:夹具显示名 Ding 改 Alice,修正畸形 Windows 路径 Co-authored-by: Cursor <cursor@vectorcontrol.tech> --------- Co-authored-by: DeliciousBuding <DeliciousBuding@users.noreply.github.com> Co-authored-by: Cursor <cursor@vectorcontrol.tech>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POST /cloud/edge/register(CloudEdgeRegister)接入 per-IP 频率限流:middleware.RateLimit(cacheClient, config.AuthRegisterRateLimit, config.AuthRateLimitWindow, middleware.IPKey),即每 IP 每 1 分钟最多 3 次,复用此前全仓零引用的死常量AuthRegisterRateLimit = 3(接线后注释自然成真,常量不再死)。形状与/client/auth/refresh、OIDC 三条路由既有限流完全一致。动机(#2154 F16 取证)
hub-server/internal/router/router.go:cloud.POST("/edge/register", ...)只挂authMW.Handler()+RequireHubSession(),无middleware.RateLimit;对照组为同文件auth.POST("/refresh", middleware.RateLimit(...), ...)。hub-server/internal/config/constants.go:119-120:AuthRegisterRateLimit = 3全仓零引用(死常量)。Scope
middleware.RateLimit/isAuthPath/ constants 数值。测试证据
新增路由级测试
TestCloudEdgeRegisterRateLimitedByIP(hub-server/internal/router/router_test.go,SetupRoutes 全链路 + miniredis + hub-local JWT + stub DeviceService):AuthRegisterRateLimit)全部 200(穿过 auth→限流→handler 全链);Retry-After;门禁(本地全绿):
go vet ./hub-server/...、go test ./internal/router/ ./internal/middleware/ ./internal/handler/ ./internal/config/、make test(hub+edge 全量)、verify-doc-ssot.py、git diff --check、verify-ci-gates.py、verify-i18n-deadkeys.py、verify-openapi-contract.py(156 routes,0 新增违规)、verify-migration-idempotency.py、verify-test-sleep-ratchet.py、verify-conventions.py、verify-hub-pure-packages.py、verify-hub-layering.py、check-secrets.sh --range、verify-commit-messages.sh。注:本地
verify-hub-lint-ratchet.py报 2 条jwtutilG101 findings,在未改动的 master(ef7d9ea)上逐字复现(本机 gosec 版本漂移,与本 diff 无关),以 CI 固定工具链为准。Redis 故障弱失败说明(必读)
isAuthPath(internal/middleware/global_rate_limit.go:58-61)只认/client/auth/前缀,/cloud/edge/register不在其中 → Redis 故障时该限流器走非鉴权分支:遵循AGENTHUB_RATE_LIMIT_FAIL_OPEN(默认 fail-open,带X-Rate-Limit-Degraded: true与 warn 日志)。这是防滥用限流可接受的弱失败(鉴权本身不受影响,Redis 故障时设备注册仍要过 auth+hub-session 门禁),与 api/conventions.md 限流故障语义一致。后续项
/edge/devices/register(桌面端注册)同样无频率限流,同类问题登记为后续。Closes 关联:#2154 F16 项(单片安全加固 round-40)。