Skip to content

feat(gateway): P0 凭证池稳定身份与统一快照 - #849

Open
xiaocheny214 wants to merge 1 commit into
1024XEngineer:mainfrom
xiaocheny214:feat/gateway-pool-p0
Open

feat(gateway): P0 凭证池稳定身份与统一快照#849
xiaocheny214 wants to merge 1 commit into
1024XEngineer:mainfrom
xiaocheny214:feat/gateway-pool-p0

Conversation

@xiaocheny214

@xiaocheny214 xiaocheny214 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • 引入稳定 credential_id{endpoint}:{sha256(key)[:16]}),取代 primary.key{i} 下标身份
  • Admit 与 Video/Image/Chat Gateway 统一经 get_pool_snapshot / pool_routes 物化路由边
  • i2v Redis 在途键迁到 windup:i2v:gate:inflight:cred:{credential_id},并兼容一轮 fix(i2v): 全站在途名额与 429 冷却,避免动作建单打满上游 #842 遗留 primary.key{i} 映射
  • 新增凭证池四表 ORM(pool_models)与 import_gateway_pool_from_env.py;无 DB 时行为与现网 AI_ROUTE_* 一致

Closes #850

Part of #843

Test plan

  • uv run pytest tests/test_gateway_pool_ids.py tests/test_gateway_pool_models.py tests/test_i2v_admit.py tests/test_gateway_video.py tests/test_gateway_image.py tests/test_gateway_chat.py -q
  • staging:头部插入新 key 后,已在途 i2v 任务的 route_id 仍指向原物理凭证
  • 可选:uv run python scripts/import_gateway_pool_from_env.py --dry-run 后灌库

@vercel

vercel Bot commented Aug 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
windup Ignored Ignored Preview Sep 6, 2026 3:03am UTC

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown

✅ 此 PR 已关联 issue,之前的提醒已自动标记为已解决。

@codecov

codecov Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.22939% with 44 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...packages/app/src/windup_app/server/mq/i2v_admit.py 83.97% 25 Missing ⚠️
...work/src/windup_framework/gateway/pool_registry.py 82.71% 14 Missing ⚠️
...es/framework/src/windup_framework/gateway/video.py 55.55% 4 Missing ⚠️
...ges/framework/src/windup_framework/gateway/chat.py 91.66% 1 Missing ⚠️

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #849      +/-   ##
==========================================
- Coverage   91.27%   91.16%   -0.11%     
==========================================
  Files         193      195       +2     
  Lines       13204    13391     +187     
