Skip to main content

📋 Software Requirements Specification (SRS)

Product Catalog Service - Monolithic Application

Version: 1.0.0 Date: 2025-12-24 Based on: Building High-Performance APIs with FastAPI


1. Introduction

1.1 Purpose

This document describes the software requirements for the Product Catalog Service - a monolithic RESTful API application built with FastAPI, serving the purpose of learning and practicing according to the training syllabus.

1.2 Scope

The system provides:

  • User authentication with JWT
  • Product management (CRUD)
  • Role-based access control
  • Automatic API documentation
  • Unit testing

1.3 Definitions

TermDefinition
JWTJSON Web Token - Authentication Token
CRUDCreate, Read, Update, Delete
RBACRole-Based Access Control
DIDependency Injection

2. Overall Description

2.1 System Architecture

┌─────────────────────────────────────────────────────────────┐
│ Product Catalog Service │
│ (Port 8000) │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────┐ │
│ │ API Layer (FastAPI Routes) │ │
│ │ • POST /register, POST /login │ │
│ │ • GET/POST/PUT/DELETE /products │ │
│ └─────────────────────┬───────────────────────────────┘ │
│ │ │
│ ┌─────────────────────▼───────────────────────────────┐ │
│ │ Service Layer (Business Logic) │ │
│ │ • AuthService, ProductService │ │
│ └─────────────────────┬───────────────────────────────┘ │
│ │ │
│ ┌─────────────────────▼───────────────────────────────┐ │
│ │ Repository Layer (Data Access) │ │
│ │ • UserRepository, ProductRepository │ │
│ └─────────────────────┬───────────────────────────────┘ │
│ │ │
│ ┌─────────────────────▼───────────────────────────────┐ │
│ │ Database (PostgreSQL/SQLite) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

2.2 Technology Stack

LayerTechnology
FrameworkFastAPI 0.104+
ORMSQLAlchemy 2.0
MigrationsAlembic
ValidationPydantic 2.0
Authpython-jose, passlib, bcrypt
ServerUvicorn
DatabasePostgreSQL / SQLite

3. Functional Requirements by Training Unit

3.1 Unit 1: Foundation & Inputs (Assignment 01)

REQ-1.1: Hello World Endpoint

IDREQ-1.1
DescriptionAPI must have a root endpoint returning basic information
PriorityHigh
Status✅ Implemented

Acceptance Criteria:

  • GET / returns JSON with message, version, docs links
  • Response status code: 200
  • Content-Type: application/json

API Specification:

GET /
Response 200:
{
"message": "Welcome to Product Catalog Service API",
"version": "1.0.0",
"docs": "/docs",
"redoc": "/redoc"
}

REQ-1.2: Health Check Endpoint

IDREQ-1.2
DescriptionAPI must have a health check endpoint
PriorityHigh
Status✅ Implemented

Acceptance Criteria:

  • GET /health returns healthy status
  • Response includes service name and version

API Specification:

GET /health
Response 200:
{
"status": "healthy",
"service": "Product Catalog Service",
"version": "1.0.0"
}

REQ-1.3: OpenAPI Documentation

IDREQ-1.3
DescriptionAPI automatically generates OpenAPI documentation
PriorityHigh
Status✅ Implemented

Acceptance Criteria:

  • Swagger UI accessible at /docs
  • ReDoc accessible at /redoc
  • OpenAPI JSON at /openapi.json
  • All endpoints documented with descriptions

REQ-1.4: Path & Query Parameters

IDREQ-1.4
DescriptionAPI supports path and query parameters with data conversion
PriorityHigh
Status✅ Implemented

Acceptance Criteria:

  • GET /products/{product_id} - Path parameter (int)
  • GET /products?skip=0&limit=100 - Query parameters
  • Automatic type conversion and validation

3.2 Unit 2: Data Modeling - Pydantic (Assignment 02)

REQ-2.1: User Schemas

IDREQ-2.1
DescriptionDefine Pydantic schemas for User
PriorityHigh
Status✅ Implemented

Schema Definitions:

# UserCreate - Input schema
class UserCreate(BaseModel):
username: str # min_length=3, max_length=50
password: str # min_length=6

