Helvetra/backend
GitHub: Helvetra/backend
基于 FastAPI 构建的隐私优先瑞士翻译 API,支持瑞士德语方言及多语种翻译,同时面向消费者和 B2B 提供分层服务与计量计费。
Stars: 2 | Forks: 0
# Helvetra Backend
为 [Helvetra](https://helvetra.ch)(一款隐私优先的瑞士翻译应用)提供支持的翻译 API。
该后端服务于两个层面:
- **消费者 API** (`/api/v1/*`):供 Web 应用和 iOS 应用使用。
- **B2B 公共 API** (`/api/public/v1/*`):通过 API key 进行身份验证,按字符通过 Stripe 计量器进行计费,文档详见 [helvetra.ch/api/public/v1/docs](https://helvetra.ch/api/public/v1/docs)。
## 功能
### 翻译
- 由瑞士 AI 提供支持的翻译 API(通过 Infomaniak 使用 Apertus-70B)
- 支持的语言:德语、法语、意大利语、英语、罗曼什语和瑞士德语(包含苏黎世、伯尔尼、巴塞尔、卢塞恩、圣加仑和瓦莱州方言)
- 自动检测源语言
- 语体正式程度切换(du/Sie, tu/vous, tu/Lei)
- 深度防御 Prompt 注入:使用分隔符包裹用户输入、system prompt 隔离、长度比例限制、尾部注释剥离(EN/DE/FR/IT)
- 基于等级的单次请求和单周期字符限制
### Auth
- 邮箱 + 密码注册,结合 bcrypt 加密 + 常用密码拒绝机制
- 作用域限定于 `/api/v1/auth` 的 HttpOnly+Secure+SameSite=Strict refresh-token cookie
- 通过 PyJWT 使用 HS256 签名的 access token(15 分钟有效期)
- 每次执行 `/refresh` 时轮换 refresh-token
- 在基于 cookie 认证且会更改状态的 endpoint 上提供 CSRF 保护(双重提交 cookie + `X-CSRF-Token` header)
- 针对(邮箱,IP)的登录锁定,以防止针对账户锁定的 DoS 攻击
- 带有多语言模板(EN/DE/FR/IT)的邮箱验证
- Sign in with Apple(通过 PyJWT + Apple JWKS 使用 RS256)
- Apple StoreKit 2 订阅验证 —— 目前已启用 kill-switch,等待针对 App Store Root CA 链的重写
### 支付
- **Web(消费者)**:Stripe Checkout 用于包月/包年订阅 + Customer Portal 用于自助管理
- **Web(B2B)**:Stripe 计量计费,使用 lookup-key 解析价格,提供 14 天的 Starter 试用,在每次翻译时内联发送计量事件
- **iOS**:StoreKit 2(验证器重写待定 —— 见上文)
### 运维
- 在 Redis 中进行速率限制(基于 IP 的全局限制 + 基于 endpoint 的认证限制 + 基于(邮箱,IP)的锁定)
- 通过原子 Redis Lua 脚本进行匿名使用情况追踪
- 当月度配额达到 80% 和 100% 时发送 B2B 用量警报邮件
- Stripe webhook 签名验证 + 幂等性去重(Apple webhook 也通过 `notificationUUID` 进行去重)
- 针对 auth 事件(登录尝试、账户删除、触发速率限制)的审计日志
## 技术栈
- **框架:** Python 3.11+ / FastAPI
- **数据库:** PostgreSQL 15 + SQLAlchemy + Alembic
- **缓存:** Redis 7
- **AI:** Apertus-70B(通过 Infomaniak AI)
- **Auth:** PyJWT (HS256 + RS256) + Sign in with Apple + Apple StoreKit 2(受控状态)
- **支付:** Stripe(Web,消费者 + B2B 计量)+ Apple StoreKit 2(iOS,受控状态)
## 设置
```
# Clone and configure
cp .env.example .env
# Edit .env — at minimum set JWT_SECRET_KEY, ENCRYPTION_KEY, APERTUS_API_KEY,
# DATABASE_URL, REDIS_URL. App refuses to boot in prod without secrets
# meeting minimum length requirements.
# Run with Docker (Postgres + Redis + backend)
docker-compose up
# Or run locally
pip install -e ".[dev]"
alembic upgrade head
uvicorn app.main:app --reload
# API: http://localhost:8000
# Consumer docs: http://localhost:8000/docs (debug-only)
# B2B public docs: http://localhost:8000/api/public/v1/docs
```
## API 层面
### 消费者 API(JWT 或会话 cookie)
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| POST | `/api/v1/auth/register` | 创建账户 + 发送验证邮件 |
| POST | `/api/v1/auth/login` | 邮箱/密码登录(cookie 或 body 中的 refresh token) |
| POST | `/api/v1/auth/refresh` | 轮换 refresh token,生成新的 access token |
| POST | `/api/v1/auth/logout` | 吊销 refresh token + 清除 cookie |
| POST | `/api/v1/auth/verify-email` | 使用邮件链接中的 token 验证邮箱 |
| POST | `/api/v1/auth/resend-verification` | 重新发送验证邮件(受速率限制) |
| POST | `/api/v1/auth/apple` | Sign in with Apple(identity-token 交换) |
| GET | `/api/v1/auth/me` | 当前已认证的用户 |
| DELETE | `/api/v1/auth/account` | 删除账户 + 取消活跃订阅 |
| POST | `/api/v1/translate` | 翻译文本(匿名或已认证) |
| POST | `/api/v1/feedback` | 提交翻译反馈(按 IP 进行速率限制) |
| GET | `/api/v1/languages` | 列出支持的语言和方言 |
| GET | `/api/v1/subscription` | 消费者订阅状态 |
| GET | `/api/v1/subscription/b2b` | B2B 订阅状态 |
| GET | `/api/v1/subscription/b2b/usage-history` | 过去 12 个月的使用周期记录 |
| GET | `/api/v1/subscription/limits` | 当前用户的等级限制 |
| GET | `/api/v1/subscription/anonymous-usage` | 每周匿名使用状态 |
| POST | `/api/v1/payments/create-gateway` | 启动消费者 Stripe checkout |
| POST | `/api/v1/payments/create-b2b-gateway` | 启动 B2B Stripe checkout |
| POST | `/api/v1/payments/b2b-portal` | 打开 Stripe Customer Portal 会话 |
| POST | `/api/v1/api-keys` | 创建 B2B API key(仅提供一次明文复制) |
| GET | `/api/v1/api-keys` | 列出调用者的 API key |
| POST | `/api/v1/api-keys/{id}/rotate` | 轮换 API key(仅返回一次新明文) |
| DELETE | `/api/v1/api-keys/{id}` | 吊销 API key |
| POST | `/api/v1/webhooks/stripe` | Stripe webhook 接收器 |
| POST | `/api/v1/webhooks/apple` | Apple App Store Server Notifications v2 接收器 |
| GET | `/api/health` | 健康检查 |
### B2B 公共 API(API key)
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| POST | `/api/public/v1/translate` | 翻译文本(`X-API-Key` 认证,通过 Stripe 计量器计费) |
| GET | `/api/public/v1/languages` | 列出支持的语言 |
| GET | `/api/public/v1/usage` | 当前周期的使用情况 |
| GET | `/api/public/v1/docs` | Swagger UI |
| GET | `/api/public/v1/redoc` | ReDoc |
| GET | `/api/public/v1/openapi.json` | OpenAPI schema(已筛选为公共路由) |
## 支持的语言
| 代码 | 语言 |
|------|----------|
| de | 德语 |
| gsw | 瑞士德语(包含地区方言) |
| fr | 法语 |
| it | 意大利语 |
| en | 英语 |
| rm | 罗曼什语 |
## 项目结构
```
app/
├── main.py # Application entry point + startup secret validation
├── config.py # Environment configuration (Pydantic Settings)
├── api/
│ ├── routes/ # FastAPI route handlers
│ ├── public_docs.py # Filtered OpenAPI schema for the B2B API
│ └── dependencies.py # Auth dependencies, get_client_ip, etc.
├── schemas/ # Pydantic request/response models
├── services/ # Business logic (auth, csrf, translation, stripe, …)
├── models/ # SQLAlchemy models
├── core/
│ ├── database.py # Async engine + session
│ ├── middleware.py # IP rate-limit middleware
│ └── tiers.py # Tier definitions (consumer + B2B)
└── data/ # Static data (common-passwords list)
alembic/ # Database migrations
tests/ # pytest suite
```
## 许可证
MIT
标签:AI翻译, Apple登录, AV绕过, Docker, FastAPI, Stripe支付, 后端开发, 安全防御评估, 搜索引擎查询, 测试用例, 翻译API, 请求拦截, 逆向工具