fix(l1): T8 review fixes — oauth status const + bulk-invite structured error

- oauth.py: use status.HTTP_402_PAYMENT_REQUIRED constant (was raw 402)
- accounts.py bulk-invite: catch HTTPException separately to preserve
  structured detail dict in failed-row error (was stringified repr,
  unparseable by clients)
- Add bulk-invite per-row 402 test verifying structured error preserved

T8 code review identified these as Important issues. Functional change is
the bulk-invite fix; clients can now parse seat-limit errors from bulk
responses. 13/13 seat-enforcement tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-28 12:58:35 -04:00
parent 47ff8ad2b5
commit 8010da8745
3 changed files with 37 additions and 2 deletions

View File

@@ -395,6 +395,8 @@ async def create_invites_bulk(
invite.email_sent_at = datetime.now(timezone.utc)
created.append(invite)
except HTTPException as exc:
failed.append({"email": invite_data.email, "error": exc.detail})
except Exception as e:
failed.append({"email": invite_data.email, "error": str(e)})

View File

@@ -3,7 +3,7 @@ import string
from datetime import datetime, timezone
from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
@@ -131,7 +131,7 @@ async def _sign_in_or_register(
seat_result = await check_seat_available(acct, sub, invite_record.role, db)
if not seat_result.available:
raise HTTPException(
status_code=402,
status_code=status.HTTP_402_PAYMENT_REQUIRED,
detail={
"code": "seat_limit_exceeded",
"role": seat_result.role,