Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
84c212d
feat: add client (CLI/IDE) restrictions for user management
Dec 13, 2025
4378341
fix(leaderboard): unify rank badge alignment for all positions (#344)
ding113 Dec 14, 2025
49979f5
fix(date-picker): add clear button to DatePickerField (#345)
ding113 Dec 14, 2025
f8d13fc
fix: regenerate allowed_clients migration with proper Drizzle Kit wor…
Dec 14, 2025
694ffce
chore: format code (feat-allowed-clients-f8d13fc)
github-actions[bot] Dec 14, 2025
c2f5162
fix(user): allow zero daily quota for unlimited (#346)
ding113 Dec 14, 2025
8d046cf
Merge pull request #341 from miraserver/feat/allowed-clients
ding113 Dec 14, 2025
0726f49
feat(users): add allowed models restriction for users
Dec 15, 2025
b2fcdc3
feat(error-rules): add detailed override responses for various error …
ding113 Dec 16, 2025
9b8da89
feat: 优化 API 文档展示和参数映射支持
Dec 17, 2025
7a3cb20
feat: migrate testing framework to Vitest and enhance API documentation
Dec 17, 2025
de44863
chore: format code (feat-api-docs-summary-7a3cb20)
github-actions[bot] Dec 17, 2025
8995def
fix: regenerate allowed_models migration using Drizzle Kit
Dec 17, 2025
01e36ab
chore: format code (feat-allowed-models-8995def)
github-actions[bot] Dec 17, 2025
b9127eb
Merge pull request #355 from ding113/feat/api-docs-summary
ding113 Dec 17, 2025
06726e1
fix: switch Docker build stage from Bun to Node.js to resolve N-API c…
github-actions[bot] Dec 17, 2025
340e2da
Merge pull request #347 from miraserver/feat/allowed-models
ding113 Dec 17, 2025
34d49db
fix: add --legacy-peer-deps flag to npm install in Dockerfile
github-actions[bot] Dec 17, 2025
60165f4
feat: 优化限额管理系统检查顺序和错误响应
Dec 18, 2025
3d218b1
chore: format code (feat-rate-limit-optimization-60165f4)
github-actions[bot] Dec 18, 2025
3ae9476
fix: correct TypeScript type for Tooltip formatter parameter
github-actions[bot] Dec 18, 2025
5b6b362
chore: update biome config and fix lint issues
Dec 18, 2025
af130ac
refactor: code quality improvements based on Gemini feedback
Dec 18, 2025
380ebf3
Merge pull request #359 from ding113/feat/rate-limit-optimization
ding113 Dec 18, 2025
cea7069
fix: support skipping TLS certificate verification for Redis
Silentely Dec 18, 2025
ac5a5dd
fix: add TLS certificate skip support to all Redis connections
Silentely Dec 18, 2025
81743a0
fix: add SNI (servername) support for cloud Redis TLS connections
Silentely Dec 18, 2025
f835d2e
fix: add REDIS_TLS_REJECT_UNAUTHORIZED to env schema
Silentely Dec 18, 2025
7da3c58
Merge pull request #360 from Silentely/fix/redis-tls-skip-verify
ding113 Dec 18, 2025
3ad0685
feat: add error handling and localization for key loading failures
ding113 Dec 18, 2025
88ecde9
Update src/app/[locale]/settings/providers/_components/forms/api-test…
ding113 Dec 18, 2025
c8420ea
feat(error-rules): add "Tool names must be unique" error pattern
github-actions[bot] Dec 18, 2025
2e5650a
chore: format code (fix-issue-366-tool-names-unique-c8420ea)
github-actions[bot] Dec 18, 2025
40b2f59
fix: remove forced stream=true for Codex requests
github-actions[bot] Dec 19, 2025
598c817
Merge pull request #369 from ding113/fix/issue-368-codex-compact-stream
ding113 Dec 19, 2025
c17fbfd
Merge pull request #367 from ding113/fix/issue-366-tool-names-unique
ding113 Dec 19, 2025
16ff4f4
feat(user-management): enhance user quota management with daily reset…
ding113 Dec 17, 2025
1ebaeb4
feat(user-management): add create user flow with onboarding tour
ding113 Dec 17, 2025
4b1255b
chore: format code (feat-user-panel-d3fb4f6)
github-actions[bot] Dec 17, 2025
a7dac94
feat(user-management): enhance user edit dialog and key management UI
ding113 Dec 17, 2025
58e25ef
chore: format code (feat-user-panel-d5cf49f)
github-actions[bot] Dec 17, 2025
cc7e5b1
fix(i18n): update provider group placeholder translations for clarity
ding113 Dec 17, 2025
e1505a1
feat(user-management): enhance user and key management UI with new fe…
ding113 Dec 17, 2025
4197760
feat(i18n): enhance translations and user interface for key management
ding113 Dec 17, 2025
618631c
fix: handle undefined value in Recharts Tooltip formatter
github-actions[bot] Dec 17, 2025
c9f6aff
chore: fix lint errors in test files after rebase
ding113 Dec 17, 2025
560c313
feat(user-management): enhance user edit and access restrictions feat…
ding113 Dec 18, 2025
79d2968
fix(sql): prevent duplicate column additions in user table
ding113 Dec 18, 2025
cf6a644
feat(i18n): enhance dashboard translations and key management UI
ding113 Dec 18, 2025
1d6bc73
feat(user-management): add quick renewal dialog and relocate enable t…
ding113 Dec 18, 2025
1305e2d
chore: format code (feat-user-panel-c9f8832)
github-actions[bot] Dec 18, 2025
f1181d2
feat(user-management): update user management table and edit section
ding113 Dec 18, 2025
7c7f690
fix: remove duplicate sumUserCostInTimeRange function
github-actions[bot] Dec 18, 2025
0611df1
fix: update translations and improve date handling in user dialogs
ding113 Dec 18, 2025
4647f96
feat: add quota usage feature and update translations
ding113 Dec 19, 2025
84d0439
chore: format code (feat-user-panel-4647f96)
github-actions[bot] Dec 19, 2025
054ed68
Merge pull request #365 from ding113/fix/better-error-display
ding113 Dec 19, 2025
d174c8f
Merge branch 'dev' into feat/user-panel
ding113 Dec 19, 2025
81dea45
Merge pull request #362 from ding113/feat/user-panel
ding113 Dec 19, 2025
c62925d
fix: update model name in TOML configuration for usage documentation
ding113 Dec 19, 2025
9869736
feat: enhance rule list table with tooltips and layout adjustments
ding113 Dec 19, 2025
3407dbb
chore: update Dockerfile to use Bun for package management and build …
ding113 Dec 19, 2025
e174400
chore: update Dockerfiles to use Debian base image and streamline Pos…
ding113 Dec 19, 2025
781b7d5
chore: update Dockerfiles to change user ownership from 'node' to 'bun'
ding113 Dec 19, 2025
6ed68ea
fix: update user management table description for localization
Dec 19, 2025
0831a61
feat: implement cursor-based pagination for usage logs
ding113 Dec 19, 2025
caa6c01
feat: add overwrite hint for existing limit types in dashboard
ding113 Dec 19, 2025
624f2c9
chore: format code (dev-caa6c01)
github-actions[bot] Dec 19, 2025
e7a5253
feat: implement response header cleanup for Bun compatibility
Dec 19, 2025
c1db3c6
fix: resolve TypeScript errors for null vs undefined in user types
github-actions[bot] Dec 19, 2025
d5991c1
Merge pull request #376 from ding113/claude-fix-pr-370-20366972438
ding113 Dec 19, 2025
92c0a62
chore: update configuration files and improve usage logs handling
ding113 Dec 19, 2025
5013f0d
fix: update cursor pagination index for message requests
ding113 Dec 19, 2025
176b556
refactor: improve layout and styling of usage logs table
ding113 Dec 19, 2025
674838c
refactor: adjust column widths and layout in virtualized logs table
ding113 Dec 19, 2025
67d680c
Merge pull request #371 from ding113/feat/cursor-pagination
ding113 Dec 19, 2025
19db0ec
refactor: enhance usage logs filters with lazy loading and status cod…
ding113 Dec 19, 2025
35a4802
refactor: reorganize imports and add comment for lazy loading hook
ding113 Dec 19, 2025
eda7293
fix: prevent event propagation in limit rule form submission
ding113 Dec 19, 2025
f8270e7
fix: update dailyQuota handling in UnifiedEditDialog
ding113 Dec 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ ENABLE_SECURE_COOKIES=true
# - Fail Open 策略:Redis 不可用时自动降级,不影响服务可用性
ENABLE_RATE_LIMIT=true # 是否启用限流功能(默认:true)
REDIS_URL=redis://localhost:6379 # Redis 连接地址(Docker 部署使用 redis://redis:6379,支持 rediss:// TLS)
REDIS_TLS_REJECT_UNAUTHORIZED=true # 是否验证 Redis TLS 证书(默认:true)
# 设置为 false 可跳过证书验证,用于自签证书或共享证书场景
# 仅在 rediss:// 协议时生效

# Session 配置
SESSION_TTL=300 # Session 过期时间(秒,默认 300 = 5 分钟)
Expand Down
234 changes: 234 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
name: 🧪 Test Suite

on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]

# 取消同一分支的进行中的工作流
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
# ==================== 代码质量检查 ====================
quality:
name: 📋 Code Quality
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Run linting
run: bun run lint

- name: Run type checking
run: bun run typecheck

- name: Check formatting
run: bun run format:check

# ==================== 单元测试 ====================
unit-tests:
name: ⚡ Unit Tests
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Run unit tests
run: bun run test -- tests/unit/ --passWithNoTests

# ==================== 集成测试(需要数据库)====================
integration-tests:
name: 🔗 Integration Tests
runs-on: ubuntu-latest

services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_password
POSTGRES_DB: claude_code_hub_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

redis:
image: redis:7-alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379

env:
DSN: postgres://test_user:test_password@localhost:5432/claude_code_hub_test
REDIS_URL: redis://localhost:6379/1
ADMIN_TOKEN: test-admin-token-for-ci
AUTO_MIGRATE: true
ENABLE_RATE_LIMIT: true
SESSION_TTL: 300

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Run database migrations
run: bun run db:migrate

- name: Run integration tests
run: bun run test -- tests/integration/ --passWithNoTests

# ==================== API 测试(需要运行服务)====================
api-tests:
name: 🌐 API Tests
runs-on: ubuntu-latest

services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_password
POSTGRES_DB: claude_code_hub_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

redis:
image: redis:7-alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379

env:
DSN: postgres://test_user:test_password@localhost:5432/claude_code_hub_test
REDIS_URL: redis://localhost:6379/1
ADMIN_TOKEN: test-admin-token-for-ci
AUTO_MIGRATE: true
PORT: 13500
ENABLE_RATE_LIMIT: true
SESSION_TTL: 300

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Build application
run: bun run build

- name: Run database migrations
run: bun run db:migrate

- name: Start server (background)
run: |
bun run start &
echo $! > server.pid
sleep 15 # 等待服务启动

- name: Wait for server ready
run: |
timeout 60 bash -c 'until curl -f http://localhost:13500/api/actions/health; do sleep 2; done'

- name: Run E2E API tests
run: bun run test:e2e
env:
API_BASE_URL: http://localhost:13500/api/actions
TEST_ADMIN_TOKEN: test-admin-token-for-ci
AUTO_CLEANUP_TEST_DATA: true

- name: Stop server
if: always()
run: |
if [ -f server.pid ]; then
kill $(cat server.pid) || true
fi

# ==================== 测试结果汇总 ====================
test-summary:
name: 📊 Test Summary
runs-on: ubuntu-latest
needs: [quality, unit-tests, integration-tests, api-tests]
if: always()

steps:
- name: Check test results
run: |
if [ "${{ needs.quality.result }}" != "success" ] || \
[ "${{ needs.unit-tests.result }}" != "success" ] || \
[ "${{ needs.integration-tests.result }}" != "success" ] || \
[ "${{ needs.api-tests.result }}" != "success" ]; then
echo "❌ 部分测试失败"
exit 1
else
echo "✅ 所有测试通过"
fi

- name: Create summary
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const summary = `## 🧪 测试结果

| 测试类型 | 状态 |
|---------|------|
| 代码质量 | ${{ needs.quality.result == 'success' && '✅' || '❌' }} |
| 单元测试 | ${{ needs.unit-tests.result == 'success' && '✅' || '❌' }} |
| 集成测试 | ${{ needs.integration-tests.result == 'success' && '✅' || '❌' }} |
| API 测试 | ${{ needs.api-tests.result == 'success' && '✅' || '❌' }} |

**总体结果**: ${{ (needs.quality.result == 'success' && needs.unit-tests.result == 'success' && needs.integration-tests.result == 'success' && needs.api-tests.result == 'success') && '✅ 所有测试通过' || '❌ 部分测试失败' }}
`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
4 changes: 1 addition & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
@.env.example
@CONTRIBUTING.md
@README.md
@docs/product-brief-claude-code-hub-2025-11-29.md
@CONTRIBUTING.md
1 change: 1 addition & 0 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ Docker Compose is the **preferred deployment method** — it automatically provi
| `DSN` | - | PostgreSQL connection string, e.g., `postgres://user:pass@host:5432/db`. |
| `AUTO_MIGRATE` | `true` | Executes Drizzle migrations on startup; consider disabling in production for manual control. |
| `REDIS_URL` | `redis://localhost:6379` | Redis endpoint, supports `rediss://` for TLS providers. |
| `REDIS_TLS_REJECT_UNAUTHORIZED` | `true` | Validate Redis TLS certificates; set `false` to skip (for self-signed/shared certs). |
| `ENABLE_RATE_LIMIT` | `true` | Toggles multi-dimensional rate limiting; Fail-Open handles Redis outages gracefully. |
| `SESSION_TTL` | `300` | Session cache window (seconds) that drives vendor reuse. |
| `ENABLE_SECURE_COOKIES` | `true` | Browsers require HTTPS for Secure cookies; set to `false` when serving plain HTTP outside localhost. |
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,11 @@ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
- **管理后台**:`http://localhost:23000`(使用 `.env` 中的 `ADMIN_TOKEN` 登录)
- **API 文档(Scalar UI)**:`http://localhost:23000/api/actions/scalar`
- **API 文档(Swagger UI)**:`http://localhost:23000/api/actions/docs`
- **API 认证指南**:[docs/api-authentication-guide.md](docs/api-authentication-guide.md)

> 💡 **提示**:如需修改端口,请编辑 `docker-compose.yml` 中的 `ports` 配置。
> 💡 **提示**:
> - 如需修改端口,请编辑 `docker-compose.yml` 中的 `ports` 配置。
> - 如需通过脚本或编程调用 API,请参考 [API 认证指南](docs/api-authentication-guide.md)。

## 🖼️ 界面预览 Screenshots

Expand Down Expand Up @@ -246,6 +249,7 @@ Docker Compose 是**首选部署方式**,自动配置数据库、Redis 和应
| `DSN` | - | PostgreSQL 连接串,如 `postgres://user:pass@host:5432/db`. |
| `AUTO_MIGRATE` | `true` | 启动时自动执行 Drizzle 迁移;生产环境可关闭以人工控制。 |
| `REDIS_URL` | `redis://localhost:6379` | Redis 地址,支持 `rediss://` 用于 TLS。 |
| `REDIS_TLS_REJECT_UNAUTHORIZED` | `true` | 是否验证 Redis TLS 证书;设为 `false` 可跳过验证(用于自签/共享证书)。 |
| `ENABLE_RATE_LIMIT` | `true` | 控制多维限流开关;Fail-Open 策略在 Redis 不可用时自动降级。 |
| `SESSION_TTL` | `300` | Session 缓存时间(秒),影响供应商复用策略。 |
| `ENABLE_SECURE_COOKIES` | `true` | 仅 HTTPS 场景能设置 Secure Cookie;HTTP 访问(非 localhost)需改为 `false`。 |
Expand Down
27 changes: 25 additions & 2 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,38 @@
}
}
}
},
{
"includes": ["**/tests/**", "**/*.test.ts", "**/*.test.tsx"],
"linter": {
"rules": {
"correctness": {
"noUnusedVariables": "off",
"noUnusedImports": "off"
}
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "off"
}
}
}
}
],
"files": {
"includes": [
"**",
"src/**",
"tests/**",
"*.ts",
"*.tsx",
"*.json",
"*.mjs",
"*.cjs",
"!**/node_modules",
"!**/.next",
"!**/dist",
"!**/*.d.ts",
"!**/drizzle",
"!**/docs-site"
]
Expand Down
30 changes: 13 additions & 17 deletions deploy/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1

FROM --platform=$BUILDPLATFORM oven/bun:slim AS build-base
FROM --platform=$BUILDPLATFORM oven/bun:debian AS build-base
WORKDIR /app

FROM build-base AS deps
Expand All @@ -26,31 +26,27 @@ ENV CI=true

RUN bun run build

FROM node:22-slim AS runner
FROM oven/bun:debian AS runner
ENV NODE_ENV=production
ENV PORT=3000
ENV HOST=0.0.0.0
WORKDIR /app

# 安装 PostgreSQL 18 客户端工具(用于数据库备份/恢复功能)和 curl(用于健康检查)
# 需要使用官方 PostgreSQL APT 仓库以获取最新版本
# 安装 PostgreSQL 客户端工具(用于数据库备份/恢复功能)和 curl(用于健康检查)
# Debian Trixie 自带 PostgreSQL 17,无需外部 APT 仓库
RUN apt-get update && \
apt-get install -y gnupg curl ca-certificates && \
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /usr/share/keyrings/postgresql-archive-keyring.gpg && \
echo "deb [signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
apt-get update && \
apt-get install -y postgresql-client-18 && \
apt-get install -y curl ca-certificates postgresql-client && \
rm -rf /var/lib/apt/lists/*

COPY --from=build --chown=node:node /app/public ./public
COPY --from=build --chown=node:node /app/drizzle ./drizzle
COPY --from=build --chown=node:node /app/messages ./messages
COPY --from=build --chown=node:node /app/.next/standalone ./
COPY --from=build --chown=bun:bun /app/public ./public
COPY --from=build --chown=bun:bun /app/drizzle ./drizzle
COPY --from=build --chown=bun:bun /app/messages ./messages
COPY --from=build --chown=bun:bun /app/.next/standalone ./
# Server Actions live inside .next/server; copy it or Next.js cannot resolve action IDs.
COPY --from=build --chown=node:node /app/.next/server ./.next/server
COPY --from=build --chown=node:node /app/.next/static ./.next/static
COPY --from=build --chown=bun:bun /app/.next/server ./.next/server
COPY --from=build --chown=bun:bun /app/.next/static ./.next/static

USER node
USER bun
EXPOSE 3000

CMD ["node", "server.js"]
CMD ["bun", "run", "server.js"]
Loading
Loading