This file guides automated agents and contributors working in this repository. It mirrors CLAUDE.md and reflects current codebase practices.
PingPong is an educational AI assistant platform with:
- Backend: FastAPI (Python 3.11+), async SQLAlchemy, Pydantic v2
- Frontend: SvelteKit with TypeScript
web/pingpong(Svelte 4, Tailwind v3, Flowbite-Svelte)
- Authorization: OpenFGA
- Authentication: JWT (magic links, SAML/SSO)
- LMS: Canvas LTI 1.3
- DB: Postgres (prod) or SQLite (dev/tests)
pingpong/FastAPI app, models, schemas, authz, integrationsalembic/database migrationsweb/pingpong/main SvelteKit UI (Svelte 4)scripts/one-off scripts and CLI helpersconfig.toml,test_config.tomlconfiguration defaults/tests
uv sync
CONFIG_PATH=config.local.toml uv run fastapi dev pingpong --port 8000 --host 0.0.0.0 --reload
uv run pytest
uv run alembic revision --autogenerate -m "description of change"
uv run python -m pingpong db migratepnpm install
pnpm dev
pnpm check
pnpm lint
pnpm format
pnpm test./start-dev-docker.sh- Request middleware order: session parsing -> authz session -> DB session -> logging. Access
request.state["db"],request.state["authz"],request.state["session"]. - Authorization uses composable expressions in
pingpong/permission.py(Authz,LoggedIn,InstitutionAdmin) and OpenFGA model inpingpong/authz/authz.fga.json. - Database is async SQLAlchemy; use
config.db.driver.async_session()or@db_session_handlerfor non-request tasks. - Schemas live in
pingpong/schemas.py(Pydantic v2). Return schemas directly from endpoints. - Central config is
pingpong/config.pyviaBaseSettingsand TOML (CONFIG_PATH=config.local.toml).
- API client lives in
web/pingpong/src/lib/api.ts. UseexpandResponse/explodeResponsehelpers and streaming utilities insrc/lib/streams.ts. - State is managed with Svelte stores; conversation state uses
ThreadManagerinsrc/lib/stores/thread.ts. - UI uses Tailwind and Flowbite-Svelte components, plus custom components in
src/lib/components.
- Follow existing async-first patterns and type hints.
- Keep imports grouped: stdlib, third-party, local.
- Use logging via
logging.getLogger(__name__)and raiseHTTPExceptionfor HTTP errors. - Prefer Pydantic models for request/response shapes instead of raw dicts.
web/pingpong:
- Prettier config uses 2 spaces, single quotes, no trailing commas, print width 100.
- ESLint with
@typescript-eslintandeslint-plugin-svelte.
- Add route handlers in
pingpong/server.pyalongside related endpoints. - Add/extend Pydantic schemas in
pingpong/schemas.py. - Apply permission expressions via
Depends(Authz(...)). - Implement client call in
web/pingpong/src/lib/api.ts. - Add tests under
pingpong/test_*.pyusing fixtures inconftest.pyand helpers inpingpong/testutil.py.
- Update models in
pingpong/models.py. - Generate migration:
uv run alembic revision --autogenerate -m "description". - Review migration in
alembic/versions/. - Apply:
uv run python -m pingpong db migrate.
- Tests load
test_config.tomlautomatically (conftest.pysetsCONFIG_PATH). - Dev email uses the mock sender; check API console output for magic links.
- LTI flows use
sessionStoragefor iframe-safe session tokens in the main UI.