[project] # PyPI distribution name. "open-ace" is rejected by PyPI as too similar to the # unrelated "openace" project; the import names and the `openace` CLI are unchanged. name = "open-ace-server" version = "2.1.1" description = "Self-hosted enterprise AI workspace and governance platform" readme = "README.md" license = "Apache-2.0" requires-python = ">=3.10" authors = [ {name = "Open ACE Team"} ] keywords = [ "ai", "ai-governance", "ai-workspace", "codex", "claude-code", "enterprise-ai", "llmops", "qwen-code", "self-hosted", ] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Framework :: Flask", "Topic :: Office/Business", "Topic :: Scientific/Engineering :: Artificial Intelligence", ] dependencies = [ "flask>=3.1.3,<4.0.0", "aiohttp>=3.14.1,<4.0.0", "websockets>=13.0,<17.0", "requests>=2.33.0,<3.0.0", "urllib3>=2.0.0,<3.0.0", "bcrypt>=4.0.0,<6.0.0", "PyJWT>=2.14.0,<3.0.0", "cryptography>=44.0.0,<51.0.0", "signxml>=4.2.2,<5.0.0", "filetype>=1.2.0,<2.0.0", "gunicorn>=23.0.0,<24.0.0", "gevent>=23.9.1,<25.0.0", "werkzeug>=3.1.3,<4.0.0", "sqlalchemy>=2.0.49,<3.0.0", "alembic>=1.16.5,<2.0.0", "PyYAML>=6.0.0,<7.0.0", "psycopg2-binary>=2.9.12,<3.0.0", "psycogreen>=1.0.0,<2.0.0", "openpyxl>=3.1.0,<4.0.0", "jinja2>=3.0.0,<4.0.0", "cachetools>=5.5.0,<8.0.0", "prometheus_client>=0.20.0,<1.0.0", "prometheus_flask_exporter>=0.23.0,<1.0.0", "typing_extensions>=4.0.0,<5.0.0", ] [project.optional-dependencies] dev = [ "pytest>=7.0.0", "pytest-cov>=4.0.0", "pytest-asyncio>=0.21.0", "pytest-rerunfailures>=10.0", "pytest-split>=0.8.0", "pytest-timeout>=2.0", "pytest-xdist>=3.0", "playwright>=1.40.0,<2.0.0", "bandit[toml]>=1.8.0,<2.0.0", "black==26.5.1", "build>=1.2.0,<2.0.0", "isort>=5.12.0", "ruff>=0.1.0", "mypy>=1.0.0", "pip-audit>=2.7.0,<3.0.0", "pre-commit>=3.0.0", "types-cachetools>=5.5.0", "types-requests>=2.28.0", ] [project.scripts] openace = "cli:main" [tool.setuptools] # Top-level modules referenced by console scripts must be packaged explicitly; # packages.find only covers the app*/scripts* package trees (issue #3171). py-modules = ["cli"] [tool.setuptools.packages.find] include = ["app*", "scripts*"] [tool.setuptools.package-data] "app.modules.workspace.autonomous" = [ "agent_bin/_guard_exec.py", "agent_bin/gh", "agent_bin/git", "agent_bin/pytest", "agent_bin/python", "agent_bin/python3", ] [project.urls] Homepage = "https://www.open-ace.com" Documentation = "https://github.com/open-ace/open-ace#readme" Repository = "https://github.com/open-ace/open-ace.git" Issues = "https://github.com/open-ace/open-ace/issues" Roadmap = "https://github.com/open-ace/open-ace/blob/main/ROADMAP.md" # ============================================================================= # Black Configuration # ============================================================================= [tool.black] line-length = 100 target-version = ['py310', 'py311'] include = '\.pyi?$' exclude = ''' /( \.git | \.hg | \.mypy_cache | \.tox | \.venv | _build | buck-out | build | dist | \.pytest_cache | __pycache__ | venv | env )/ ''' # ============================================================================= # isort Configuration # ============================================================================= [tool.isort] profile = "black" line_length = 100 known_first_party = ["app", "scripts", "shared"] sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] skip = [".git", ".hg", ".mypy_cache", ".tox", ".venv", "_build", "buck-out", "build", "dist", ".pytest_cache", "__pycache__", "venv", "env"] # ============================================================================= # Ruff Configuration # ============================================================================= [tool.ruff] line-length = 100 target-version = "py310" exclude = ["*.sh", "*.bash", "*.zsh", "*.ps1", "*.cmd", "docker-entrypoint.sh"] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # Pyflakes "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade "SIM", # flake8-simplify "TCH", # flake8-type-checking ] ignore = [ "E501", # line too long (handled by black) "B008", # do not perform function calls in argument defaults "B905", # zip without explicit strict parameter "SIM108", # use ternary operator "E402", # module import not at top of file (Flask app init order) "E722", # bare except (intentional in many routes) "E741", # ambiguous variable name (short names like l, I, O) "SIM102", # collapsible if (sometimes less readable) "SIM105", # suppressible exception (context manager overhead) "SIM117", # multiple with statements (readability) "B007", # unused loop control variable (common in enumerate) "B018", # useless expression (often intentional in scripts) "B904", # raise without from inside except (compatibility) "SIM115", # open file without context handler (scripts) "UP031", # printf string formatting (migration risk) "UP038", # deprecated: isinstance(x, A | B) is slower than isinstance(x, (A, B)) # TCH003 (move stdlib abc imports into TYPE_CHECKING block) is intentionally # disabled repo-wide: it is a stylistic refactor out of scope for individual # PRs and requires per-file verification (esp. in migrations/remote-agent). "TCH003", ] [tool.ruff.lint.per-file-ignores] "tests/*" = ["S101", "PLR2004", "F401", "F811", "TCH", "B017", "I001"] "scripts/*" = ["TCH", "F401", "I001", "UP035"] "**/__init__.py" = ["F401"] # ============================================================================= # MyPy Configuration # ============================================================================= [tool.mypy] python_version = "3.10" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = false disallow_incomplete_defs = false check_untyped_defs = true ignore_missing_imports = true show_error_codes = true show_column_numbers = true pretty = true [[tool.mypy.overrides]] module = "tests.*" ignore_errors = true [[tool.mypy.overrides]] module = "scripts.*" disable_error_code = ["no-any-return", "arg-type", "union-attr", "operator", "index", "has-type", "return-value"] # Issue #2131: Ignore type errors in app modules that are not directly checked # by pre-commit but are found through dependency resolution [[tool.mypy.overrides]] module = [ "app.ws_frame", "app.utils.outbound_url_guard", "app.modules.governance.alert_notifier", "app.modules.workspace.terminal_ws_bridge", "app.modules.workspace.vscode_ws_bridge", "app.routes.workspace", "app.routes.sso", "app.routes.auth", "app.routes.api_keys", "app.routes.alerts", "app.routes.autonomous", "app", ] ignore_errors = true # ============================================================================= # Pytest Configuration # ============================================================================= [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py", "*_test.py"] python_classes = ["Test*"] python_functions = ["test_*"] # addopts moved to pytest.ini to avoid duplicate key error filterwarnings = [ "ignore::DeprecationWarning", ] # ============================================================================= # Coverage Configuration # ============================================================================= [tool.coverage.run] # Phase 1: P0 security modules (Issue #1856). # Phase 2 (eval §6.2 P1-3): expand to app/routes + app/services so the coverage # gate measures the HTTP + business-logic surface, not just the security core. # The CI gate is driven by the --cov flags in ci/suites.json (python-core # suite); keep this source list in sync with them. # Gradually expand: P0 → P1 → P2 source = [ "scripts/shared", "server.py", "cli.py", "app/auth", "app/remote_ws_handler", "app/modules/sso", "app/routes", "app/services", ] omit = [ "tests/*", "*/__pycache__/*", "*/.venv/*", "*/venv/*", ] [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "@abstractmethod", ] show_missing = true skip_covered = true # ============================================================================= # Bandit Configuration (Security Linter) # ============================================================================= [tool.bandit] exclude_dirs = ["tests", ".venv", "venv", ".qwen"] skips = ["B101", "B601"]