Skip to content

About

Self-hosted bill and invoice manager with OCR, email ingestion, travel tracking, and multi-user data isolation.

Topics

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Smart Bill Manager

English: README_EN.md

Smart Bill Manager 是面向个人和小团队的自托管 AI 财务单据工作台。它把支付截图、发票和行程资料整理成可追溯候选;只有用户明确审核确认后,候选才会成为正式财务事实。

Important

v0.7.0 是 Clean Slate 公开实测预发布版,目前只提供 linux/amd64 单机部署。真实模型正确率、真实邮箱联调、TLS/域名和生产部署尚未完成,不应视为生产稳定版。

安装

需要 linux/amd64 主机、Docker Engine,以及至少 6 GiB 可用内存。两条路径任选一条。

用 docker run

起两个容器,不需要额外建网络:

docker run -d --name smart-bill-manager-db \
  --restart unless-stopped \
  -p 127.0.0.1:5432:5432 \
  -e POSTGRES_USER=sbm_app \
  -e POSTGRES_DB=smart_bill_manager \
  -e POSTGRES_PASSWORD=<自己设一个数据库密码> \
  -v sbm-postgres:/var/lib/postgresql/data \
  postgres:17-alpine

docker run -d --name smart-bill-manager \
  --restart unless-stopped --init --stop-timeout 20 \
  -p 127.0.0.1:8080:8080 \
  -v sbm-data:/var/lib/sbm \
  ghcr.io/tuoro/smart-bill-manager:v0.7.0

再取数据库容器的 IP,下一步要填:

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' smart-bill-manager-db

打开 http://127.0.0.1:8080,页面分两步引导:先填数据库连接——地址改成上面查到的 IP,端口 5432 和库名 smart_bill_manager 保持预填值,账号 sbm_app,密码是刚才设的那个(可先点「检测连接」)——验证通过后自动建表;再创建管理员账号(用户名 + 密码)。之后即可使用。

数据库那条 -p 127.0.0.1:5432:5432 把库开在宿主机回环上,方便用 psql、备份工具或图形客户端直接连;只绑 127.0.0.1,不会暴露到局域网。宿主机上 5432 已被占用就改成别的,比如 -p 127.0.0.1:15432:5432。

应用容器不走这个端口。两个容器都在 Docker 默认的 bridge 网络里按 IP 直接互通,所以初始化页的地址填上面查到的容器 IP,不是 127.0.0.1——默认网络不解析容器名,也不能从容器里访问宿主机的回环地址。

数据库连接也可以用 -e SBM_POSTGRES_HOST=<上面查到的 IP>、-e SBM_POSTGRES_USER、-e SBM_POSTGRES_PASSWORD 预先指定,页面就会跳过第一步;这几个变量优先于页面保存的配置。已经有 PostgreSQL 的话不需要起第一个容器,直接填它的地址即可。

装好之后,数据库连接可以在「系统 → 数据库连接」里查看和修改(仅 Owner),改完重启应用容器生效。数据库容器删除重建后 IP 可能变(docker restart 不会变),变了应用就连不上,在这里填新 IP 即可。见部署指南。

用 Docker Compose

和上面两条命令等价,参数一一对应,只是写成了一个文件。下载它:

curl -O https://raw.githubusercontent.com/tuoro/Smart-bill-manager/main/compose.yaml

把里面的 POSTGRES_PASSWORD 改成自己的密码,其余不用动,然后在该文件所在目录启动:

docker compose up -d

打开 http://127.0.0.1:8080,页面分两步:先填数据库连接——地址、端口、库名都已经预填好,不用改也不用查 IP,只补账号 sbm_app 和刚才设的密码——再创建管理员账号。

这是它比两条 docker run 省事的地方:Compose 自建的网络能解析服务名,而服务名和容器名一致,正好就是页面预填的那个地址。

刚启动的前几秒数据库还在初始化,这时点「检测连接」会失败,等几秒再点一次即可。两条 docker run 也是同样的时序。

日常操作在该目录里执行,docker logs、docker restart 那套命令也照样能用,因为容器名是一样的:

docker compose logs -f smart-bill-manager     # 看日志
docker compose restart smart-bill-manager     # 重启应用
docker compose down                           # 停止并删除容器,数据保留在卷里

docker compose down 不加 -v 不会删卷,数据和主密钥都留着。升级时把文件里的 image 改成新 tag 再 docker compose up -d;有待执行的迁移时应用会拒绝启动,先备份,再给应用服务加上 SBM_ALLOW_MIGRATION: "true"。

完整内容如下,也可以自己新建一个 compose.yaml 粘贴进去:

# Smart Bill Manager 单机部署,与 README 里那两条 docker run 等价。
#
# 用法:把下面的密码改成自己的,在本文件所在目录执行 docker compose up -d,
# 再打开 http://127.0.0.1:8080 按页面提示配置即可。

name: smart-bill-manager

