Files
YPMS/pyproject.toml
T
Chris TonjesandClaude Opus 5.5 5f2d885fdc Phase 0 milestone 0.8: CI pipeline on Gitea Actions
Workflow moved to .gitea/workflows/ci.yml (Gitea is the CI host). Every
gate now passes locally, step-for-step; green on main is pending an
act_runner on gitea.doesworks.net (runs #1-#5 are queued "Waiting").

Gate fixes found by actually running them:
- pip-audit: `--disable-pip` without `-r` was a usage error, so the old
  step could never pass. Now `pip-audit --strict .` audits the runtime
  dependency set from pyproject.
- pip-audit then flagged ecdsa (PYSEC-2026-1325, no fix), a hard dep of
  python-jose. Swapped to PyJWT (HS256 only; 3-line change in
  auth/security.py). Flag to OWC.
- PyJWT warned the test JWT secret was 11 bytes. JWT_SECRET now requires
  >= 32 bytes (RFC 7518 s3.2) at settings load; dev/compose/test defaults
  updated. Test-only value carries an inline gitleaks:allow.
- bandit B101: assert in retention._count_past replaced with a raise.
- gitleaks: gitleaks-action needs a GitHub token/license; replaced with
  the pinned 8.30.1 binary, sha256-verified, scanning full history.

Added:
- SBOM: CycloneDX 1.6 from a clean runtime-only venv (39 components),
  uploaded as a CI artifact. YPMS-POAM-042.
- cyclonedx-bom in dev extras; CI outputs gitignored.

158 tests passing, 95.83% coverage; ruff, mypy, bandit, pip-audit,
gitleaks clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 10:57:09 -04:00

92 lines
2.3 KiB
TOML

[project]
name = "ypms"
version = "0.1.0"
description = "DC Youth Program Management System"
requires-python = ">=3.12"
dependencies = [
"fastapi>=0.115",
"uvicorn[standard]>=0.30",
"sqlalchemy>=2.0",
"alembic>=1.13",
"psycopg[binary]>=3.2",
"pydantic[email]>=2.8",
"pydantic-settings>=2.4",
"passlib>=1.7",
"pyjwt>=2.9",
"python-multipart>=0.0.9",
"structlog>=24.4",
"cryptography>=43",
"jinja2>=3.1",
]
[project.optional-dependencies]
dev = [
"pytest>=8.3",
"pytest-asyncio>=0.24",
"pytest-cov>=5.0",
"httpx>=0.27",
"ruff>=0.6",
"mypy>=1.11",
"bandit>=1.7",
"pip-audit>=2.7",
"cyclonedx-bom>=4",
]
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
where = ["src"]
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
addopts = "-ra --strict-markers"
[tool.coverage.run]
source = ["src/ypms"]
omit = [
"tests/*",
# router.py is testable end-to-end only once the auth stack lands in
# milestone 0.3. The framework tests exercise its underlying CRUDService
# + BulkOps directly, which is where the real logic lives.
"src/ypms/framework/router.py",
]
[tool.coverage.report]
show_missing = true
skip_covered = false
[tool.ruff]
line-length = 100
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM"]
# E501: handled by formatter; B008: FastAPI's Depends() in defaults is canonical
ignore = ["E501", "B008"]
[tool.mypy]
python_version = "3.12"
strict = true
ignore_missing_imports = true
# The generic router factory has to work with runtime-bound type variables
# that FastAPI introspects via typing.get_type_hints. That means the closure
# uses `create_t: type[BaseModel]` bindings which mypy can't model precisely.
# See ARCHITECTURE.md §4.1. Same suppression pattern as OWC's framework.
[[tool.mypy.overrides]]
module = "ypms.framework.router"
disable_error_code = ["valid-type", "type-arg", "attr-defined", "unused-ignore"]
# Generic CRUD uses TypeVars mypy can't fully model — the ModelT.id and
# ModelT.deleted_at accesses require a Protocol bound we don't ship for
# ergonomics. Same suppression pattern OWC uses in practice.
[[tool.mypy.overrides]]
module = "ypms.framework.crud"
disable_error_code = ["attr-defined", "valid-type", "unused-ignore"]
[tool.bandit]
exclude_dirs = ["tests", "migrations"]