- core:配置(prod 拒绝默认密钥 / dev 短信 / 假模型)、租户事务 + 行级安全策略、 problem+json 错误码、信封加密与签名下载、对象存储、事务内入队、Valkey stream 事件流、权限点 - identity:手机号 HMAC 存储、注册、登录(挤下线需确认,API3)、服务端会话 - billing:额度流水只追加,预扣 / 结算 / 退回,一笔预扣只有一个结局 - document:分片上传、按文件头识别格式、Gotenberg 转换、文字层与稳定句子编号 - checklist:标注规则识别、模型抽取、三道校验、标注类条款规则兜底、重跑对齐 - ai:提示词注册表(extract.substantive v1 来自 S4 v2)、假模型、OpenAI 兼容供应商、ai_call 流水 - 迁移:data-model 基线、套餐、Procrastinate、会话状态函数 - 测试 30 个:租户隔离、额度、失败退回、对象加密、契约一致性 - Compose(含 migrate)、镜像、CI Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
2.5 KiB
TOML
92 lines
2.5 KiB
TOML
[project]
|
||
name = "bid-doctor"
|
||
version = "0.1.0"
|
||
description = "标博士服务端:业务接口(api)和后台任务(worker)是同一套代码、两种进程"
|
||
requires-python = ">=3.12"
|
||
dependencies = [
|
||
"fastapi>=0.115",
|
||
"uvicorn[standard]>=0.32",
|
||
"pydantic>=2.9",
|
||
"pydantic-settings>=2.6",
|
||
"sqlalchemy[asyncio]>=2.0.36",
|
||
"psycopg[binary,pool]>=3.2",
|
||
"alembic>=1.14",
|
||
"procrastinate>=3.10,<4", # core/queue.py 直接调用它的 SQL 函数,升级大版本前要核对
|
||
"redis>=5.2",
|
||
"httpx>=0.28",
|
||
"pypdfium2>=4.30",
|
||
"pdfplumber>=0.11",
|
||
"python-multipart>=0.0.18",
|
||
"cryptography>=44",
|
||
]
|
||
|
||
[dependency-groups]
|
||
dev = [
|
||
"pytest>=8.3",
|
||
"pytest-asyncio>=0.25",
|
||
"ruff>=0.8",
|
||
"pyright>=1.1.390",
|
||
"import-linter>=2.1",
|
||
"pyyaml>=6",
|
||
]
|
||
|
||
[project.scripts]
|
||
bid-doctor = "bid_doctor.cli:main"
|
||
|
||
[build-system]
|
||
requires = ["hatchling>=1.26"]
|
||
build-backend = "hatchling.build"
|
||
|
||
[tool.hatch.build.targets.wheel]
|
||
packages = ["src/bid_doctor"]
|
||
|
||
[tool.ruff]
|
||
line-length = 120
|
||
target-version = "py312"
|
||
src = ["src", "tests"]
|
||
|
||
[tool.ruff.lint]
|
||
select = ["E", "F", "W", "I", "B", "UP", "SIM", "RUF", "ASYNC", "S", "BLE", "PT"]
|
||
ignore = [
|
||
"RUF001", "RUF002", "RUF003", # 中文全角标点是有意的
|
||
"S101", # assert 用来表达不变量
|
||
]
|
||
|
||
[tool.ruff.lint.per-file-ignores]
|
||
"tests/**" = ["S", "PT011", "PT018"]
|
||
"migrations/**" = ["E402"]
|
||
|
||
[tool.pyright]
|
||
include = ["src"]
|
||
pythonVersion = "3.12"
|
||
venvPath = ".."
|
||
venv = ".venv"
|
||
typeCheckingMode = "strict"
|
||
reportMissingTypeStubs = false
|
||
reportUnknownMemberType = false
|
||
reportUnknownVariableType = false
|
||
reportUnknownArgumentType = false
|
||
|
||
[tool.pytest.ini_options]
|
||
asyncio_mode = "auto"
|
||
asyncio_default_fixture_loop_scope = "session"
|
||
asyncio_default_test_loop_scope = "session"
|
||
testpaths = ["tests"]
|
||
pythonpath = ["."]
|
||
|
||
[tool.importlinter]
|
||
root_package = "bid_doctor"
|
||
|
||
[[tool.importlinter.contracts]]
|
||
name = "core 不依赖业务模块"
|
||
type = "forbidden"
|
||
source_modules = ["bid_doctor.core"]
|
||
forbidden_modules = ["bid_doctor.identity", "bid_doctor.billing", "bid_doctor.project", "bid_doctor.document",
|
||
"bid_doctor.checklist", "bid_doctor.ai", "bid_doctor.audit", "bid_doctor.notification"]
|
||
|
||
[[tool.importlinter.contracts]]
|
||
name = "业务模块不依赖 api 层的组合模块"
|
||
type = "forbidden"
|
||
source_modules = ["bid_doctor.document", "bid_doctor.checklist", "bid_doctor.billing", "bid_doctor.identity.service"]
|
||
forbidden_modules = ["bid_doctor.project.workbench", "bid_doctor.app"]
|