services:
  smart-bill-manager-db:
    image: postgres:17-alpine
    container_name: smart-bill-manager-db
    restart: unless-stopped
    # 只绑回环,供 psql 和备份工具连接;不要写成 5432:5432,那会把库开给局域网。
    ports:
      - "127.0.0.1:5432:5432"
    environment:
      POSTGRES_USER: sbm_app
      POSTGRES_DB: smart_bill_manager
      POSTGRES_PASSWORD: 改成你自己的数据库密码
    volumes:
      - sbm-postgres:/var/lib/postgresql/data

  smart-bill-manager:
    image: ghcr.io/tuoro/smart-bill-manager:v0.7.0
    container_name: smart-bill-manager
    restart: unless-stopped
    init: true
    stop_grace_period: 20s
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - sbm-data:/var/lib/sbm

volumes:
  sbm-postgres:
  sbm-data:

升级时换用新的镜像 tag 重建应用容器。存在未执行的数据库迁移时应用会拒绝启动并提示——迁移原地修改数据且不可回滚,请先按备份与恢复创建并验证备份,再加 -e SBM_ALLOW_MIGRATION=true 重建。

加固参数、使用已有 PostgreSQL、卷内布局和日常运维见部署指南。

数据库与持久化

应用容器的所有持久数据都在 /var/lib/sbm 下,挂一个卷即可:

/var/lib/sbm/
├── objects/    # 上传的图片和 PDF        (sbm:sbm 0700)
├── secrets/    # 主密钥,由入口脚本管理  (root:sbm 0710,应用只能穿越)
└── config/     # 数据库连接与密码        (sbm:sbm 0700,初始化页写入)

PostgreSQL 数据在它自己的容器卷里。首次启动时若未挂载主密钥,入口脚本会在 secrets/ 内生成一份并在日志中提示——它和数据在同一个卷里,必须单独复制一份到别处保管,丢失后已保存的 Provider API Key 无法恢复。

备份必须同时覆盖数据库、对象文件和主密钥,且按备份与恢复说明生成认证备份包。把卷或数据目录整个复制不构成可恢复的备份。

Clean Slate 只表示不读取旧架构和 SQLite 数据。从当前新架构开始,后续版本默认保留数据,并通过版本化 PostgreSQL Schema migration 升级数据库结构;不会要求用户每次更新都清空数据库。

主要能力

  • 图片和 PDF 上传、批量逐项反馈与多页审核;
  • 最小中文多模态提取、本地确定性规范化和字段级校验;
  • 失败转人工审核、正式单据检索与可追溯纠错,不绕过 Source → Claim → Fact;
  • 手工创建行程、组合多张机票与其他单据、自动归属及辅助材料管理;
  • 重复候选、支付—发票分配、默认 30 天推荐与说明原因后的跨期手工分配;
  • 坏账标记/解除及相关行程删除保护,不自动核销金额;
  • 邮件附件本地归档、报销状态和材料 ZIP 导出;
  • 成员邀请、角色管理、自助改密与本地账号恢复;
  • 确定性数据洞察、租户隔离、审计、认证备份与完整恢复。

安全与数据边界

Source -> Claim -> Fact
原始证据 -> 可审核候选(AI 或显式人工来源)-> 用户确认的数据
  • 模型不能直接创建 Fact;Schema、本地业务规则、权限和人工审核缺一不可。
  • PostgreSQL 17 是唯一关系数据源,金额始终使用整数最小单位。
  • API Key 加密保存,主密钥独立托管;部署工具不把 secret 放入环境、参数或仓库。
  • 新系统不兼容旧代码、旧 API、旧数据库或旧任务状态,也不读取或迁移 v0.2.4 及更早版本数据。
  • 默认只监听 127.0.0.1。不要未经 TLS 和生产验收直接暴露到局域网或公网。

当前限制

  • 首个镜像仅支持 linux/amd64;
  • 正式真实模型正确率评测尚未完成;
  • 邮箱页面当前只保存无凭据连接描述符,不连接真实邮箱;
  • 不包含域名、TLS、反向代理、远程 PostgreSQL、高可用或云对象存储;
  • 不提供旧架构或 SQLite 数据导入;当前 Clean Slate PostgreSQL 版本之间默认保留数据并进行结构升级。

文档

入口 内容
部署指南 安装、初始化、启动、停止和网络边界
本地运维 健康检查、容量、诊断与升级边界
成员与账号 成员邀请、停用、自助改密与本地恢复说明
钉钉收单 建钉钉应用、启用连接器、绑定账号与聊天里审单
材料包导出 当前行程与固定报销快照 ZIP、文件范围和资源限制
备份与恢复 认证备份、验证和完整恢复
产品与范围 / 路线图 产品定位、已完成范围和后续门禁
架构 / 数据模型 Source、Claim、Fact 与 PostgreSQL 设计
AI 流水线 模型契约、规范化、校验和审核
验收标准 / M4 证据 本地质量门禁和安全聚合证据

旧 backend-go/、frontend/、根 Dockerfile 和根 Compose 只保留为历史参考,不是当前运行入口。旧版本请使用对应历史 Release。

安全与许可

安全问题请按 SECURITY.md 私下报告,不要在公开 Issue 中披露。项目采用 MIT License。

About

Self-hosted bill and invoice manager with OCR, email ingestion, travel tracking, and multi-user data isolation.

Topics

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages