Skip to content

Backend architecture ​

HoHu uses FastAPI, SQLAlchemy 2.0 async sessions, and Pydantic. Business code lives in app/modules/<module>/. For a complete implementation, see the business notes tutorial.

Request flow ​

LayerResponsibilityKeep elsewhere
APIValidate input, authenticate, check action permissions, obtain trusted tenant context, call services, commit, and return responsesDetailed cross-module business workflows
ServiceApply business rules and tenant/record scope, query or modify data, and flush when neededHTTP responses and database commits
ModelTables, fields, relationships, indexes, and constraintsUI formatting and authorization decisions
SchemaInput validation, aliases, output fields, and serializationDatabase queries

Route dependencies obtain the current user or get_current_tenant_context from app/modules/auth/service.py. Action checks use require_permissions from app/core/auth.py. Services still apply tenant and record filters; a client-supplied tenant ID cannot replace trusted context.

Transactions and errors ​

Services may call await db.flush() to obtain generated values, but must not commit. The API calls await db.commit() after all business operations succeed, then returns success. Invalidate caches after the commit. Jobs and other non-HTTP callers must define their own transaction boundaries too.

Use domain exceptions from app/core/exceptions.py with stable error codes. Reuse the shared exception handler. Do not raise HTTPException in business logic or catch every error and return success. See error handling.

API contract reference ​

ItemConvention
Success{code: 200, msg, data}, returned through ResponseModel.success(...)
Paginationdata.records, data.total, data.current, data.size
IDsSnowflake IDs are JSON strings; do not convert them to JavaScript Number
Field namessnake_case in Python; camelCase aliases in API schemas
TimeISO 8601 UTC according to the endpoint contract; format for display in the UI
InputDefine fields and limits; reject client control over server-managed tenant, owner, and audit fields

Naming and ID conversion come from schema configuration and serializers, not an automatic transformation of arbitrary dictionaries. Follow the notes example for alias_generator, from_attributes, and ID serializers.

Module registration checklist ​

  1. Register the business router in app/main.py.
  2. Import models in alembic/env.py, generate a migration, and review it.
  3. Register tenant-owned tables in app/core/tenant_inventory.py and its tests.
  4. Add pages and permissions to menu seeds, synchronize them, and grant access through an administrator.

See repository structure for paths, Web pages and requests for frontend integration, and debugging and validation before delivery.