# UserResponse - Output schema
class UserResponse(BaseModel):
id: int
username: str
is_active: bool
created_at: datetime

model_config = {"from_attributes": True}

# Token - JWT response
class Token(BaseModel):
access_token: str
token_type: str # "bearer"

Acceptance Criteria:

  • UserCreate validates username (3-50 chars)
  • UserCreate validates password (min 6 chars)
  • UserResponse excludes password field
  • Validation errors return 422 with details

REQ-2.2: Product Schemas

IDREQ-2.2
DescriptionDefine Pydantic schemas for Product
PriorityHigh
Status✅ Implemented

Schema Definitions:

# ProductCreate - Input for creation
class ProductCreate(BaseModel):
name: str # min_length=1, max_length=100
description: str # optional, max_length=500
price: Decimal # gt=0, max_digits=10, decimal_places=2
quantity: int # ge=0

# ProductUpdate - Input for update (all optional)
class ProductUpdate(BaseModel):
name: Optional[str]
description: Optional[str]
price: Optional[Decimal]
quantity: Optional[int]

# ProductResponse - Output schema
class ProductResponse(BaseModel):
id: int
name: str
description: Optional[str]
price: Decimal
quantity: int
created_at: datetime
updated_at: datetime

model_config = {"from_attributes": True}

Acceptance Criteria:

  • Price validation: positive number, max 2 decimal places
  • Quantity validation: non-negative integer
  • Name required, description optional
  • response_model filters output fields

REQ-2.3: Nested Models Support

IDREQ-2.3
DescriptionSupport nested Pydantic models
PriorityMedium
Status⚠️ Partial

Acceptance Criteria:

  • Support nested structures in request/response
  • Proper serialization/deserialization

3.3 Unit 3: Database Setup (Assignment 03)

REQ-3.1: SQLAlchemy Models

IDREQ-3.1
DescriptionDefine SQLAlchemy 2.0 models
PriorityHigh
Status✅ Implemented

User Model:

class User(Base):
__tablename__ = "users"

id: int # Primary key, auto-increment
username: str # Unique, indexed, max 50 chars
hashed_password: str # Max 255 chars
is_active: bool # Default True
created_at: datetime # Server default now()
updated_at: datetime # Auto-update on change

Product Model:

class Product(Base):
__tablename__ = "products"

id: int # Primary key, auto-increment
name: str # Max 100 chars, indexed
description: str # Optional, max 500 chars
price: Numeric # Precision 10, scale 2
quantity: int # Default 0
created_at: datetime # Server default now()
updated_at: datetime # Auto-update on change

Acceptance Criteria:

  • Models use SQLAlchemy 2.0 style (Mapped annotations)
  • Proper indexes on frequently queried columns
  • Timestamps auto-managed

REQ-3.2: Database Connection

IDREQ-3.2
DescriptionSetup database connection with SQLAlchemy
PriorityHigh
Status✅ Implemented

Acceptance Criteria:

  • Support PostgreSQL and SQLite
  • Connection pooling configured
  • get_db dependency for session management
  • Proper session cleanup (try/finally)

Configuration:

# Environment variable
DATABASE_URL=postgresql://user:pass@localhost:5432/dbname
# or
DATABASE_URL=sqlite:///./product_catalog.db

REQ-3.3: Alembic Migrations

IDREQ-3.3
DescriptionDatabase migrations with Alembic
PriorityHigh
Status✅ Implemented

Acceptance Criteria:

  • alembic init configured
  • Auto-generate migrations from models
  • alembic upgrade head creates all tables
  • alembic downgrade -1 rollback works
  • Migration history tracked

Commands:

# Generate migration
alembic revision --autogenerate -m "description"

# Apply migrations
alembic upgrade head

# Rollback
alembic downgrade -1


3.4 Unit 4: CRUD & Dependency Injection (Assignment 04)

REQ-4.1: Dependency Injection Setup

IDREQ-4.1
DescriptionImplement DI pattern with FastAPI Depends()
PriorityHigh
Status✅ Implemented

Dependencies:

# Database session dependency
def get_db() -> Generator[Session, None, None]:
db = SessionLocal()
try:
yield db
finally:
db.close()

