feat(validators): add noqa suppression support to security and performance validators
All checks were successful
CI / dependency-scanning (push) Successful in 27s
CI / docs (push) Successful in 35s
CI / ruff (push) Successful in 8s
CI / pytest (push) Successful in 34m22s
CI / validate (push) Successful in 19s
CI / deploy (push) Successful in 2m25s

- Add centralized _is_noqa_suppressed() to BaseValidator with normalization
  (accepts both SEC001 and SEC-001 formats for ruff compatibility)
- Wire noqa support into all 21 security and 18 performance check functions
- Add ruff external config for SEC/PERF/MOD/EXC codes in pyproject.toml
- Convert all 280 Python noqa comments to dashless format (ruff-compatible)
- Add site/ to IGNORE_PATTERNS (excludes mkdocs build output)
- Suppress 152 false positive findings (test passwords, seed data, validator
  self-references, Apple Wallet SHA1, etc.)
- Security: 79 errors → 0, 60 warnings → 0
- Performance: 80 warnings → 77 (3 test script suppressions)
- Add proposal doc with noqa inventory and remaining findings recommendations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-14 22:56:56 +01:00
parent f84c5d903e
commit 1b8a40f1ff
75 changed files with 404 additions and 310 deletions

View File

@@ -103,7 +103,7 @@ DEMO_COMPANIES = [
"name": "WizaCorp Ltd.",
"description": "Leading technology and electronics distributor",
"owner_email": "john.owner@wizacorp.com",
"owner_password": "password123", # noqa: SEC-001
"owner_password": "password123", # noqa: SEC001
"owner_first_name": "John",
"owner_last_name": "Smith",
"contact_email": "info@wizacorp.com",
@@ -116,7 +116,7 @@ DEMO_COMPANIES = [
"name": "Fashion Group S.A.",
"description": "International fashion and lifestyle retailer",
"owner_email": "jane.owner@fashiongroup.com",
"owner_password": "password123", # noqa: SEC-001
"owner_password": "password123", # noqa: SEC001
"owner_first_name": "Jane",
"owner_last_name": "Merchant",
"contact_email": "contact@fashiongroup.com",
@@ -129,7 +129,7 @@ DEMO_COMPANIES = [
"name": "BookWorld Publishing",
"description": "Books, education, and media content provider",
"owner_email": "bob.owner@bookworld.com",
"owner_password": "password123", # noqa: SEC-001
"owner_password": "password123", # noqa: SEC001
"owner_first_name": "Bob",
"owner_last_name": "Seller",
"contact_email": "support@bookworld.com",
@@ -213,7 +213,7 @@ DEMO_TEAM_MEMBERS = [
{
"merchant_index": 0,
"email": "alice.manager@wizacorp.com",
"password": "password123", # noqa: SEC-001
"password": "password123", # noqa: SEC001
"first_name": "Alice",
"last_name": "Manager",
"store_codes": ["ORION", "WIZAGADGETS"], # manages two stores
@@ -222,7 +222,7 @@ DEMO_TEAM_MEMBERS = [
{
"merchant_index": 0,
"email": "charlie.staff@wizacorp.com",
"password": "password123", # noqa: SEC-001
"password": "password123", # noqa: SEC001
"first_name": "Charlie",
"last_name": "Staff",
"store_codes": ["WIZAHOME"],
@@ -232,7 +232,7 @@ DEMO_TEAM_MEMBERS = [
{
"merchant_index": 1,
"email": "diana.stylist@fashiongroup.com",
"password": "password123", # noqa: SEC-001
"password": "password123", # noqa: SEC001
"first_name": "Diana",
"last_name": "Stylist",
"store_codes": ["FASHIONHUB", "FASHIONOUTLET"],
@@ -241,7 +241,7 @@ DEMO_TEAM_MEMBERS = [
{
"merchant_index": 1,
"email": "eric.sales@fashiongroup.com",
"password": "password123", # noqa: SEC-001
"password": "password123", # noqa: SEC001
"first_name": "Eric",
"last_name": "Sales",
"store_codes": ["FASHIONOUTLET"],
@@ -251,7 +251,7 @@ DEMO_TEAM_MEMBERS = [
{
"merchant_index": 2,
"email": "fiona.editor@bookworld.com",
"password": "password123", # noqa: SEC-001
"password": "password123", # noqa: SEC001
"first_name": "Fiona",
"last_name": "Editor",
"store_codes": ["BOOKSTORE", "BOOKDIGITAL"],
@@ -615,7 +615,7 @@ def create_demo_merchants(db: Session, auth_manager: AuthManager) -> list[Mercha
owner_user = User(
username=merchant_data["owner_email"].split("@")[0],
email=merchant_data["owner_email"],
hashed_password=auth_manager.hash_password( # noqa: SEC-001
hashed_password=auth_manager.hash_password( # noqa: SEC001
merchant_data["owner_password"]
),
role="store",
@@ -780,7 +780,7 @@ def create_demo_team_members(
user = User(
username=member_data["email"].split("@")[0],
email=member_data["email"],
hashed_password=auth_manager.hash_password(member_data["password"]), # noqa: SEC-001
hashed_password=auth_manager.hash_password(member_data["password"]), # noqa: SEC001
role="store",
first_name=member_data["first_name"],
last_name=member_data["last_name"],
@@ -838,7 +838,7 @@ def create_demo_customers(
customers = []
# Use a simple demo password for all customers
demo_password = "customer123" # noqa: SEC-001
demo_password = "customer123" # noqa: SEC001
for i in range(1, count + 1):
email = f"customer{i}@{store.subdomain}.example.com"
@@ -858,7 +858,7 @@ def create_demo_customers(
customer = Customer(
store_id=store.id,
email=email,
hashed_password=auth_manager.hash_password(demo_password), # noqa: SEC-001
hashed_password=auth_manager.hash_password(demo_password), # noqa: SEC001
first_name=f"Customer{i}",
last_name="Test",
phone=f"+352123456{i:03d}",
@@ -1178,14 +1178,14 @@ def print_summary(db: Session):
merchant = merchants[i - 1] if i <= len(merchants) else None
print(f" Merchant {i}: {merchant_data['name']}")
print(f" Email: {merchant_data['owner_email']}")
print(f" Password: {merchant_data['owner_password']}") # noqa: SEC-021
print(f" Password: {merchant_data['owner_password']}") # noqa: SEC021
if merchant and merchant.stores:
for store in merchant.stores:
print(
f" Store: http://localhost:8000/store/{store.store_code}/login"
)
print(
f" or http://{store.subdomain}.localhost:8000/store/login"
f" or http://{store.subdomain}.localhost:8000/store/login" # noqa: SEC034
)
print()
@@ -1196,7 +1196,7 @@ def print_summary(db: Session):
store_codes = ", ".join(member_data["store_codes"])
print(f" {member_data['first_name']} {member_data['last_name']} ({merchant_name})")
print(f" Email: {member_data['email']}")
print(f" Password: {member_data['password']}") # noqa: SEC-021
print(f" Password: {member_data['password']}") # noqa: SEC021
print(f" Stores: {store_codes}")
print()
@@ -1204,7 +1204,7 @@ def print_summary(db: Session):
print("" * 70)
print(" All customers:")
print(" Email: customer1@{subdomain}.example.com")
print(" Password: customer123") # noqa: SEC-021
print(" Password: customer123") # noqa: SEC021
print(" (Replace {subdomain} with store subdomain, e.g., orion)")
print()
@@ -1215,7 +1215,7 @@ def print_summary(db: Session):
print(
f" Path-based: http://localhost:8000/stores/{store.store_code}/shop/"
)
print(f" Subdomain: http://{store.subdomain}.localhost:8000/")
print(f" Subdomain: http://{store.subdomain}.localhost:8000/") # noqa: SEC034
print()
print("⚠️ ALL DEMO CREDENTIALS ARE INSECURE - For development only!")
@@ -1224,11 +1224,11 @@ def print_summary(db: Session):
print(" 1. Start development: make dev")
print(" 2. Login as store:")
print(" • Path-based: http://localhost:8000/store/ORION/login")
print(" • Subdomain: http://orion.localhost:8000/store/login")
print(" • Subdomain: http://orion.localhost:8000/store/login") # noqa: SEC034
print(" 3. Visit store shop: http://localhost:8000/stores/ORION/shop/")
print(" 4. Admin panel: http://localhost:8000/admin/login")
print(f" Username: {settings.admin_username}")
print(f" Password: {settings.admin_password}") # noqa: SEC-021
print(f" Password: {settings.admin_password}") # noqa: SEC021
# =============================================================================