Skip to content

feat(gateway): P0-C SSE 流式转发 + 上游 key 加密 + 共享/钱包/交易 API (v0.2.2) - #74

Merged
argszero merged 1 commit into
mainfrom
feat/backend-p0c-stream-crypto
Aug 18, 2026
Merged

argszero merged 1 commit into
mainfrom
feat/backend-p0c-stream-crypto

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

P0-C backend implementation (rant 2026-08-18T10:36:04 — SSE 流式转发 + 上游 key 加密 + 共享/钱包/交易 API). Completes streaming support (required by Cursor/Claude Code), upstream key encryption at rest, and user-facing sharing/wallet/transaction APIs aligned with the prototype. Version v0.2.2.

Changes

1. SSE streaming (src/gateway.rs)

  • stream:true requests take a streaming path: reqwest bytes_stream passthrough chunk-by-chunk, keeping data:/event: lines verbatim
  • Response headers content-type: text/event-stream + cache-control: no-cache
  • Usage metering from stream tail: OpenAI last-chunk usage (with stream_options.include_usage), Anthropic message_start input_tokens + message_delta output_tokens
  • Client disconnect aborts upstream (stream dropped → settle never runs → no charge)
  • Initial-connection failover reuses the P0-B 7-rule routing (401/403/429/5xx/network → cooldown → switch, max 3)

2. Upstream key encryption (src/crypto.rs new)

  • AES-256-GCM (RustCrypto aes-gcm), format v1:<nonce_hex>:<cipher_hex>
  • Master key: env ATP_MASTER_KEY → config [server].master_key → dev random + warning
  • Startup migration db::migrate_key_encryption: legacy plaintext keys auto-encrypted (idempotent)
  • Gateway decrypts before forwarding; decrypt failure treats key as unhealthy

3. Sharing API (src/routes/sharing.rs new, prototype US-8/9)

  • POST /api/sharings — list a key (encrypted at rest, DB never holds plaintext)
  • GET /api/sharings — my sharings with masked key sk-****xxxx, used/quota/earn/status/available window
  • PATCH /api/sharings/:id — pause/resume/soft-delete (paused/on/off)
  • keys gains available_days/available_start/available_end/note columns (v2 migration, idempotent ensure_column)

4. Wallet / Transactions / Dashboard (src/routes/wallet.rs new)

  • GET /api/wallet → {balance, month_use, month_earn}
  • GET /api/transactions?type=&page=&page_size= — type filter (consume/earn/all), pagination, time desc
  • GET /api/dashboard — month aggregation by type + net change + last-7-days series (sparkline)

Tests

  • 49 tests pass (16 new: crypto 5, db migration 2, SSE/gateway 4, sharing 3, wallet 2)
  • cargo build + cargo clippy --all-targets -- -D warnings + cargo fmt --check clean
  • Live smoke: stream:true → SSE chunked with [DONE] + correct headers; DB keys all v1: ciphertext (incl. migrated placeholder); sharing list masked; wallet/transactions/dashboard ledger correct (consume + earn 90/10)

Notes

  • Version bumped to v0.2.2
  • Available-window enforcement deferred to P1 (stored & displayed only)

Closes rant 2026-08-18T10:36:04.876683 (P0-C).

- SSE 流式转发(src/gateway.rs):stream:true 走 forward_stream,reqwest
  bytes_stream 逐块透传(data:/event: 原样),content-type text/event-stream +
  cache-control no-cache;openai 流尾 usage(include_usage 最后 chunk)、
  anthropic message_start input + message_delta output 解析计量;客户端断开
  自动中止上游且不入账;连接阶段故障转移复用七条定案
- 上游 key 加密(src/crypto.rs 新增):AES-256-GCM,v1:<nonce>:<cipher> 格式,
  主密钥 env ATP_MASTER_KEY → config [server].master_key → dev 随机+告警;
  启动时旧明文 key 自动加密迁移(db::migrate_key_encryption);转发前解密
- 共享管理 API(src/routes/sharing.rs):POST /api/sharings 上架(加密落库)、
  GET 列表(key 脱敏 sk-****xxxx + 收益/额度/状态/可用时间段)、
  PATCH /api/sharings/:id 暂停/恢复/软删(paused/on/off);keys 表新增
  available_days/start/end + note 列(v2 迁移 ensure_column 幂等补列)
- 钱包/交易/仪表盘 API(src/routes/wallet.rs):GET /api/wallet(balance/
  month_use/month_earn)、GET /api/transactions(type 过滤+分页+时间倒序)、
  GET /api/dashboard(本月聚合+净变化+近 7 天序列)
- 测试 49 个全过(新增 16:crypto 5 / db 迁移 2 / SSE 4 / sharing 3 / wallet 2),
  clippy + fmt 干净;live smoke 全过(SSE 逐块+[DONE]、DB 全 v1: 密文、
  列表脱敏、wallet/transactions/dashboard 记账正确)

Rant: 2026-08-18T10:36:04(P0-C SSE 流式转发 + 上游 key 加密 + 共享/钱包/交易 API)
@argszero
argszero merged commit 4c7b127 into main Aug 18, 2026
1 check passed
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.

1 participant