# Usage in routes
@router.get("/products")
def get_products(db: Session = Depends(get_db)):
pass

Acceptance Criteria:

  • get_db dependency properly yields session
  • Session closed after request
  • Dependencies injectable in routes

REQ-4.2: Repository Pattern

IDREQ-4.2
DescriptionImplement Repository pattern for data access
PriorityHigh
Status✅ Implemented

Base Repository:

class BaseRepository(Generic[T]):
def __init__(self, db: Session, model: Type[T]):
self.db = db
self.model = model

def create(self, obj_data: dict) -> T
def get_by_id(self, id: int) -> Optional[T]
def get_all(self, skip: int, limit: int) -> List[T]
def update(self, id: int, obj_data: dict) -> Optional[T]
def delete(self, id: int) -> bool

Acceptance Criteria:

  • Generic base repository with CRUD methods
  • UserRepository extends base with custom methods
  • ProductRepository extends base with custom methods
  • Separation of data access from business logic

REQ-4.3: Product CRUD Operations

IDREQ-4.3
DescriptionFull CRUD for Products
PriorityHigh
Status✅ Implemented

API Endpoints:

MethodEndpointDescriptionAuth
GET/productsList all productsNo
GET/products/{id}Get product by IDNo
POST/productsCreate productYes
PUT/products/{id}Update productYes
DELETE/products/{id}Delete productYes

Acceptance Criteria:

  • GET /products - Pagination with skip/limit
  • GET /products/{id} - 404 if not found
  • POST /products - 201 Created, return product
  • PUT /products/{id} - Partial update support
  • DELETE /products/{id} - 204 No Content

3.5 Unit 5: Authentication (Assignment 05)

REQ-5.1: User Registration

IDREQ-5.1
DescriptionUser registration endpoint
PriorityHigh
Status✅ Implemented

API Specification:

POST /register
Content-Type: application/json

Request:
{
"username": "john_doe",
"password": "SecurePass123"
}

Response 201:
{
"id": 1,
"username": "john_doe",
"is_active": true,
"created_at": "2025-10-18T10:00:00"
}

Response 400:
{
"detail": "Username already exists"
}

Acceptance Criteria:

  • Password hashed with bcrypt before storage
  • Duplicate username returns 400
  • Password not returned in response
  • User created as active by default

REQ-5.2: Password Hashing

IDREQ-5.2
DescriptionSecure password hashing
PriorityHigh
Status✅ Implemented

Implementation:

import bcrypt

def get_password_hash(password: str) -> str:
"""Hash password using bcrypt"""
return bcrypt.hashpw(
password.encode('utf-8'),
bcrypt.gensalt()
).decode('utf-8')

def verify_password(plain: str, hashed: str) -> bool:
"""Verify password against hash"""
return bcrypt.checkpw(
plain.encode('utf-8'),
hashed.encode('utf-8')
)

Acceptance Criteria:

  • Use bcrypt for hashing
  • Salt automatically generated
  • Verification function works correctly

REQ-5.3: User Login & JWT Token

IDREQ-5.3
DescriptionLogin endpoint returning JWT
PriorityHigh
Status✅ Implemented

API Specification:

POST /login
Content-Type: application/x-www-form-urlencoded

Request:
username=john_doe&password=SecurePass123

Response 200:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer"
}

Response 401:
{
"detail": "Incorrect username or password"
}

Acceptance Criteria:

  • OAuth2 Password Flow (form data)
  • JWT token contains username/user_id
  • Token expires after configured time
  • Invalid credentials return 401

REQ-5.4: JWT Token Generation

IDREQ-5.4
DescriptionJWT token creation and validation
PriorityHigh
Status✅ Implemented

Implementation:

from jose import jwt, JWTError
from datetime import datetime, timedelta

def create_access_token(data: dict) -> str:
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(
minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES
)
to_encode.update({"exp": expire})
return jwt.encode(
to_encode,
settings.SECRET_KEY,
algorithm=settings.ALGORITHM
)

