feat(17-01): add credential profile service, router, device assignment

- Service with CRUD + Transit encryption for all new credential writes
- Router with 6 endpoints under /tenants/{tenant_id}/credential-profiles
- Delete returns HTTP 409 with device_count when devices reference profile
- Registered credential_profiles_router in main.py
- DeviceUpdate schema accepts optional credential_profile_id
- update_device validates profile belongs to tenant before assigning

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-21 18:54:02 -05:00
parent eb3ea0def3
commit 7354708df2
5 changed files with 498 additions and 0 deletions

View File

@@ -318,6 +318,23 @@ async def update_device(
if data.tls_mode is not None:
device.tls_mode = data.tls_mode
# Assign credential profile if provided
if data.credential_profile_id is not None:
from app.models.credential_profile import CredentialProfile
cp_result = await db.execute(
select(CredentialProfile).where(
CredentialProfile.id == data.credential_profile_id,
CredentialProfile.tenant_id == tenant_id,
)
)
if not cp_result.scalar_one_or_none():
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Credential profile not found",
)
device.credential_profile_id = data.credential_profile_id
# Re-encrypt credentials if new ones are provided
credentials_changed = False
if data.password is not None: