Source: codebase audit, 2026-06-11 (audit finding F8, Tier 3)
Severity: Low
Category: Type hygiene / DRY
Problem
The same six-line type dance is repeated to access `.rowcount` on a SQLAlchemy result:
```python
result = await session.execute(stmt)
psycopg's CursorResult exposes .rowcount, but mypy needs the cast
deleted = cast(CursorResult[Any], result).rowcount or 0
```
Sites in api/survey_engine/service.py: 374, 614, 624, 635, 957, 971.
The `or 0` guards against `None`, but the cast suppresses mypy without explaining why `.rowcount` is Optional. Future refactors might drop the guard.
Suggested approach
Add a one-liner helper somewhere (e.g. `api/db_helpers.py` or near the existing imports):
```python
def rowcount(result: Result[Any]) -> int:
return cast(CursorResult[Any], result).rowcount or 0
```
Replace the six call sites with `rowcount(result)`.
Verification
`uv run mypy api/` should remain clean. No behavior change.
Priority
Nice-to-have, not worth its own PR. Fold into a touch of `service.py` for another reason.
Source: codebase audit, 2026-06-11 (audit finding F8, Tier 3)
Severity: Low
Category: Type hygiene / DRY
Problem
The same six-line type dance is repeated to access `.rowcount` on a SQLAlchemy result:
```python
result = await session.execute(stmt)
psycopg's CursorResult exposes .rowcount, but mypy needs the cast
deleted = cast(CursorResult[Any], result).rowcount or 0
```
Sites in api/survey_engine/service.py: 374, 614, 624, 635, 957, 971.
The `or 0` guards against `None`, but the cast suppresses mypy without explaining why `.rowcount` is Optional. Future refactors might drop the guard.
Suggested approach
Add a one-liner helper somewhere (e.g. `api/db_helpers.py` or near the existing imports):
```python
def rowcount(result: Result[Any]) -> int:
return cast(CursorResult[Any], result).rowcount or 0
```
Replace the six call sites with `rowcount(result)`.
Verification
`uv run mypy api/` should remain clean. No behavior change.
Priority
Nice-to-have, not worth its own PR. Fold into a touch of `service.py` for another reason.