def decode_access_token(token: str) -> Optional[str]:
try:
payload = jwt.decode(
token,
settings.SECRET_KEY,
algorithms=[settings.ALGORITHM]
)
return payload.get("sub")
except JWTError:
return None

Configuration:

SECRET_KEY=your-super-secret-key-min-32-characters
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

Acceptance Criteria:

  • Token contains "sub" claim with username
  • Token contains "exp" claim for expiration
  • Expired tokens rejected
  • Invalid tokens rejected

3.6 Unit 6: Authorization (Assignment 06)

REQ-6.1: Get Current User Dependency

IDREQ-6.1
DescriptionDependency to extract current user from JWT
PriorityHigh
Status✅ Implemented

Implementation:

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")

def get_current_user(
token: str = Depends(oauth2_scheme),
db: Session = Depends(get_db)
) -> User:
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)

username = decode_access_token(token)
if username is None:
raise credentials_exception

user = UserRepository(db).get_by_username(username)
if user is None:
raise credentials_exception

return user

Acceptance Criteria:

  • Extracts token from Authorization header
  • Decodes and validates JWT
  • Returns User object if valid
  • Raises 401 if invalid/expired

REQ-6.2: Protected Endpoints

IDREQ-6.2
DescriptionEndpoints require authentication
PriorityHigh
Status✅ Implemented

Protected Routes:

