Contributing Guide
Prerequisites
Before you begin, ensure you have the following installed:
- Python 3.11
- pip (Python package manager)
- Git
- Azure Account (for cloud services)
- Virtual Environment (recommended)
- OS: macOS, Linux, or Windows with WSL2
- RAM: Minimum 4GB (8GB recommended)
- Disk Space: At least 2GB free space
Development Setup
1. Clone the Repository
git clone https://github.com/Fluxgentech/aquagenapi.git
cd aquagenapi
2. Create a Virtual Environment
python -m venv .venv
# Activate on macOS/Linux:
source .venv/bin/activate
# Activate on Windows:
.venv\Scripts\activate
3. Install Dependencies
pip install -r requirements.txt
If you encounter errors with PDF generation libraries, install these specific versions:
pip install xhtml2pdf==0.2.13
pip install reportlab==4.0.7
4. Run the Server
export FLASK_DEBUG=1 && export FLASK_ENV=dev && flask run --host localhost --port 5001
The application will start on http://localhost:5001.
Swagger UI
- User API: http://localhost:5001/api/user/docs
- Admin API: http://localhost:5001/api/admin/docs
- External API: http://localhost:5001/api/external/docs
Troubleshooting
Port already in use:
lsof -ti:5001 | xargs kill -9
Package installation errors:
pip install --upgrade pip
pip install -r requirements.txt
Feature Branch Workflow
-
Create a feature branch from
production:git checkout production
git pull origin production
git checkout -b feature/my-feature-name -
Make changes, commit frequently with clear messages.
-
Push and create a pull request against
production. -
Request review from at least one team member.
-
Merge after approval and passing CI.
Architecture Principles
Separation of concerns — Routes handle HTTP, services handle logic, formatters handle output, the database layer is the bridge between the codebase and Cosmos DB. Never query the database from a route or formatter directly.
DatabaseSupporter as the single data access layer — All Cosmos DB interactions go through DatabaseSupporter static methods. No code outside database/ should import CosmosClient directly.
current_user as the request context — Industry data, user data, and permissions are loaded once per request into current_user. Services access this via flask_jwt_extended.current_user rather than making additional DB calls for the same data.
No secrets in code — All credentials and configuration values come from Key Vault via smi.get(). Never hardcode secrets, even in development.
PR Checklist
- New routes have
@jwt_required()(or explicitly excluded inPUBLIC_ROUTES) - New routes declare
Authorizationin the request parser - Error cases return appropriate status codes (
1403,1401, etc.) - New POST/PUT endpoints validate request body with JSON Schema
- Swagger responses declared with
@namespace.response() - New database methods added to
DatabaseSupporter(not inline in service) - No hardcoded industry IDs, user IDs, or secrets
- No
print()statements left in production code (uselogging) - Code follows existing naming conventions
Commit Conventions
feat: add water neutrality endpoint
fix: correct monthly report date range calculation
docs: update authentication guide
refactor: extract common alert logic to base class
chore: update requirements.txt
Branch Conventions
feature/water-neutrality-endpoint
fix/monthly-report-date-bug
docs/update-auth-guide
refactor/alert-base-class
Security Rules
- No hardcoded secrets — all secrets via
smi.get(SecretName.XYZ)from Key Vault - No sensitive data in logs — no passwords, tokens, or PII in log messages
- Input validation — validate all user-supplied input before processing
- Soft deletes — use
deleted: trueflag rather than hard-deleting industry or user data