家庭保单管理工具
极简 · Self-host · 隐私安全
- 📋 保单管理 — 集中管理家庭所有保险保单
- 👨👩👧👦 成员管理 — 追踪每位家庭成员的保障情况
- 🔍 保障速查 — 快速查看任意成员或资产的保障覆盖
- 📅 续保日历 — 一目了然的保单到期提醒
- 🏢 保险公司 — 管理保险公司和代理人联系方式
- 🏠 资产管理 — 房产、车辆等财产保险关联
- 🔒 隐私优先 — 数据存储在自己的 Cloudflare D1 数据库
Surety 是一个全栈 Cloudflare 应用:
Browser ──► Cloudflare Access (Google OAuth)
└─► Hono Worker (surety) ──► @surety/api ──► @surety/db ──► D1 binding
│
└─► Static assets (Vite SPA build)
CLI ──► Bearer token ──► Hono Worker ──► @surety/api ──► @surety/db ──► D1
- 前端:Vite + React Router SPA,构建产物直接写到 Worker 的
static/目录,由 WorkerASSETSbinding 托管(SPA fallback)。 - API:Hono Worker,路由全部位于
/api/*,业务逻辑委托给@surety/api。 - Auth:
- 浏览器走 Cloudflare Access(Google OAuth),Worker 中
accessAuth中间件校验Cf-Access-Jwt-Assertion。 - CLI / 脚本走 Bearer token(
api_tokens表),apiKeyAuth中间件校验。 /api/live公开无需鉴权;本地 localhost host 直通以便本地调试。
- 浏览器走 Cloudflare Access(Google OAuth),Worker 中
- CLI:
@nocoo/surety— AI/脚本通过 Bearer token 调 Worker HTTP API,已取代原 MCP Server。
# 需要先安装 Bun: https://bun.sh
bun installcp .env.example .env本地开发不需要跑自己的 Worker — Vite dev server 会代理 /api/* 到线上 Worker,同时自动注入 Bearer token,让你直接在浏览器里看到 prod 数据:
# 线上 Worker API 地址 (默认 https://surety-api.hexly.ai)
SURETY_API_URL=https://surety-api.hexly.ai
# 拿一个 CLI token(详见下面的"CLI — Bearer token")
SURETY_DEV_API_TOKEN=sk_xxx💡 想跑本地 Worker 也可以:
bun run dev:worker启动wrangler dev,然后把SURETY_API_URL指向http://localhost:7016。
# 推送 schema 到 D1
bun run db:push
# (可选) 填充测试数据
SURETY_TARGET_DB=dev bun run db:seed💡 详见 CLAUDE.md 中的 Worker Deployment 章节。
bun dev打开浏览器访问 👉 http://localhost:7012
Bun workspace monorepo。依赖图:apps/web → apps/worker(运行时)+ apps/worker → @surety/api → @surety/db。
surety/
├── 📂 apps/
│ ├── 📂 web/ # Vite React SPA
│ │ ├── 📂 src/
│ │ │ ├── 📂 app/ # 路由页面 (React Router)
│ │ │ ├── 📂 components/ # React UI 组件 (shadcn/ui)
│ │ │ ├── 📂 hooks/ # React hooks
│ │ │ ├── 📂 lib/ # 客户端工具
│ │ │ ├── 📂 __tests__/ # fetchAPI 等单元测试
│ │ │ ├── api.ts # fetch wrapper (credentials include)
│ │ │ ├── App.tsx # 根路由
│ │ │ └── main.tsx # 入口
│ │ ├── index.html
│ │ └── vite.config.ts # dev proxy → prod Worker
│ └── 📂 worker/ # Hono API + 静态资源
│ ├── 📂 src/
│ │ ├── index.ts # Hono app, 路由注册
│ │ ├── 📂 middleware/ # access-auth, api-key-auth, is-localhost
│ │ ├── 📂 routes/ # members, policies, …, auth-cli
│ │ └── 📂 lib/ # context/types helpers
│ ├── 📂 __tests__/ # Worker 单元测试
│ ├── 📂 static/ # Vite 构建产物 (git-ignored) + logos
│ └── wrangler.toml
├── 📂 packages/
│ ├── 📂 db/ # @surety/db — Schema + Repositories
│ │ └── 📂 src/
│ │ ├── schema.ts
│ │ ├── index.ts # sqlite-proxy + D1 binding driver
│ │ └── 📂 repositories/
│ ├── 📂 api/ # @surety/api — 业务逻辑(framework-agnostic)
│ │ └── 📂 src/
│ │ ├── dashboard.ts
│ │ ├── coverage-lookup.ts
│ │ ├── renewal-calendar.ts
│ │ └── …
├── package.json # Workspace root
├── tsconfig.base.json
└── bunfig.toml
| 组件 | 选型 |
|---|---|
| ⚡ Runtime | Bun |
| 🖥️ 前端 | Vite 6 + React 19 + React Router 7 + SWR |
| ☁️ 后端 | Hono on Cloudflare Workers |
| 📝 Language | TypeScript (strict mode) |
| 🗄️ Database | Cloudflare D1 + Drizzle ORM(D1 binding 直连) |
| 🎨 UI | Tailwind CSS v4 + shadcn/ui |
| 🔐 Auth | Cloudflare Access (Google OAuth) + Bearer token(CLI) |
| 命令 | 说明 |
|---|---|
bun dev |
启动 Vite dev server (端口 7012),代理到线上 Worker |
bun run dev:worker |
启动本地 Hono Worker (wrangler dev --port 7016) |
bun run build |
Vite 构建到 apps/worker/static/ |
bun test |
运行所有单元测试(web + worker + cli) |
bun run test:web |
仅 web SPA 单测 |
bun run test:worker |
仅 Worker 中间件/路由单测 |
bun run test:coverage |
测试覆盖率报告(行/函数门槛 ≥ 95) |
bun run test:coverage:cached |
L1 文件哈希缓存:只在输入变化时跑测试 |
bun run test:l2:http |
L2 HTTP 套件:wrangler dev --local (port 7017) + 真 D1/R2 |
bun run test:e2e:browser |
L3 Playwright 浏览器回归(port 27012,chromium-only) |
bun run lint |
ESLint(零警告) |
bun run typecheck |
tsc --noEmit |
bun run db:push |
推送 schema 到 D1 |
bun run db:studio |
打开 Drizzle Studio |
bun run db:seed |
填充测试数据 |
- 浏览器访问
https://surety.hexly.ai - Cloudflare Access 拦截 → Google OAuth 登录
- CF 回发
Cf-Access-Jwt-Assertionheader,Worker 的accessAuth用 CF JWKS 校验并提取email。 - 本地开发时 host 以
localhost/127.0.0.1/.dev.hexly.ai开头 → 直接放行,用于脱机调试。
目前只有 /api/auth/cli loopback 流程可以铸 token(设置页暂时没有手动创建入口):
- 在本地起一个监听
http://127.0.0.1:PORT/cb的小脚本(接收回调),例如:# 一次性 netcat 接收 nc -l 7777 - 浏览器打开(会先走 CF Access 登录):
(
https://surety.hexly.ai/api/auth/cli?callback_url=http://127.0.0.1:7777/cb&state=NONCE?callback=亦可作为?callback_url=的别名,兼容@nocoo/cli-base。) - Worker 通过 CF Access 鉴权后铸造一个绑定当前邮箱的 token,302 重定向回
callback_url,查询参数里带上api_key、state、email。callback_url必须是http://127.0.0.1:*或http://localhost:*。 - 把
api_key配到SURETY_DEV_API_TOKEN(Vite dev proxy)或 CLI 配置里。 Worker 的apiKeyAuth中间件负责校验并更新lastUsedAt。
ℹ️ 吊销 token 走
DELETE /api/auth/tokens/:id(设置页目前没有 token 管理 UI,只能用 API 直接管理)。
@nocoo/surety 是 AI 和脚本访问 Surety 数据的入口,通过 Bearer token 调用 Worker HTTP API(surety-api.hexly.ai),完整替代了早期的 MCP server。
bun add -g @nocoo/surety
surety login
surety members ls
surety policies get 3 --full完整命令、配置和输出契约见 apps/cli/README.md。从 MCP 迁移到 CLI 的设计与演进记录见 docs/16-cli-replace-mcp.md。
MIT © 2026