@router.post("/products")
def create_product(
product: ProductCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
# Only authenticated users can create
pass

Acceptance Criteria:

  • POST /products requires JWT
  • PUT /products/{id} requires JWT
  • DELETE /products/{id} requires JWT
  • GET endpoints remain public

REQ-6.3: Role-Based Access Control (RBAC)

IDREQ-6.3
DescriptionImplement roles for users
PriorityMedium
Status❌ Not Implemented

Required Changes:

  1. Add role to User model:
class User(Base):
# ... existing fields
role: str # "user", "admin"

  1. Role checking dependency:
def require_role(required_role: str):
def role_checker(
current_user: User = Depends(get_current_user)
) -> User:
if current_user.role != required_role:
raise HTTPException(
status_code=403,
detail="Insufficient permissions"
)
return current_user
return role_checker

# Usage
@router.delete("/products/{id}")
def delete_product(
id: int,
admin: User = Depends(require_role("admin"))
):
pass

Acceptance Criteria:

  • User model has role field
  • Default role is "user"
  • Admin endpoints check role
  • 403 Forbidden for insufficient permissions

3.7 Unit 7: Testing & Middleware (Assignment 07)

REQ-7.1: Unit Tests with Pytest

IDREQ-7.1
DescriptionUnit tests for API endpoints
PriorityHigh
Status❌ Not Implemented

Test Structure:

mono-src/
└── tests/
├── __init__.py
├── conftest.py # Fixtures
├── test_auth.py # Auth tests
├── test_products.py # Product tests
└── test_health.py # Health check tests

Required Tests:

# tests/conftest.py
import pytest
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from app.main import app
from app.database import Base, get_db

SQLALCHEMY_TEST_URL = "sqlite:///./test.db"
engine = create_engine(SQLALCHEMY_TEST_URL)
TestingSessionLocal = sessionmaker(bind=engine)

@pytest.fixture
def client():
Base.metadata.create_all(bind=engine)

def override_get_db():
db = TestingSessionLocal()
try:
yield db
finally:
db.close()

app.dependency_overrides[get_db] = override_get_db

with TestClient(app) as c:
yield c

Base.metadata.drop_all(bind=engine)

# tests/test_auth.py
def test_register_user(client):
response = client.post("/register", json={
"username": "testuser",
"password": "Test@123"
})
assert response.status_code == 201
assert response.json()["username"] == "testuser"

def test_register_duplicate_user(client):
client.post("/register", json={
"username": "testuser",
"password": "Test@123"
})
response = client.post("/register", json={
"username": "testuser",
"password": "Test@123"
})
assert response.status_code == 400

def test_login_success(client):
client.post("/register", json={
"username": "testuser",
"password": "Test@123"
})
response = client.post("/login", data={
"username": "testuser",
"password": "Test@123"
})
assert response.status_code == 200
assert "access_token" in response.json()

def test_login_wrong_password(client):
client.post("/register", json={
"username": "testuser",
"password": "Test@123"
})
response = client.post("/login", data={
"username": "testuser",
"password": "WrongPass"
})
assert response.status_code == 401

# tests/test_products.py
def test_get_products_empty(client):
response = client.get("/products")
assert response.status_code == 200
assert response.json() == []

def test_create_product_unauthorized(client):
response = client.post("/products", json={
"name": "Test Product",
"price": 99.99,
"quantity": 10
})
assert response.status_code == 401

def test_create_product_authorized(client):
# Register and login
client.post("/register", json={
"username": "testuser",
"password": "Test@123"
})
login_resp = client.post("/login", data={
"username": "testuser",
"password": "Test@123"
})
token = login_resp.json()["access_token"]

# Create product
response = client.post(
"/products",
json={
"name": "Test Product",
"price": 99.99,
"quantity": 10
},
headers={"Authorization": f"Bearer {token}"}
)
assert response.status_code == 201
assert response.json()["name"] == "Test Product"

Acceptance Criteria:

  • Test coverage > 80%
  • Tests use separate test database
  • Auth tests cover success/failure cases
  • CRUD tests cover all operations
  • Tests run with pytest tests/ -v

REQ-7.2: CORS Middleware

IDREQ-7.2
DescriptionCORS configuration for cross-origin requests
PriorityHigh
Status✅ Implemented

Implementation:

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
CORSMiddleware,
allow_origins=settings.ALLOWED_ORIGINS, # ["*"] or specific
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

Configuration:

ALLOWED_ORIGINS=["http://localhost:3000","http://localhost:5173"]

Acceptance Criteria:

  • CORS headers in responses
  • Configurable origins via environment
  • Preflight requests handled

REQ-7.3: Error Handling Middleware

IDREQ-7.3
DescriptionCustom exception handlers
PriorityMedium
Status⚠️ Partial

Required Implementation:

from fastapi import Request
from fastapi.responses import JSONResponse

class AppException(Exception):
def __init__(self, status_code: int, detail: str):
self.status_code = status_code
self.detail = detail

@app.exception_handler(AppException)
async def app_exception_handler(
request: Request,
exc: AppException
):
return JSONResponse(
status_code=exc.status_code,
content={
"error": True,
"message": exc.detail,
"path": str(request.url)
}
)

@app.exception_handler(Exception)
async def global_exception_handler(
request: Request,
exc: Exception
):
return JSONResponse(
status_code=500,
content={
"error": True,
"message": "Internal server error",
"path": str(request.url)
}
)

Acceptance Criteria:

  • Custom exception class
  • Consistent error response format
  • Global exception handler for 500 errors
  • Detailed errors in development mode

3.8 Unit 8: GraphQL APIs (Optional)

REQ-8.1: Strawberry GraphQL Integration

IDREQ-8.1
DescriptionGraphQL endpoint with Strawberry
PriorityLow
Status❌ Not Implemented

Required Implementation:

# app/graphql/types.py
import strawberry
from datetime import datetime

@strawberry.type
class ProductType:
id: int
name: str
description: str | None
price: float
quantity: int
created_at: datetime

# app/graphql/schema.py
@strawberry.type
class Query:
@strawberry.field
def products(self) -> list[ProductType]:
# Resolve products
pass

@strawberry.field
def product(self, id: int) -> ProductType | None:
# Resolve single product
pass

@strawberry.type
class Mutation:
@strawberry.mutation
def create_product(
self,
name: str,
price: float,
quantity: int
) -> ProductType:
pass

schema = strawberry.Schema(query=Query, mutation=Mutation)

# app/main.py
from strawberry.fastapi import GraphQLRouter
from app.graphql.schema import schema

graphql_router = GraphQLRouter(schema)
app.include_router(graphql_router, prefix="/graphql")

Acceptance Criteria:

  • GraphiQL accessible at /graphql
  • Query products
  • Query single product
  • Mutation for create/update/delete
  • Authentication in resolvers

3.9 Unit 9: Deployment (Final Project)

REQ-9.1: Environment Configuration

IDREQ-9.1
DescriptionConfiguration with pydantic-settings
PriorityHigh
Status✅ Implemented

Implementation:

from pydantic_settings import BaseSettings
from typing import List

class Settings(BaseSettings):
# Application
APP_NAME: str = "Product Catalog Service"
APP_VERSION: str = "1.0.0"
DEBUG: bool = False

# Database
DATABASE_URL: str

# Security
SECRET_KEY: str
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30

# CORS
ALLOWED_ORIGINS: List[str] = ["*"]

class Config:
env_file = ".env"
case_sensitive = True

settings = Settings()

Acceptance Criteria:

  • All secrets from environment
  • No hardcoded credentials
  • .env.example provided
  • Different configs for dev/prod

REQ-9.2: Production Deployment

IDREQ-9.2
DescriptionProduction-ready deployment
PriorityMedium
Status⚠️ Partial

Required Files:

# Dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- '8000:8000'
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/catalog
- SECRET_KEY=${SECRET_KEY}
depends_on:
- db

db:
image: postgres:15
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=catalog
volumes:
- postgres_data:/var/lib/postgresql/data

volumes:
postgres_data:

Acceptance Criteria:

  • Dockerfile provided
  • docker-compose.yml for local dev
  • Health check endpoint
  • Proper logging configuration

4. Non-Functional Requirements

4.1 Performance

IDRequirement
NFR-1Response time < 200ms for simple queries
NFR-2Support 100 concurrent users
NFR-3Database connection pooling enabled

4.2 Security

IDRequirement
NFR-4Passwords hashed with bcrypt
NFR-5JWT tokens expire after 30 minutes
NFR-6CORS properly configured
NFR-7SQL injection prevention via ORM
NFR-8No sensitive data in logs

4.3 Maintainability

IDRequirement
NFR-9Code follows PEP 8
NFR-10Type hints for all functions
NFR-11Docstrings for public methods
NFR-12Test coverage > 80%

5. Implementation Checklist

5.1 Current Status Summary

UnitAssignmentStatusPriority
1Foundation & Inputs✅ Complete-
2Pydantic Models✅ Complete-
3Database Setup✅ Complete-
4CRUD & DI✅ Complete-
5Authentication✅ Complete-
6Authorization⚠️ RBAC missingHigh
7Testing❌ Not doneCritical
8GraphQL❌ Not doneLow
9Deployment⚠️ PartialMedium

5.2 Required Actions

Critical (Must Have)

  1. Add Unit Tests
mkdir -p mono-src/tests
# Create test files as specified in REQ-7.1

  1. Add Role to User Model
# app/models/user.py
role = Column(String(20), default="user", nullable=False)

  1. Create Migration for Role
alembic revision --autogenerate -m "Add role to users"
alembic upgrade head

Medium Priority

  1. Add Custom Exception Handlers
  2. Create Dockerfile
  3. Create docker-compose.yml

Low Priority

  1. Implement GraphQL (Optional)
  2. Add API Rate Limiting

6. API Reference Summary

Authentication

EndpointMethodDescriptionAuth
/registerPOSTRegister new userNo
/loginPOSTLogin, get JWTNo

Products

EndpointMethodDescriptionAuth
/productsGETList productsNo
/products/{id}GETGet productNo
/productsPOSTCreate productYes
/products/{id}PUTUpdate productYes
/products/{id}DELETEDelete productYes

System

EndpointMethodDescription
/GETAPI info
/healthGETHealth check
/docsGETSwagger UI
/redocGETReDoc

7. Appendix

A. Environment Variables

# Application
APP_NAME=Product Catalog Service
APP_VERSION=1.0.0
DEBUG=True

# Database
DATABASE_URL=postgresql://user:password@localhost:5432/product_catalog

# Security
SECRET_KEY=your-super-secret-key-minimum-32-characters-long
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

# CORS
ALLOWED_ORIGINS=["http://localhost:3000","http://localhost:5173"]

B. Quick Commands

# Setup
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env

# Database
alembic upgrade head

# Run
uvicorn app.main:app --reload

# Test
pytest tests/ -v --cov=app


Document Version: 1.0.0 Created: 2025-12-24 Author: CongDX Status: Draft