Files
nextcraft/apps/ai-service/pyproject.toml
T
CIAgent 2d9f3201b3 feat(P01): sandbox backend + workdir + deps + config (Wave 1)
Task 1-1-01: SandboxBackend protocol + UnshareBackend (unshare user/mount/pid/net)
+ workdir layout (workspace/ + snapshots/). Isolation probe real on this box:
in-ns uid=0, network isolated (fresh net ns, lo only), writes contained to per-sandbox
bind dir; proc-remount not permitted (documented, not required). Deviations (documented):
util-linux 2.38.1 lacks --bind flag -> bind moved into namespace via sh -c mount shim;
rlimits moved into shim (preexec would kill the pytest interpreter); userns != DAC barrier
(host-uid-owned targets), documented for hardening under D-025.

Task 1-1-02: add sqlmodel, sqlalchemy, websockets, aiofiles (PyPI-verified); config keys
SANDBOX_DIR/MAX_CONCURRENT=5/TIMEOUT_S=900/MAX_WORKDIR_MB=512/DB_PATH (D-024/027/032/G-2).

Task 1-1-03: README sandbox isolation section with real probe transcript + locked
resource-limit mechanism (G-1/G-2); ruff config already correct (no change).

139/139 tests pass; ruff clean. .gitignore: ignore all ai-service sandboxes dirs (runtime+tests).

---ci---
phase: 1
milestone: v0.3
status: execute
requirements: {covered: [REQ-3-001, REQ-3-002], partial: []}
---/ci---
2026-09-12 00:47:45 +00:00

44 lines
1022 B
TOML

[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[project]
name = "nextcraft-ai-service"
version = "0.2.0"
description = "Nextcraft AI tutor service — six LLM agents behind a provider-agnostic layer"
requires-python = ">=3.11"
dependencies = [
"fastapi>=0.141,<0.142",
"uvicorn>=0.52,<0.53",
"pydantic>=2.13,<2.14",
"pydantic-settings>=2.15,<2.16",
"httpx>=0.28,<0.29",
"sse-starlette>=3.4,<3.5",
"sqlmodel>=0.0.24,<0.1",
"sqlalchemy>=2.0,<2.1",
"websockets>=13,<16",
"aiofiles>=24.1,<26",
]
[project.optional-dependencies]
dev = [
"pytest>=9.1,<10",
"pytest-asyncio>=1.4,<2",
"ruff>=0.14",
]
[tool.setuptools.packages.find]
include = ["ai_service*"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
[tool.ruff]
line-length = 100
target-version = "py311"
[tool.ruff.lint]
select = ["E", "F", "W", "I", "UP", "B"]
# B008: Depends() in argument defaults is the idiomatic FastAPI DI pattern
ignore = ["B008"]