refactor(P11+P12): codebase hygiene — CLAUDE.md rewrite, type safety, dead code removal

- Rewrite CLAUDE.md to match current 8-service architecture (was 11, 5 deleted)
- Remove all as-any casts in OrderDetail.tsx (9 casts → 0)
- Add cad_parsed_objects/cad_part_materials to OrderItem interface
- Rename require_admin → require_global_admin across 6 router files (22 calls)
- Remove EXPORT_GLB_PRODUCTION enum + generate_gltf_production_task (dead code)
- Remove worker-thumbnail from ALLOWED_SERVICES, replace Flamenco link
- Delete obsolete PLAN.md (1455 lines) and PLAN_REFACTOR.md (1174 lines)
- Fix digit-only USD prim names with p_ prefix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 07:22:04 +01:00
parent 3dcfa7c0bd
commit 577dd1ca7e
21 changed files with 303 additions and 3229 deletions
+9 -9
View File
@@ -4,7 +4,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import update
from app.database import get_db
from app.utils.auth import require_admin
from app.utils.auth import require_global_admin
from app.domains.tenants.schemas import (
TenantCreate, TenantUpdate, TenantOut,
TenantAIConfigUpdate, TenantAIConfigOut,
@@ -18,7 +18,7 @@ router = APIRouter(prefix="/tenants", tags=["tenants"])
@router.get("/", response_model=list[TenantOut])
async def list_tenants(
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
_: object = Depends(require_global_admin),
):
rows = await service.list_tenants(db)
result = []
@@ -34,7 +34,7 @@ async def list_tenants(
async def get_tenant(
tenant_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
_: object = Depends(require_global_admin),
):
tenant = await service.get_tenant(db, tenant_id)
if not tenant:
@@ -46,7 +46,7 @@ async def get_tenant(
async def create_tenant(
body: TenantCreate,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
_: object = Depends(require_global_admin),
):
tenant = await service.create_tenant(db, name=body.name, slug=body.slug, is_active=body.is_active)
return TenantOut.model_validate(tenant)
@@ -57,7 +57,7 @@ async def update_tenant(
tenant_id: uuid.UUID,
body: TenantUpdate,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
_: object = Depends(require_global_admin),
):
tenant = await service.update_tenant(
db, tenant_id,
@@ -74,7 +74,7 @@ async def update_tenant(
async def delete_tenant(
tenant_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
_: object = Depends(require_global_admin),
):
ok = await service.delete_tenant(db, tenant_id)
if not ok:
@@ -107,7 +107,7 @@ def _tenant_ai_config_out(tenant: Tenant) -> TenantAIConfigOut:
async def get_tenant_ai_config(
tenant_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
_: object = Depends(require_global_admin),
):
"""Return AI config for a tenant (without the raw api_key)."""
tenant = await service.get_tenant(db, tenant_id)
@@ -121,7 +121,7 @@ async def update_tenant_ai_config(
tenant_id: uuid.UUID,
body: TenantAIConfigUpdate,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
_: object = Depends(require_global_admin),
):
"""Merge AI configuration into tenant_config JSONB.
If ai_api_key is None in the request body, the existing key is preserved.
@@ -160,7 +160,7 @@ async def update_tenant_ai_config(
async def test_tenant_ai_config(
tenant_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
_: object = Depends(require_global_admin),
):
"""Send a minimal ping to Azure OpenAI using the tenant's stored credentials.
Returns {"ok": true} or {"ok": false, "error": "human readable message"}.