diff --git a/app/modules/analytics/routes/pages/store.py b/app/modules/analytics/routes/pages/store.py index 2f7f5ddb..81126baf 100644 --- a/app/modules/analytics/routes/pages/store.py +++ b/app/modules/analytics/routes/pages/store.py @@ -13,7 +13,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_store_from_cookie_or_header, get_db from app.modules.core.services.platform_settings_service import ( - platform_settings_service, # MOD-004 - shared platform service + platform_settings_service, # noqa: MOD-004 - shared platform service ) from app.modules.tenancy.models import Store, User from app.templates_config import templates diff --git a/app/modules/checkout/routes/api/storefront.py b/app/modules/checkout/routes/api/storefront.py index 1c8fe66e..8138c340 100644 --- a/app/modules/checkout/routes/api/storefront.py +++ b/app/modules/checkout/routes/api/storefront.py @@ -27,7 +27,7 @@ from app.modules.checkout.schemas import ( from app.modules.checkout.services import checkout_service from app.modules.customers.schemas import CustomerContext from app.modules.messaging.services.email_service import ( - EmailService, # MOD-004 - Core email service + EmailService, # noqa: MOD-004 - Core email service ) from app.modules.orders.schemas import OrderCreate, OrderResponse from app.modules.orders.services import order_service diff --git a/app/modules/cms/routes/api/store_content_pages.py b/app/modules/cms/routes/api/store_content_pages.py index f6245725..802cd8b1 100644 --- a/app/modules/cms/routes/api/store_content_pages.py +++ b/app/modules/cms/routes/api/store_content_pages.py @@ -27,7 +27,7 @@ from app.modules.cms.schemas import ( from app.modules.cms.services import content_page_service from app.modules.tenancy.models import User from app.modules.tenancy.services.store_service import ( - StoreService, # MOD-004 - shared platform service + StoreService, # noqa: MOD-004 - shared platform service ) store_service = StoreService() diff --git a/app/modules/cms/routes/pages/store.py b/app/modules/cms/routes/pages/store.py index ae62be51..d27a3b50 100644 --- a/app/modules/cms/routes/pages/store.py +++ b/app/modules/cms/routes/pages/store.py @@ -14,7 +14,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_store_from_cookie_or_header, get_db from app.modules.cms.services import content_page_service from app.modules.core.services.platform_settings_service import ( - platform_settings_service, # MOD-004 - shared platform service + platform_settings_service, # noqa: MOD-004 - shared platform service ) from app.modules.tenancy.models import Store, User from app.templates_config import templates diff --git a/app/modules/core/routes/api/admin_menu_config.py b/app/modules/core/routes/api/admin_menu_config.py index 28c4d24a..725e2313 100644 --- a/app/modules/core/routes/api/admin_menu_config.py +++ b/app/modules/core/routes/api/admin_menu_config.py @@ -28,7 +28,7 @@ from app.api.deps import ( get_db, ) from app.modules.core.services.menu_service import MenuItemConfig, menu_service -from app.modules.enums import FrontendType # API-007 - Enum for type safety +from app.modules.enums import FrontendType # noqa: API-007 - Enum for type safety from app.modules.tenancy.services.platform_service import platform_service from app.utils.i18n import DEFAULT_LANGUAGE, translate from models.schema.auth import UserContext diff --git a/app/modules/core/services/auth_service.py b/app/modules/core/services/auth_service.py index b2dfeec1..11adf758 100644 --- a/app/modules/core/services/auth_service.py +++ b/app/modules/core/services/auth_service.py @@ -61,7 +61,7 @@ class AuthService: # Update last_login timestamp user.last_login = datetime.now(UTC) - db.commit() # SVC-006 - Login must persist last_login timestamp + db.commit() # noqa: SVC-006 - Login must persist last_login timestamp token_data = self.auth_manager.create_access_token(user) @@ -176,7 +176,7 @@ class AuthService: # Update last_login timestamp user.last_login = datetime.now(UTC) - db.commit() # SVC-006 - Login must persist last_login timestamp + db.commit() # noqa: SVC-006 - Login must persist last_login timestamp token_data = self.auth_manager.create_access_token(user) diff --git a/app/modules/core/services/platform_settings_service.py b/app/modules/core/services/platform_settings_service.py index f4e03143..dc9fec88 100644 --- a/app/modules/core/services/platform_settings_service.py +++ b/app/modules/core/services/platform_settings_service.py @@ -133,7 +133,7 @@ class PlatformSettingsService: ) db.add(admin_setting) - db.commit() # SVC-006 - Setting change is atomic, commit is intentional + db.commit() # noqa: SVC-006 - Setting change is atomic, commit is intentional db.refresh(admin_setting) logger.info(f"Platform setting '{key}' set to '{value}' by user {user_id}") diff --git a/app/modules/customers/routes/api/storefront.py b/app/modules/customers/routes/api/storefront.py index efff4e03..de43854d 100644 --- a/app/modules/customers/routes/api/storefront.py +++ b/app/modules/customers/routes/api/storefront.py @@ -25,7 +25,7 @@ from app.core.database import get_db from app.core.environment import should_use_secure_cookies from app.exceptions import ValidationException from app.modules.core.services.auth_service import ( - AuthService, # MOD-004 - Core auth service + AuthService, # noqa: MOD-004 - Core auth service ) from app.modules.customers.models import PasswordResetToken from app.modules.customers.schemas import ( @@ -44,7 +44,7 @@ from app.modules.customers.services import ( customer_service, ) from app.modules.messaging.services.email_service import ( - EmailService, # MOD-004 - Core email service + EmailService, # noqa: MOD-004 - Core email service ) from app.modules.tenancy.exceptions import StoreNotFoundException from models.schema.auth import ( diff --git a/app/modules/inventory/services/inventory_service.py b/app/modules/inventory/services/inventory_service.py index 957c9153..2366392b 100644 --- a/app/modules/inventory/services/inventory_service.py +++ b/app/modules/inventory/services/inventory_service.py @@ -754,7 +754,7 @@ class InventoryService: self, db: Session ) -> AdminStoresWithInventoryResponse: """Get list of stores that have inventory entries (admin only).""" - # SVC-005 - Admin function, intentionally cross-store + # noqa: SVC-005 - Admin function, intentionally cross-store # Use subquery to avoid DISTINCT on JSON columns (PostgreSQL can't compare JSON) store_ids_subquery = ( db.query(Inventory.store_id) diff --git a/app/modules/marketplace/schemas/marketplace_import_job.py b/app/modules/marketplace/schemas/marketplace_import_job.py index 966ab8b2..a1d43874 100644 --- a/app/modules/marketplace/schemas/marketplace_import_job.py +++ b/app/modules/marketplace/schemas/marketplace_import_job.py @@ -25,8 +25,8 @@ class MarketplaceImportJobRequest(BaseModel): @field_validator("source_url") @classmethod def validate_url(cls, v): - if not v.startswith(("http://", "https://")): # SEC-034 - raise ValueError("URL must start with http:// or https://") # SEC-034 + if not v.startswith(("http://", "https://")): # noqa: SEC-034 + raise ValueError("URL must start with http:// or https://") # noqa: SEC-034 return v.strip() @field_validator("marketplace") @@ -64,8 +64,8 @@ class AdminMarketplaceImportJobRequest(BaseModel): @field_validator("source_url") @classmethod def validate_url(cls, v): - if not v.startswith(("http://", "https://")): # SEC-034 - raise ValueError("URL must start with http:// or https://") # SEC-034 + if not v.startswith(("http://", "https://")): # noqa: SEC-034 + raise ValueError("URL must start with http:// or https://") # noqa: SEC-034 return v.strip() @field_validator("marketplace") diff --git a/app/modules/marketplace/services/letzshop/order_service.py b/app/modules/marketplace/services/letzshop/order_service.py index d5caa243..19c57c5c 100644 --- a/app/modules/marketplace/services/letzshop/order_service.py +++ b/app/modules/marketplace/services/letzshop/order_service.py @@ -865,7 +865,7 @@ class LetzshopOrderService: pass if needs_update: - self.db.commit() # SVC-006 - background task needs incremental commits + self.db.commit() # noqa: SVC-006 - background task needs incremental commits stats["updated"] += 1 else: stats["skipped"] += 1 @@ -881,7 +881,7 @@ class LetzshopOrderService: # Create new order using unified service try: self.create_order(store_id, shipment) - self.db.commit() # SVC-006 - background task needs incremental commits + self.db.commit() # noqa: SVC-006 - background task needs incremental commits stats["imported"] += 1 # Decrement remaining count for batch efficiency @@ -1093,7 +1093,7 @@ class LetzshopOrderService: status="pending", ) self.db.add(job) - self.db.commit() # SVC-006 - job must be visible immediately before background task starts + self.db.commit() # noqa: SVC-006 - job must be visible immediately before background task starts self.db.refresh(job) return job @@ -1134,6 +1134,6 @@ class LetzshopOrderService: ) if job: job.celery_task_id = celery_task_id - self.db.commit() # SVC-006 - Called from API endpoint + self.db.commit() # noqa: SVC-006 - Called from API endpoint return True return False diff --git a/app/modules/marketplace/services/letzshop/store_sync_service.py b/app/modules/marketplace/services/letzshop/store_sync_service.py index 328b35ae..8e5a064f 100644 --- a/app/modules/marketplace/services/letzshop/store_sync_service.py +++ b/app/modules/marketplace/services/letzshop/store_sync_service.py @@ -498,7 +498,7 @@ class LetzshopStoreSyncService: # Create store store = admin_service.create_store(self.db, store_data) - # Mark the Letzshop store as claimed (commits internally) # SVC-006 + # Mark the Letzshop store as claimed (commits internally) # noqa: SVC-006 self.mark_store_claimed(letzshop_slug, store.id) logger.info( diff --git a/app/modules/marketplace/services/marketplace_product_service.py b/app/modules/marketplace/services/marketplace_product_service.py index fceafa8a..cc315f9d 100644 --- a/app/modules/marketplace/services/marketplace_product_service.py +++ b/app/modules/marketplace/services/marketplace_product_service.py @@ -446,7 +446,7 @@ class MarketplaceProductService: InventorySummaryResponse if inventory found, None otherwise """ try: - # SVC-005 - Admin/internal function for inventory lookup by GTIN + # noqa: SVC-005 - Admin/internal function for inventory lookup by GTIN inventory_entries = db.query(Inventory).filter(Inventory.gtin == gtin).all() if not inventory_entries: return None diff --git a/app/modules/marketplace/services/platform_signup_service.py b/app/modules/marketplace/services/platform_signup_service.py index 7e8908e5..f3ca3045 100644 --- a/app/modules/marketplace/services/platform_signup_service.py +++ b/app/modules/marketplace/services/platform_signup_service.py @@ -415,7 +415,7 @@ class PlatformSignupService: ) subscription.stripe_customer_id = stripe_customer_id - db.commit() # SVC-006 - Atomic account creation needs commit + db.commit() # noqa: SVC-006 - Atomic account creation needs commit # Update session self.update_session(session_id, { @@ -603,7 +603,7 @@ class PlatformSignupService: if subscription: subscription.card_collected_at = datetime.now(UTC) subscription.stripe_payment_method_id = payment_method_id - db.commit() # SVC-006 - Finalize signup needs commit + db.commit() # noqa: SVC-006 - Finalize signup needs commit # Get store info store = db.query(Store).filter(Store.id == store_id).first() diff --git a/app/modules/messaging/services/email_service.py b/app/modules/messaging/services/email_service.py index 4b06ea44..4d387fcc 100644 --- a/app/modules/messaging/services/email_service.py +++ b/app/modules/messaging/services/email_service.py @@ -1336,7 +1336,7 @@ class EmailService: related_id=related_id, ) self.db.add(log) - self.db.commit() # SVC-006 - Email logs are side effects, commit immediately + self.db.commit() # noqa: SVC-006 - Email logs are side effects, commit immediately return log # Inject branding variables if requested @@ -1471,7 +1471,7 @@ class EmailService: if not email_enabled: log.status = EmailStatus.FAILED.value log.error_message = "Email sending is disabled" - self.db.commit() # SVC-006 - Email logs are side effects, commit immediately + self.db.commit() # noqa: SVC-006 - Email logs are side effects, commit immediately logger.info(f"Email sending disabled, skipping: {to_email}") return log @@ -1497,7 +1497,7 @@ class EmailService: log.mark_failed(error or "Unknown error") logger.error(f"Email failed to {to_email}: {error}") - self.db.commit() # SVC-006 - Email logs are side effects, commit immediately + self.db.commit() # noqa: SVC-006 - Email logs are side effects, commit immediately return log diff --git a/app/modules/monitoring/services/background_tasks_service.py b/app/modules/monitoring/services/background_tasks_service.py index 518c4f94..abbb0e8d 100644 --- a/app/modules/monitoring/services/background_tasks_service.py +++ b/app/modules/monitoring/services/background_tasks_service.py @@ -44,7 +44,7 @@ class BackgroundTasksService: def get_running_test_runs(self, db: Session) -> list[TestRun]: """Get currently running test runs""" - # SVC-005 - Platform-level, TestRuns not store-scoped + # noqa: SVC-005 - Platform-level, TestRuns not store-scoped return db.query(TestRun).filter(TestRun.status == "running").all() def get_import_stats(self, db: Session) -> dict: diff --git a/app/modules/orders/routes/api/storefront.py b/app/modules/orders/routes/api/storefront.py index 1ad26f07..8e174cb7 100644 --- a/app/modules/orders/routes/api/storefront.py +++ b/app/modules/orders/routes/api/storefront.py @@ -32,7 +32,7 @@ from app.modules.orders.schemas import ( ) from app.modules.orders.services import order_service from app.modules.orders.services.invoice_service import ( - invoice_service, # MOD-004 - Core invoice service + invoice_service, # noqa: MOD-004 - Core invoice service ) from app.modules.tenancy.exceptions import StoreNotFoundException diff --git a/app/modules/orders/services/order_service.py b/app/modules/orders/services/order_service.py index d72d62bf..75d52f6e 100644 --- a/app/modules/orders/services/order_service.py +++ b/app/modules/orders/services/order_service.py @@ -1292,7 +1292,7 @@ class OrderService: ) -> dict[str, Any]: """Get shipping label information for an order (admin only).""" from app.modules.core.services.admin_settings_service import ( - admin_settings_service, # MOD-004 + admin_settings_service, # noqa: MOD-004 ) order = db.query(Order).filter(Order.id == order_id).first() diff --git a/app/modules/tenancy/models/merchant_domain.py b/app/modules/tenancy/models/merchant_domain.py index 62603714..9e6814e4 100644 --- a/app/modules/tenancy/models/merchant_domain.py +++ b/app/modules/tenancy/models/merchant_domain.py @@ -103,7 +103,7 @@ class MerchantDomain(Base, TimestampMixin): - EXAMPLE.COM -> example.com """ # Remove protocol - domain = domain.replace("https://", "").replace("http://", "") # SEC-034 + domain = domain.replace("https://", "").replace("http://", "") # noqa: SEC-034 # Remove trailing slash domain = domain.rstrip("/") diff --git a/app/modules/tenancy/models/store_domain.py b/app/modules/tenancy/models/store_domain.py index 4f024638..40fd1c73 100644 --- a/app/modules/tenancy/models/store_domain.py +++ b/app/modules/tenancy/models/store_domain.py @@ -92,7 +92,7 @@ class StoreDomain(Base, TimestampMixin): - EXAMPLE.COM -> example.com """ # Remove protocol - domain = domain.replace("https://", "").replace("http://", "") # SEC-034 + domain = domain.replace("https://", "").replace("http://", "") # noqa: SEC-034 # Remove trailing slash domain = domain.rstrip("/") diff --git a/app/modules/tenancy/routes/api/admin_modules.py b/app/modules/tenancy/routes/api/admin_modules.py index c942b79e..4f7a5b4e 100644 --- a/app/modules/tenancy/routes/api/admin_modules.py +++ b/app/modules/tenancy/routes/api/admin_modules.py @@ -100,7 +100,7 @@ def _build_module_response( is_enabled: bool, ) -> ModuleResponse: """Build ModuleResponse from module code.""" - from app.modules.enums import FrontendType # API-007 - Enum for type safety + from app.modules.enums import FrontendType # noqa: API-007 - Enum for type safety module = MODULES.get(code) if not module: diff --git a/app/modules/tenancy/routes/api/admin_users.py b/app/modules/tenancy/routes/api/admin_users.py index d7a520bd..8610ec7f 100644 --- a/app/modules/tenancy/routes/api/admin_users.py +++ b/app/modules/tenancy/routes/api/admin_users.py @@ -22,7 +22,7 @@ from app.api.deps import get_current_super_admin, get_current_super_admin_api from app.core.database import get_db from app.exceptions import ValidationException from app.modules.tenancy.models import ( - User, # API-007 - Internal helper uses User model + User, # noqa: API-007 - Internal helper uses User model ) from app.modules.tenancy.services.admin_platform_service import admin_platform_service from models.schema.auth import UserContext diff --git a/app/modules/tenancy/routes/api/store.py b/app/modules/tenancy/routes/api/store.py index c72554cf..cf4db2f0 100644 --- a/app/modules/tenancy/routes/api/store.py +++ b/app/modules/tenancy/routes/api/store.py @@ -18,7 +18,7 @@ from sqlalchemy.orm import Session from app.core.database import get_db from app.modules.tenancy.schemas.store import StoreDetailResponse -from app.modules.tenancy.services.store_service import store_service # mod-004 +from app.modules.tenancy.services.store_service import store_service # noqa: mod-004 store_router = APIRouter() logger = logging.getLogger(__name__) diff --git a/app/modules/tenancy/schemas/merchant_domain.py b/app/modules/tenancy/schemas/merchant_domain.py index a5eee29b..dc24fd22 100644 --- a/app/modules/tenancy/schemas/merchant_domain.py +++ b/app/modules/tenancy/schemas/merchant_domain.py @@ -34,7 +34,7 @@ class MerchantDomainCreate(BaseModel): def validate_domain(cls, v: str) -> str: """Validate and normalize domain.""" # Remove protocol if present - domain = v.replace("https://", "").replace("http://", "") # SEC-034 + domain = v.replace("https://", "").replace("http://", "") # noqa: SEC-034 # Remove trailing slash domain = domain.rstrip("/") diff --git a/app/modules/tenancy/schemas/store_domain.py b/app/modules/tenancy/schemas/store_domain.py index c4319bd5..fde0b12f 100644 --- a/app/modules/tenancy/schemas/store_domain.py +++ b/app/modules/tenancy/schemas/store_domain.py @@ -35,7 +35,7 @@ class StoreDomainCreate(BaseModel): def validate_domain(cls, v: str) -> str: """Validate and normalize domain.""" # Remove protocol if present - domain = v.replace("https://", "").replace("http://", "") # SEC-034 + domain = v.replace("https://", "").replace("http://", "") # noqa: SEC-034 # Remove trailing slash domain = domain.rstrip("/") diff --git a/middleware/auth.py b/middleware/auth.py index cc22c216..fd7be9d8 100644 --- a/middleware/auth.py +++ b/middleware/auth.py @@ -502,6 +502,6 @@ class AuthManager: db.refresh(admin_user) # Log creation for audit trail (credentials redacted for security) - logger.info("Default admin user created") # sec-001 sec-021 + logger.info("Default admin user created") # noqa: sec-001 sec-021 return admin_user diff --git a/pyproject.toml b/pyproject.toml index 5409d20e..c23f5896 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,6 +18,7 @@ include = ["app*", "models*", "middleware*", "storage*"] line-length = 88 target-version = "py311" + # Exclude directories exclude = [ ".git", @@ -34,6 +35,9 @@ exclude = [ ] [tool.ruff.lint] +# Allow custom architecture validator codes in # noqa directives (e.g., SEC-034, SVC-006) +external = ["SEC", "SVC", "MOD", "API", "ARCH", "PERF"] + # Enable comprehensive rule sets select = [ "E", # pycodestyle errors