Files
praxis/pyproject.toml
T
Praxis CI e39521d51d feat(P01): SLICE-03 operator auth — argon2id + signed cookies + rate limit
- TASK-03-01 server/auth/passwords.py: argon2id via argon2-cffi
  PasswordHasher (t=3, m=64MiB, p=4 — exceeds OWASP). hash/verify/
  needs_rehash; verify returns False on mismatch (uniform 401 path).
- TASK-03-02 server/auth/cookies.py: get_session_middleware_kwargs()
  → Starlette SessionMiddleware (itsdangerous HMAC-SHA256, D-056).
  Cookie praxis_op, httpOnly, SameSite=strict, max_age=28800 (8h).
  PRAXIS_COOKIE_SECURE default true; false logs WARNING (R-AUTH-01).
  G-031 reframe documented: k-anon defense-in-depth is the PRIMARY
  mitigation (sniffed cookie → no PII); secure flag is SECONDARY.
- TASK-03-03 server/auth/rate_limit.py: slowapi Limiter (in-memory,
  D-041), 5/minute per IP on login. reset_login_rate_limit() helper.
- TASK-03-04 server/auth/dependencies.py + models.py: current_operator
  Depends — reads signed-cookie session, fetches operator from PgStore,
  401 on missing/invalid/inactive (clears session), 503 if no Postgres.
  Never trusts the client (D-057).
- TASK-03-05 server/auth/routes.py: APIRouter(prefix=/api/operator)
  with POST /login (rate-limited, rehash-on-login), POST /logout
  (auth-gated, clears session), GET /me (auth-gated, React guard).
- TASK-03-06 tests/test_auth.py: 18 unit tests (mocked PgStore) —
  passwords, cookie config, rate limit, 401/503 cases, login/logout/me,
  rehash-on-login.
- pyproject.toml: added itsdangerous>=2.1 (SessionMiddleware dep).

---ci---
project: praxis
phase: 1
milestone: v0.4
status: execute
persona: security-engineer
task: 03-01,03-02,03-03,03-04,03-05,03-06
requirements:
  covered: [REQ-AUTH-01, REQ-NFR-AUTH-01]
  grill:
    - G-031 (R-AUTH-01 reframe: k-anon primary, secure flag secondary)
---/ci---
2026-08-04 00:52:16 +00:00

72 lines
2.3 KiB
TOML

[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "praxis-server"
version = "0.1.0"
description = "Praxis — voice-first AI apprenticeship platform (v0.1 foundation: minimal viable voice loop)"
readme = "README.md"
requires-python = ">=3.11"
license = { text = "Proprietary" }
authors = [{ name = "Praxis v0.1 (CIAgent)" }]
dependencies = [
# Web framework — FastAPI serves /health + /pipecat/webrtc + StaticFiles (D-023)
"fastapi>=0.110",
# ASGI server — uvicorn runs the FastAPI app (used by server.__main__.main)
"uvicorn>=0.30",
# Orchestration — Pipecat (D-017) with the three native service extras + WebRTC transport
"pipecat-ai[deepgram,cartesia,piper,webrtc]>=1.6.0",
# LLM access — Ollama Cloud direct API (D-020). Pipecat's OLLamaLLMService uses the
# OpenAI-compatible client; we point base_url at https://ollama.com/v1 + bearer key.
"openai>=1.40",
# Scenario format — YAML DSL → Pydantic (D-018)
"pydantic>=2.7",
"pyyaml>=6.0",
# Learner state — SQLite (D-007), async access
"aiosqlite>=0.20",
# Config
"python-dotenv>=1.0",
# Latency probes — HTTP client for the integrated e2e probe
"httpx>=0.27",
"websockets>=12.0",
# Audio probe fixture generation (synthesized PCM) for the ASR probe
"numpy>=1.26",
# VC issuer (SLICE-09) — Ed25519 sign/verify (libsodium), JCS canonicalization
# (RFC 8785), base58-btc for Multikey proofValue encoding.
"pynacl>=1.5",
"canonicaljson>=2.0",
"base58>=2.1",
# v0.4 operator tier — Postgres pool (D-050), argon2id passwords (D-041),
# slowapi rate limiting (D-041). RESEARCH-v0.4 §new-deps.
"asyncpg>=0.29",
"argon2-cffi>=23.1",
"slowapi>=0.1",
# SessionMiddleware uses itsdangerous for signed cookies (D-056).
"itsdangerous>=2.1",
]
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-asyncio>=0.23",
"pytest-cov>=5.0",
]
[project.scripts]
praxis-server = "server.__main__:main"
[tool.setuptools.packages.find]
where = ["."]
include = ["server*", "db*", "scenarios*"]
exclude = ["client*", "tests*", "scripts*"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
python_files = ["test_*.py"]
addopts = "-ra -q"
[tool.coverage.run]
source = ["server", "db"]