Skip to content

costeaalex/chicc-chic

Repository files navigation

Chic-Chic: Subscription Limits Enforcement API

A backend service that simulates a SaaS subscription system with limits on staff members and bookings, built with FastAPI and SQLite.

Quick Start

# Install dependencies
just install

# Run the server
just run

# Run tests
just test

Or with Docker:

just docker-up

The API is available at http://localhost:8000. Interactive docs at http://localhost:8000/docs.

Authentication

All /accounts endpoints require a JWT Bearer token. Obtain one first:

# Get a token (credentials: user / user)
curl -X POST http://localhost:8000/token \
  -H "Content-Type: application/json" \
  -d '{"username": "user", "password": "user"}'

# Use the token in subsequent requests
curl -X POST http://localhost:8000/accounts \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Salon"}'

API Endpoints

Method Path Description
POST /token Get JWT access token
POST /accounts Create an account
POST /accounts/{id}/subscribe Assign a subscription
POST /accounts/{id}/staff Add a staff member
POST /accounts/{id}/bookings Create a booking
GET /health Health check

Subscription Plans

Feature Basic Pro
Max staff members 2 5
Max bookings per day 5 20

Project Structure

app/
  core/                         # Shared infrastructure
    auth.py                     # JWT authentication
    database.py                 # SQLAlchemy engine & session
    exceptions.py               # Domain exceptions
    plans.py                    # Plan type enum & limits config
  features/                     # Feature-based modules
    accounts/
      models.py                 # SQLAlchemy model
      schemas.py                # Pydantic request/response DTOs
      interfaces.py             # ABC interfaces (IAccountRepository, IAccountService)
      repository.py             # Database access layer
      service.py                # Business logic
      controller.py             # HTTP concern translation
      router.py                 # FastAPI route definitions & DI wiring
    staff/                      # Same layered structure
    bookings/                   # Same layered structure
    auth/                       # Token endpoint (controller + router)
tests/
  features/
    accounts/
      test_account_service.py   # Unit tests with mocked repository
    staff/
      test_staff_service.py
    bookings/
      test_booking_service.py

Design Decisions

  • Feature-based directory structure: Each domain concept (accounts, staff, bookings) is a self-contained module with its own model, schemas, interfaces, repository, service, controller, and router. This keeps related code colocated and makes it easy to navigate.
  • Layered architecture: Each feature follows the pattern: Router (route definitions) -> Controller (HTTP concern translation, exception-to-status mapping) -> Service (business logic) -> Repository (database access). Each layer has a single responsibility.
  • Interface segregation: Services and repositories implement abstract base classes (IAccountService, IStaffRepository, etc.). This enables dependency injection and makes unit testing straightforward — services are tested with mocked repositories, no database needed.
  • Domain exceptions: Business rule violations are expressed as domain exceptions (StaffLimitExceededError, BookingLimitExceededError) in core/exceptions.py. Controllers translate these to appropriate HTTP responses, keeping services framework-agnostic.
  • Plan limits as data: Subscription plan limits are defined in a PLAN_LIMITS dictionary in core/plans.py, making it straightforward to add new plans or adjust limits without touching business logic.
  • FastAPI dependency injection: Each router uses Depends() to wire the full dependency chain (db session -> repository -> service -> controller) per request.

Assumptions

  • Staff members and bookings are append-only (no delete/update endpoints needed).
  • The daily booking limit is per-account, not per-staff-member.
  • Changing an account's plan does not retroactively remove excess staff or bookings.
  • A single shared user authenticates all API requests (no per-account auth).
  • Staff and booking creation require an active subscription plan (returns 403 otherwise).

Production Improvements

  • Database: Replace SQLite with PostgreSQL for concurrent access and better performance.
  • User management: Implement proper user registration, password hashing (bcrypt/argon2), and per-account authorization.
  • DI container: Replace manual wiring in routers with a proper DI container (e.g., dependency-injector) for cleaner composition roots.
  • Rate limiting: Add request rate limiting to prevent abuse.
  • Pagination: Add list endpoints with cursor-based pagination for staff and bookings.
  • Plan upgrades/downgrades: Handle edge cases when switching plans (e.g., account has 5 staff on Pro and downgrades to Basic).
  • Soft deletes: Add soft-delete support for staff and bookings.
  • Migrations: Use Alembic for database schema migrations instead of create_all.
  • Observability: Add structured logging, request tracing, and metrics.
  • Environment config: Move secrets (JWT key) to environment variables with proper secret management.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors