fix(v2): TokenAuth V2 path must call SetupContextForToken

V2 chat returned HTTP 403 with body
  {"error":{"type":"new_api_error","message":"record not found ..."}}
even after Manager body_decrypt and Ed25519 verify both passed and the
device row was found. Root cause: the V2 dispatch in TokenAuth set
`id` + `token_id` directly via VerifyV2DeviceSignedRequest, called
applyTokenPolicyAndContext for IP/user/group checks, then jumped to
c.Next() — skipping SetupContextForToken entirely.

SetupContextForToken populates eight more keys the downstream relay
and billing pipeline expect:
  token_key, token_name, token_unlimited_quota, token_quota,
  token_model_limit_enabled, token_model_limit,
  ContextKeyTokenGroup, ContextKeyTokenCrossGroupRetry

Without them, channel distribute / pre-consume / log_consume
silently misroute and a generic "record not found" leaks out as 403.
The legacy bearer path didn't have this bug because it always
finished with SetupContextForToken before c.Next().

Verified with /tmp/v2_probe2.js (after this deploys): POST
/v1/messages with full V2 envelope returns HTTP 200 with the model's
reply body.
This commit is contained in:
2026-05-21 03:50:04 +08:00
parent 52549bb2af
commit 67225fd67e
+10
View File
@@ -335,6 +335,16 @@ func TokenAuth() func(c *gin.Context) {
if !applyTokenPolicyAndContext(c, token) {
return // applyTokenPolicyAndContext already aborted
}
// Critical: V2 path must populate the same per-token context
// keys the legacy path does — token_key, token_name,
// token_quota, model_limits, ContextKeyTokenGroup, etc. —
// otherwise downstream Distribute / billing logic blow up
// with "record not found". This bug surfaced as HTTP 403
// new_api_error on every V2 chat call after device pairing
// finally started succeeding.
if err := SetupContextForToken(c, token); err != nil {
return
}
c.Next()
return
}