==========================================
+ Hits        12052    12208     +156     
- Misses       1152     1183      +31     
Flag Coverage Δ
backend 91.16% <84.22%> (-0.11%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...framework/src/windup_framework/gateway/__init__.py 100.00% <100.00%> (ø)
...es/framework/src/windup_framework/gateway/image.py 93.75% <100.00%> (+0.03%) ⬆️
...framework/src/windup_framework/gateway/pool_ids.py 100.00% <100.00%> (ø)
...s/framework/src/windup_framework/gateway/routes.py 100.00% <100.00%> (ø)
...ges/framework/src/windup_framework/gateway/chat.py 89.52% <91.66%> (+0.10%) ⬆️
...es/framework/src/windup_framework/gateway/video.py 81.50% <55.55%> (-0.17%) ⬇️
...work/src/windup_framework/gateway/pool_registry.py 82.71% <82.71%> (ø)
...packages/app/src/windup_app/server/mq/i2v_admit.py 86.14% <83.97%> (-2.45%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本次审阅覆盖凭证池 ORM/导入、路由物化、Chat/Image/Video 网关以及 i2v Admit 的完整固定 SHA diff。当前实现仍有几处会导致数据库池配置不生效、请求错误地复用首个凭证、并发配额失效或泄露密钥的问题,建议修复后再合并。由于环境中未安装 uv/pytest,验证采用固定范围 diff、调用链检查与 compileallgit diff --check 通过。

Additional findings

  • backend/packages/app/src/windup_app/server/mq/i2v_admit.py:?: [P1] Enforce account and credential inflight limits: The new RoutableEdge carries account_inflight_max and credential_inflight_max, and account-scoped edges even expose a shared account Redis key, but acquisition still calls the global inflight_max() and increments only edge.redis_inflight_key(). Thus a configured credential limit is ignored, and multiple credentials sharing one account can each admit up to the global limit instead of enforcing the account limit. This can exceed upstream capacity and defeats the quota fields introduced by the pool tables; acquisition needs to use the edge limit and, for account scope, atomically enforce the shared account set as well.
  • backend/scripts/import_gateway_pool_from_env.py:?: [P1] Do not persist imported keys as plaintext: The importer writes the raw environment secret into api_key_ciphertext with only a plaintext: prefix. The model contract explicitly says this column stores ciphertext and that keys must be decrypted only in memory; the prefix does not encrypt anything, so a database read exposes every upstream API key. Use the repository's encryption mechanism (and provide the matching decryptor to the runtime loader) rather than storing the secret verbatim.
  • backend/packages/framework/src/windup_framework/gateway/pool_registry.py:?: [P1] Preserve the adapter for each stable credential: snapshot_from_settings now emits stable IDs such as primary:<hash>, while the builders below still populate _route_adapters using the legacy primary.key{i} IDs. lookup_adapter therefore misses the per-key entry for every stable route and falls through to the default adapter, so a multi-key deployment sends all attempts through the first API key (and DB routes have the same problem). Build adapters keyed by the same stable credential IDs, or construct the adapter from the selected route instead of silently falling back.

Comment thread backend/packages/framework/src/windup_framework/gateway/routes.py
xyh202131
xyh202131 previously approved these changes Aug 28, 2026

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The review covers the new credential identity/pool registry, all gateway consumers, i2v admission migration, and the import/schema tooling. Three integration/security issues need correction before the database-backed pool can safely replace settings-based routing. Python compilation succeeds; the PR's advertised pytest command could not run here because uv and pytest are unavailable.

Additional findings

  • backend/scripts/import_gateway_pool_from_env.py:?: [P1] Do not persist API keys as plaintext ciphertext: The importer writes plaintext:{route.api_key} into api_key_ciphertext, exposing the full upstream secret in the database despite the model's contract that only ciphertext is stored. This is also not a usable encryption format for the decrypt_api_key callback expected by snapshot_from_rows(). A dry-run is safe, but any real import permanently stores every AI_ROUTE_* key in cleartext; use the repository's encryption mechanism (or fail closed when no encryption key/provider is configured) before inserting credentials.
  • backend/packages/framework/src/windup_framework/gateway/pool_registry.py:?: [P1] Keep factory adapter keys aligned with stable route IDs: Database/settings snapshots now materialize each route with route_id == credential_id (for example, the added assignment in snapshot_from_rows()), but build_chat_gateway(), build_image_gateway(), and build_video_gateway() still construct route_adapters using routes_from_settings(), whose keys are primary.key0, primary.key1, etc. In the normal factory path, _adapter_for() therefore misses every stable credential key and falls back to self._adapter (the first adapter), so retries/fallbacks can send all credentials through the first API key. Build the adapter map from pool_routes()/stable IDs or make lookup explicitly map the legacy keys.

Comment thread backend/packages/framework/src/windup_framework/gateway/routes.py
Admit 与 Gateway 共用稳定 credential_id,把 1024XEngineer#842 车道从 primary.key{i} 迁到物理钥匙,避免改 CSV 顺序把在途和冷却戴到另一把 key 上。

Part of 1024XEngineer#843
Closes 1024XEngineer#850
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(gateway): P0 凭证池稳定 identity 与 Admit/Gateway 统一快照

2 participants