infrasynth-backend-kit/pyproject.toml
jcv-dev a2930426b4 feat: tenant configs, live signals, and automatic permission management
- infrasynth.configs: typed multi-tenant config store (registry, service,
  secrets, cache) + public config_changed/config_reset signals and API
- emit the declared-but-dead signals (features flags/overrides, scheduler
  task_completed/task_failed, tenancy tenant_updated, audit model_changed)
  and per-model audit field exclusions
- security: permission catalog (security_permission), Django-style
  model-derived AutoPermission, PermissionRegistry, RoleAssignment,
  global-or-tenant Grant/Revoke, catalog API
- consolidate the permission surface: PermissionRegistry only (drop the
  settings dict), IsAuthenticatedAndPermitted aliases HybridPermission,
  require_permission replaced by required_permissions + require_all
- packaging: add [build-system]; add Forgejo publish workflow (.forgejo)
2026-09-29 17:06:54 -05:00

136 lines
4.3 KiB
TOML

[build-system]
# PEP 518/517: required so `python -m build` produces sdist + wheel.
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "infrasynth-base"
version = "1.0.0"
description = "InfraSynth Base — reusable Django infrastructure kit"
requires-python = ">=3.12"
license = { text = "MIT" }
dependencies = [
"django>=5.2,<6.0", # the framework the whole kit targets
"djangorestframework>=3.16,<4.0", # API layer, viewsets, serializers
"django-cors-headers>=4.7", # CORS for the SPA frontends
"djangorestframework-simplejwt>=5.5", # JWT minting/validation behind the cookie auth
"djangorestframework-camel-case>=1.4", # wire-format camelCase (API-STANDARD §3)
"drf-spectacular>=0.28", # live OpenAPI schema at /api/v1/schema/ (API-STANDARD §12)
"django-filter>=25.1", # per-view FilterSets
"psycopg2-binary>=2.9", # PostgreSQL driver
"python-dotenv>=1.0", # local .env loading
"cryptography>=44.0", # Fernet encryption for secrets at rest
"pydantic>=2.0", # settings/validation helpers
"pyotp>=2.10", # TOTP 2FA
"qrcode[pil]>=8.1", # 2FA provisioning QR codes
"celery[redis]>=5.4", # background tasks
"django-celery-results>=2.5", # Celery result backend models
"django-celery-beat>=2.7", # periodic task scheduling
"boto3>=1.35", # S3 storage backend
"django-storages>=1.14", # cloud storage backends (S3/GCS)
"Pillow>=11.0", # image processing pipelines
"reportlab>=4.2", # invoice PDF generation
"twilio>=9.0", # SMS notification channel
"stripe>=10.0", # Stripe payment gateway
"mercadopago>=3.0", # MercadoPago payment gateway
"requests>=2.32", # outbound webhook delivery
"flower>=2.0", # Celery monitoring dashboard
"gunicorn>=23.0", # production WSGI server
]
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-django>=4.8",
"pytest-cov>=5.0",
"factory-boy>=3.3",
"faker>=28.0",
"ruff>=0.6",
"mypy>=1.11",
"pre-commit>=3.8",
"django-stubs[compatible-mypy]>=5.2",
"djangorestframework-stubs[compatible-mypy]>=3.16",
"types-requests",
"hypothesis>=6.0", # property tests for time/token/billing math (AGENTS §11)
"schemathesis>=3.0", # contract tests against the live OpenAPI schema (API-STANDARD §15)
]
# Enable with INFRASYNTH_FILES["VIRUS_SCANNER"]="clamav".
clamav = ["clamd>=0.5"] # ClamAV client for the files virus-scan step
[tool.setuptools.packages.find]
include = ["infrasynth*"]
[tool.setuptools.package-data]
infrasynth = ["**/*.py", "**/migrations/*.py"]
[tool.ruff]
target-version = "py312"
line-length = 120
[tool.ruff.lint]
select = ["E", "F", "I", "N", "W", "UP"]
[tool.ruff.lint.per-file-ignores]
"**/migrations/*.py" = ["E501"]
"config/settings/*.py" = ["F403", "F405"]
[tool.ruff.format]
quote-style = "double"
[tool.mypy]
python_version = "3.12"
plugins = ["mypy_django_plugin.main"]
strict_equality = true
no_implicit_optional = true
disallow_untyped_defs = false
disallow_any_generics = false
disallow_subclassing_any = false
disallow_untyped_calls = false
disallow_untyped_decorators = false
disallow_incomplete_defs = false
check_untyped_defs = false
no_implicit_reexport = true
warn_redundant_casts = true
warn_return_any = false
warn_unused_ignores = false
disable_error_code = ["var-annotated", "no-any-return", "import-untyped"]
[[tool.mypy.overrides]]
module = [
"mercadopago.*",
"mercadopago",
"twilio.*",
"twilio",
"stripe.*",
"stripe",
"cloudinary.*",
"cloudinary",
"storages.*",
"rest_framework_simplejwt.*",
]
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = "infrasynth.billing.gateways.stripe"
disable_error_code = ["attr-defined"]
[tool.django-stubs]
django_settings_module = "config.settings.test"
[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "config.settings.test"
testpaths = ["tests"]
python_files = ["test_*.py"]
[tool.coverage.run]
source = ["infrasynth"]
omit = ["*/migrations/*", "*/__init__.py"]
[tool.coverage.report]
show_missing = true
skip_covered = true
# Gate for the whole package. The binding bar is ≥95% on the *public API
# surface* plus 100% branch coverage on security-relevant code (AGENTS §11);
# this floor keeps total coverage from regressing while that surface grows.
fail_under = 85