Skip to content

Latest commit

 

History

86 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AAEasy

AAEasy 是一个 Cloudflare-native 的多人分账 PWA。前端、API、关系数据、实时协作与 PDF 导出均运行在 Cloudflare 平台上。

当前架构

flowchart LR
  Browser["React SPA / PWA"] -->|"HTTPS + JSON"| Worker["Hono Worker"]
  Browser <-->|"WebSocket"| Worker
  Worker -->|"Drizzle D1 binding"| D1["Cloudflare D1"]
  Worker -->|"事件发布"| DO["Durable Objects"]
  Worker -->|"HTML + CSS"| BrowserRun["Cloudflare Browser Run"]
  Browser -->|"OIDC + PKCE"| Auth["Pangda Auth / KeyForge"]
  AI["MCP-compatible AI"] -->|"Streamable HTTP + OAuth"| Worker
  AI -->|"Authorization code + PKCE"| Auth
  Worker -->|"Token introspection"| Auth
Loading
实现
前端 Vite、React 19、React Router、TanStack Query、Tailwind CSS
API Cloudflare Worker + Hono
数据 Cloudflare D1(SQLite)+ Drizzle ORM
实时 Durable Objects + WebSocket Hibernation
登录 Pangda Auth OIDC authorization code + PKCE
导出 CSV + Cloudflare Browser Run PDF
AI 记账 MCP Streamable HTTP;复用账本权限、校验、审计与实时事件
测试 Vitest、TypeScript、ESLint、Wrangler dry-run

金额在 D1 中以十进制 TEXT 保存,并在 Drizzle 边界映射为 bigint,避免 D1 JavaScript 数字的精度损失。多语句写入使用 D1 batch();费用乐观锁额外使用内部 mutation token,防止陈旧请求改写分摊或审计记录。

本地运行

需要 Node.js 22.12+ 和 pnpm 10+,不再需要 Docker 或本地 PostgreSQL。

pnpm install
cp .dev.vars.example .dev.vars
pnpm auth:setup
pnpm dev

pnpm dev 会先把 migrations/ 应用到 Wrangler 的本地 D1,再由 Cloudflare Vite plugin 同时提供 SPA 与 Worker。打开 http://localhost:5173

本地登录默认使用 http://localhost:17001 的 KeyForge。pnpm auth:setup 会创建或修复 aaeasy client,并把一次性 client secret 写入 .dev.vars

AI 记账(MCP)

https://<你的域名>/mcp 配置给支持 MCP OAuth 的客户端;客户端会自动通过 KeyForge 登录、同意并获取绑定到该 resource 的 token。AAEasy 不再创建或保存独立 MCP Token。服务提供账本列表、账本上下文和费用创建工具;AI 写入仍受 KeyForge scope 以及现有角色、成员绑定、归档状态、金额/分摊校验与审计约束。详细配置见 MCP AI 记账文档

数据库

pnpm db:migrate:local       # 应用到本地 D1
pnpm db:migrations:list     # 查看本地迁移状态
pnpm db:generate            # schema 变化后生成迁移
pnpm db:migrate:remote      # 应用到生产 D1

初始 schema 位于 migrations/0000_military_jack_murdock.sql0001_d1_write_guards.sql 增加两个重要保护:归档账本前校验结算快照完整性,以及禁止向已归档账本写入费用。

从旧 PostgreSQL 搬迁已有业务数据:

DIRECT_DATABASE_URL="$AAEASY_SOURCE_POSTGRES_URL" \
AAEASY_USER_IDENTITY_MAP_FILE="$AAEASY_IDENTITY_MAP" \
  pnpm exec tsx scripts/export-postgres-to-d1.ts > "$AAEASY_EXPORT_SQL"
pnpm exec wrangler d1 execute aaeasy-production \
  --remote --env production --file "$AAEASY_EXPORT_SQL"

导出脚本只用于一次性切换,默认不导出旧登录和分享 session,并要求提供经过验证的 Neon → KeyForge 身份映射。导出的 SQL 和身份映射包含用户数据,必须放在安全的临时位置并在导入后删除。Cloudflare 不支持直接导入 PostgreSQL dump,因此脚本会转换身份引用、时间戳、JSON、数组、布尔值和内部 mutation token。正式操作见 PostgreSQL → D1 数据导入手册

Cloudflare 部署

先创建 dev/production D1,分别把 Wrangler 返回的 ID 写入 wrangler.jsonc 顶层和 env.production.d1_databases

pnpm exec wrangler d1 create aaeasy-dev
pnpm exec wrangler d1 create aaeasy-production
pnpm db:migrate:remote
pnpm run deploy

生产部署还需要配置 OIDC secrets、Browser Run、Durable Objects 和自定义域名。完整步骤见 Cloudflare 部署手册

常用命令

pnpm dev              # 本地 D1 + Worker + SPA
pnpm dev:pdf          # 使用远程 Browser Run 测试 PDF(消耗账户配额)
pnpm build            # 使用 production Cloudflare environment 构建
pnpm typecheck        # SPA、共享包和 Worker 类型检查
pnpm lint             # ESLint
pnpm test             # Vitest
pnpm check            # 全量质量检查
pnpm cf:typegen       # 重新生成 Cloudflare binding 类型

目录

src/                  React SPA、页面、组件和客户端 action wrappers
worker/src/           Hono API、Durable Objects、PDF、认证
packages/contracts/   API schema 与 DTO
packages/core/        金额、分摊、账本与清算纯函数
packages/db/          D1/SQLite Drizzle schema 与 binding client
migrations/           Wrangler D1 migrations
scripts/              配置检查、数据导出、本地登录初始化
docs/                 架构与部署手册

安全边界

  • 所有写请求经过 CSRF origin 校验和服务端权限校验。
  • MCP token 由 KeyForge 签发并在线 introspect,严格绑定 https://aaeasy.pangda.app/mcp audience;AAEasy 不保存 token,且不提供 Super Admin 旁路。
  • OIDC token 使用服务端 AES-GCM 加密后保存;应用不接收密码或 Passkey。
  • 分享解锁、用户搜索和 PDF 导出由 Durable Object 限流。
  • 分享访客不能导出完整账本;只读分享不能写费用。
  • 费用写入使用 version 乐观锁,账本事件使用单调 revision 修复断线缺口。
  • 成员、角色、分享、邀请、费用与结算写入都会记录 audit_logs

About

Self-hosted PWA for splitting shared expenses — multi-currency with frozen FX, passkey + password auth, AI-assisted entry, live multi-user editing, and PDF exports.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages