π Product marketplace¶
Multi-tenant sales platform Mercado Livre / Shopee style, no external integrations. The point is to exercise tempest-fastapi-sdk in a realistic scenario β auth, multi-tenant, RBAC, idempotency, auditable stock, orders with a state machine, real-time SSE status, MinIO uploads, transactional email.
Project pages¶
| Page | What's there |
|---|---|
| Business rules | The domain written as prose β who can do what, under which conditions. Read first. |
| Domain model | UML class + ER diagrams, every entity explained (attributes, invariants, relationships). |
| Critical flows | Sequence diagrams covering signup, member invite, product creation, checkout, shipment. Order and Invitation state machines. |
| Endpoint map | Table of the whole REST API with method + path + auth + payload + status. |
Project setup (5 min)¶
# 1. Scaffold via SDK
tempest new marketplace --extras auth,admin,upload,cache,email,minio,queue,tasks,metrics
# 2. Boot the infra
cd marketplace
docker compose up -d
# 3. Configure env
cp .env.example .env
uv sync
# 4. Migrations (create the schema, including the users table)
uv run tempest db revision -m "init"
uv run tempest db upgrade
# 5. Bootstrap the first admin so /admin login works
uv run tempest user create --email admin@local --password admin-pass-12 --admin
# 6. Run
uv run python main.py
When the service boots you have:
- REST API at
http://localhost:8000 - Swagger docs at
http://localhost:8000/docs - SDK admin panel at
http://localhost:8000/admin - MinIO console at
http://localhost:9001(minioadmin/minioadmin) - RabbitMQ UI at
http://localhost:15672(guest/guest) - MailHog UI at
http://localhost:8025
SDK stack exercised¶
| Need | SDK primitive |
|---|---|
| Public signup + login + password reset | UserAuthService + make_auth_router (signup / activate / login / password-reset ready since v0.31.0) + BaseUserModel + BaseUserTokenModel |
| Access-token refresh via JWT pair | JWTUtils + make_jwt_user_dependency |
| Multi-tenant membership | BaseRepository[T], make_role_dependency, make_permission_dependency |
| Member invitation | EmailUtils.render_template + generate_opaque_token/hash_opaque_token |
| Variants + versioned prices | BaseModel + AuditMixin + SQLAlchemy 2.0 async relationships |
| Append-only stock with bulk seed | BaseModel (movement) + BaseRepository.bulk_create_values / bulk_upsert (v0.28+) |
| Non-duplicating checkout | IdempotencyMiddleware + RedisIdempotencyStore |
| Upload body-size limit | BodySizeLimitMiddleware (v0.28+) |
| Product images | UploadUtils + MinIOUploadStorage + presigned URLs |
| Real-time order status | EventStream, sse_response |
| Async notifications | AsyncTaskBrokerManager (TaskIQ) + AsyncBrokerManager (FastStream) |
| Public catalog cache | AsyncRedisManager, @cached |
| Oncall metrics | PrometheusMiddleware + make_prometheus_router (v0.28+) and MetricsUtils |
| Social OAuth (Google / GitHub) | GoogleOAuthClient / GitHubOAuthClient / OIDCProvider (v0.29+) |
| Safe server-rendered forms | CSRFMiddleware (v0.29+) |
| Outbound calls to external services | HTTPClient (v0.28+) with retry + circuit-breaker |
| Standardized errors | AppException hierarchy + register_exception_handlers |
Per-level logs + /logs |
configure_logging(log_dir=β¦) + make_logs_router |
Suggested structure¶
marketplace/
βββ main.py
βββ docker-compose.yaml
βββ pyproject.toml
βββ alembic/
βββ src/
βββ api/
β βββ app.py
β βββ routers/
β β βββ auth.py # signup + login + refresh
β β βββ organizations.py # CRUD org + members
β β βββ invitations.py # invite / accept / revoke
β β βββ catalog.py # public navigation
β β βββ products.py # product + variant CRUD (org-only)
β β βββ stock.py # in / out / adjust
β β βββ cart.py # buyer cart
β β βββ orders.py # checkout + status
β β βββ reviews.py # post-delivery reviews
β βββ dependencies/
β βββ auth.py # current_user, require_org_role
β βββ controllers.py
βββ controllers/ # cross-service orchestration
βββ services/ # domain logic
βββ schemas/ # Pydantic DTOs
βββ core/ # settings + exceptions + constants
βββ db/
β βββ models/ # ORM
β βββ repositories/ # queries
βββ queue/ # FastStream consumers
βββ tasks/ # TaskIQ tasks
βββ utils/
Recommended implementation order¶
- Auth β
UserModel(BaseUserModel)+UserTokenModel(BaseUserTokenModel)+ wireUserAuthService+make_auth_router. Five endpoints ready:/auth/signup,/auth/activate/{token},/auth/login,/auth/password-reset/request,/auth/password-reset/confirm. (Covers: abstract model concretization, bundled flow, JWT pair, Jinja2 templates.) See Auth flow recipe Β». - Organizations + members β
Organization+Membershipwith the 2-orgs-per-user / 10-members-per-org guard. (Covers: domain invariants, role-based access.) - Invitations β
Invitationwith opaque token, Jinja2 email, 7-day expiry. (Covers: transactional email.) - Catalog + products β
Product+ProductVariant+PriceHistory. (Covers: 1-N relationships, soft-delete.) - Stock β
StockMovement(append-only) + balance derived via view or aggregate query. (Covers: auditing, transactions.) - Cart + checkout β
Cart+Order+OrderItemwith idempotency. (Covers: state machine, idempotency.) - Real-time status via SSE β event stream for status changes. (Covers: SSE.)
- Product images β upload via
UploadUtils+MinIOUploadStorage+ listing with presigned URL. (Covers: storage.) - Async notifications β TaskIQ sending emails + RabbitMQ publishing events to projections / reports. (Covers: queues, tasks.)
- Metrics + admin β Prometheus endpoint +
/adminlisting entities. (Covers: observability, SDK admin.)
Each step ships one complete vertical slice β one feature end-to-end before adding the next.