Description
OtfCognito still leaks raw botocore exceptions from two public call sites in src/otf_api/auth/auth.py, despite the error boundary established in #141 (_create_cognito in user.py) and its follow-up commit (check_token in auth.py, same PR #142). login_with_password only handles ClientError for its retry-on-UserLambdaValidationException path and bare-raises everything else, with no BotoCoreError handling at all. renew_access_token has no exception handling whatsoever — both ClientError and BotoCoreError propagate straight to callers with raw provider text.
These were identified during code review of PR #142 as pre-existing gaps with the same shape #141 targeted, but out of scope for that PR.
Acceptance Criteria
Affected Areas
src/otf_api/auth/auth.py — login_with_password (roughly lines 232-265): add BotoCoreError handling and replace the bare raise for non-retryable ClientError with OtfAuthenticationError from e, keeping the existing retry logic intact
src/otf_api/auth/auth.py — renew_access_token (roughly lines 343-363): wrap the self.idp_client.initiate_auth(...) call with ClientError/BotoCoreError handling; this method currently has none of the except-branch scaffolding the other two fixed call sites had, so it needs to be built from scratch
tests/test_auth/test_otf_cognito.py — add coverage for the new exception mapping on both methods
Context
Follow the pattern established in _create_cognito (src/otf_api/auth/user.py:23-38) and check_token (src/otf_api/auth/auth.py:313-341):
except ClientError as e:
...
raise OtfAuthenticationError("OTF authentication failed") from e
except BotoCoreError as e:
# ClientError is a sibling of BotoCoreError, not a subclass, so this branch only ever
# sees non-API failures (connectivity, timeout, endpoint resolution).
LOGGER.exception("Transport error while ...")
raise OtfTransportError("OTF transport error") from e
Constraints:
login_with_password's existing retry-on-UserLambdaValidationException logic (checking e.response["Error"]["Code"] / ["Message"] and retrying once after a 5s sleep) must be preserved — only the non-retryable fallthrough path changes from a bare raise to raise OtfAuthenticationError(...) from e.
renew_access_token has no existing except branches at all — this is new exception handling, not a preserve-and-extend edit like the other two call sites.
OtfAuthenticationError and OtfTransportError are defined in src/otf_api/exceptions.py; both expose the original exception via __cause__.
Description
OtfCognitostill leaks raw botocore exceptions from two public call sites insrc/otf_api/auth/auth.py, despite the error boundary established in #141 (_create_cognitoinuser.py) and its follow-up commit (check_tokeninauth.py, same PR #142).login_with_passwordonly handlesClientErrorfor its retry-on-UserLambdaValidationExceptionpath and bare-raises everything else, with noBotoCoreErrorhandling at all.renew_access_tokenhas no exception handling whatsoever — bothClientErrorandBotoCoreErrorpropagate straight to callers with raw provider text.These were identified during code review of PR #142 as pre-existing gaps with the same shape #141 targeted, but out of scope for that PR.
Acceptance Criteria
login_with_passwordcatchesClientErrorfor the non-retryable case and raisesOtfAuthenticationErrorwith a fixed safe message (from e), preserving the existing retry-on-UserLambdaValidationExceptionbehaviorlogin_with_passwordcatchesBotoCoreErrorand raisesOtfTransportErrorwith a fixed safe message (from e)renew_access_tokenwrapsself.idp_client.initiate_auth(...), catchingClientError->OtfAuthenticationErrorandBotoCoreError->OtfTransportError, both with fixed safe messages andfrom eAffected Areas
src/otf_api/auth/auth.py—login_with_password(roughly lines 232-265): addBotoCoreErrorhandling and replace the bareraisefor non-retryableClientErrorwithOtfAuthenticationErrorfrom e, keeping the existing retry logic intactsrc/otf_api/auth/auth.py—renew_access_token(roughly lines 343-363): wrap theself.idp_client.initiate_auth(...)call withClientError/BotoCoreErrorhandling; this method currently has none of the except-branch scaffolding the other two fixed call sites had, so it needs to be built from scratchtests/test_auth/test_otf_cognito.py— add coverage for the new exception mapping on both methodsContext
Follow the pattern established in
_create_cognito(src/otf_api/auth/user.py:23-38) andcheck_token(src/otf_api/auth/auth.py:313-341):Constraints:
login_with_password's existing retry-on-UserLambdaValidationExceptionlogic (checkinge.response["Error"]["Code"]/["Message"]and retrying once after a 5s sleep) must be preserved — only the non-retryable fallthrough path changes from a bareraisetoraise OtfAuthenticationError(...) from e.renew_access_tokenhas no existing except branches at all — this is new exception handling, not a preserve-and-extend edit like the other two call sites.OtfAuthenticationErrorandOtfTransportErrorare defined insrc/otf_api/exceptions.py; both expose the original exception via__cause__.