Skip to content

fix(auth): address code-review findings on VerifyOTPResponse - #1205

Merged
grdsdev merged 1 commit into
mainfrom
fix/sdk-1022-verifyotp-response-review-fixes
Aug 13, 2026
Merged

grdsdev merged 1 commit into
mainfrom
fix/sdk-1022-verifyotp-response-review-fixes

Conversation

@grdsdev

@grdsdev grdsdev commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #1088 (already merged) addressing findings from a post-merge code review of that PR's VerifyOTPResponse change.

Changes

  • Sources/Auth/Types.swift: VerifyOTPResponse.init(from:) now throws a descriptive dataCorruptedError on an unrecognized shape instead of letting EmailChangeConfirmation's own decode failure leak through unwrapped — matches AuthResponse's existing behavior for the same situation.
  • Fixed the emailChangeConfirmationPending doc comment, which assumed the new email always confirms second. GoTrue doesn't enforce an order between the two confirmations — whichever of the two hasn't confirmed yet is the one still pending.
  • Tests/AuthTests/AuthResponseTests.swift: added a test locking in that a bare user (no session) is correctly not a valid VerifyOTPResponse shape, since /verify never returns one (unlike signUp, which can).
  • Dropped a stray docs/superpowers/ reference in the isolated integration-test project's config.toml comment — that path isn't documentation for this.
  • Restored a sentence in AGENTS.md explaining why the breaking-change marker matters (release-please and the API stability check key off it) — this was dropped when this branch's migration-guide convention replaced main's equivalent section during a rebase, and got missed before merge.

Test plan

  • swift test --filter "AuthTests|SupabaseTests" — 257 tests pass
  • Format check, spell-check clean
  • Verified against the supabase/auth Go source (internal/api/verify.go) that verifyPost has exactly two response paths — the {msg,code} map or a full session via issueRefreshToken — confirming VerifyOTPResponse correctly has no bare-user case

- VerifyOTPResponse.init(from:) now throws a descriptive
  dataCorruptedError on an unrecognized shape instead of letting
  EmailChangeConfirmation's own decode failure leak through
  unwrapped, matching AuthResponse's existing behavior.
- Fix the emailChangeConfirmationPending doc comment, which assumed
  the new email always confirms second; GoTrue doesn't enforce an
  order between the two confirmations.
- Add a test locking in that a bare user (no session) is correctly
  not a valid VerifyOTPResponse shape, since /verify never returns
  one (unlike signUp).
- Drop a stray "docs/superpowers/" reference in the isolated
  integration-test project's config.toml comment.
- Restore the explanation of why the breaking-change marker matters
  (release-please/API-stability check) that got dropped when this
  branch's migration-guide convention replaced main's during rebase.
@grdsdev
grdsdev requested a review from a team as a code owner August 13, 2026 10:07
@github-actions github-actions Bot added the auth label Aug 13, 2026
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: df91ea83-0100-468f-88d3-7a1fb06f3710

📥 Commits

Reviewing files that changed from the base of the PR and between dd5e825 and a3acaf1.

📒 Files selected for processing (4)
  • AGENTS.md
  • Sources/Auth/Types.swift
  • Tests/AuthTests/AuthResponseTests.swift
  • Tests/IntegrationTests/supabase-secure-email-change/supabase/config.toml

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved one-time password verification response handling for session and email-change confirmation flows.
    • Invalid or incomplete verification responses are now rejected instead of being accepted as valid user data.
    • Clarified email-change confirmation requirements for both current and new email addresses.
  • Documentation

    • Updated contribution guidance for major-version changes and required migration notes.
    • Refined configuration documentation references.

Walkthrough

VerifyOTPResponse now decodes only Session or EmailChangeConfirmation responses and throws a data-corruption error for other payloads. A test verifies that a bare user payload is rejected. Documentation now covers both breaking-change markers, major-version handling, reviewer flags, and migration-guide requirements. The integration configuration now references AGENTS.md.

Possibly related PRs

Mergeability Score: ⚪ Minimal · up to a3aca

This PR makes localized corrections to OTP response decoding, documentation, tests, and repository guidance; no actionable merge-blocking risk remains after normal checks and review.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 31689724997

Coverage decreased (-0.9%) to 83.769%

Details

  • Coverage decreased (-0.9%) from the base build.
  • Patch coverage: 7 uncovered changes across 1 file (0 of 7 lines covered, 0.0%).
  • 85 coverage regressions across 2 files.

Uncovered Changes

File Changed Covered %
Sources/Auth/Types.swift 7 0 0.0%

Coverage Regressions

85 previously-covered lines in 2 files lost coverage.

File Lines Losing Coverage Coverage
Sources/Auth/AuthClient.swift 70 81.88%
Sources/Auth/Types.swift 15 78.96%

Coverage Stats

Coverage Status
Relevant Lines: 10480
Covered Lines: 8779
Line Coverage: 83.77%
Coverage Strength: 39.8 hits per line

💛 - Coveralls

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Capability matrix drift detected

The following capabilities are marked implemented in swift but have no registered symbols to verify:

  • auth.passkey.register_passkey (no symbols list — cannot confirm implementation exists)
  • auth.passkey.sign_in_with_passkey (no symbols list — cannot confirm implementation exists)
  • client.authentication_integration.third_party_auth (no symbols list — cannot confirm implementation exists)
  • client.authentication_integration.cross_client_token_sync (no symbols list — cannot confirm implementation exists)
  • client.authentication_integration.oauth_flow_type (no symbols list — cannot confirm implementation exists)
  • client.authentication_integration.session_url_detection (no symbols list — cannot confirm implementation exists)
  • client.session_management.custom_storage (no symbols list — cannot confirm implementation exists)
  • client.session_management.persist_session (no symbols list — cannot confirm implementation exists)
  • client.request_configuration.global_headers (no symbols list — cannot confirm implementation exists)
  • client.observability.trace_propagation (no symbols list — cannot confirm implementation exists)
  • database.query.select (no symbols list — cannot confirm implementation exists)
  • database.query.schema_selection (no symbols list — cannot confirm implementation exists)
  • database.query.rpc (no symbols list — cannot confirm implementation exists)
  • database.mutate.insert (no symbols list — cannot confirm implementation exists)
  • database.mutate.update (no symbols list — cannot confirm implementation exists)
  • database.mutate.upsert (no symbols list — cannot confirm implementation exists)
  • database.mutate.delete (no symbols list — cannot confirm implementation exists)
  • database.mutate.select_after_mutation (no symbols list — cannot confirm implementation exists)
  • database.using_filters.eq (no symbols list — cannot confirm implementation exists)
  • database.using_filters.neq (no symbols list — cannot confirm implementation exists)
  • database.using_filters.gt (no symbols list — cannot confirm implementation exists)
  • database.using_filters.gte (no symbols list — cannot confirm implementation exists)
  • database.using_filters.lt (no symbols list — cannot confirm implementation exists)
  • database.using_filters.lte (no symbols list — cannot confirm implementation exists)
  • database.using_filters.like (no symbols list — cannot confirm implementation exists)
  • database.using_filters.ilike (no symbols list — cannot confirm implementation exists)
  • database.using_filters.is (no symbols list — cannot confirm implementation exists)
  • database.using_filters.in (no symbols list — cannot confirm implementation exists)
  • database.using_filters.contains (no symbols list — cannot confirm implementation exists)
  • database.using_filters.contained_by (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_gt (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_gte (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_lt (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_lte (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_adjacent (no symbols list — cannot confirm implementation exists)
  • database.using_filters.overlaps (no symbols list — cannot confirm implementation exists)
  • database.using_filters.text_search (no symbols list — cannot confirm implementation exists)
  • database.using_filters.match (no symbols list — cannot confirm implementation exists)
  • database.using_filters.not (no symbols list — cannot confirm implementation exists)
  • database.using_filters.or (no symbols list — cannot confirm implementation exists)
  • database.using_filters.raw (no symbols list — cannot confirm implementation exists)
  • database.using_filters.regex (no symbols list — cannot confirm implementation exists)
  • database.using_filters.regex_icase (no symbols list — cannot confirm implementation exists)
  • database.using_filters.is_distinct (no symbols list — cannot confirm implementation exists)
  • database.using_filters.like_all (no symbols list — cannot confirm implementation exists)
  • database.using_filters.like_any (no symbols list — cannot confirm implementation exists)
  • database.using_filters.ilike_all (no symbols list — cannot confirm implementation exists)
  • database.using_filters.ilike_any (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.order (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.limit (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.range (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.single_row (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.strip_nulls (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.format_csv (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.format_geojson (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.max_affected_rows (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.request_cancellation (no symbols list — cannot confirm implementation exists)
  • database.configuration.auto_retry (no symbols list — cannot confirm implementation exists)
  • functions.invocation.invoke (no symbols list — cannot confirm implementation exists)
  • functions.invocation.set_auth_token (no symbols list — cannot confirm implementation exists)
  • functions.invocation.method_override (no symbols list — cannot confirm implementation exists)
  • functions.invocation.streaming_response (no symbols list — cannot confirm implementation exists)
  • functions.invocation.request_cancellation (no symbols list — cannot confirm implementation exists)
  • realtime.client.connect (no symbols list — cannot confirm implementation exists)
  • realtime.client.disconnect (no symbols list — cannot confirm implementation exists)
  • realtime.client.get_channels (no symbols list — cannot confirm implementation exists)
  • realtime.client.remove_channel (no symbols list — cannot confirm implementation exists)
  • realtime.client.remove_all_channels (no symbols list — cannot confirm implementation exists)
  • realtime.client.connection_state (no symbols list — cannot confirm implementation exists)
  • realtime.client.listen_heartbeats (no symbols list — cannot confirm implementation exists)
  • realtime.client.set_auth_token (no symbols list — cannot confirm implementation exists)
  • realtime.client.channel (no symbols list — cannot confirm implementation exists)
  • realtime.channel.subscribe (no symbols list — cannot confirm implementation exists)
  • realtime.channel.unsubscribe (no symbols list — cannot confirm implementation exists)
  • realtime.channel.broadcast (no symbols list — cannot confirm implementation exists)
  • realtime.channel.broadcast_http (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.postgres_changes (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.subscribe_presence (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.private_channel (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.broadcast_self (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.broadcast_ack (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.broadcast_replay (no symbols list — cannot confirm implementation exists)
  • realtime.presence.track (no symbols list — cannot confirm implementation exists)
  • realtime.presence.untrack (no symbols list — cannot confirm implementation exists)
  • realtime.presence.presence_key (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.custom_websocket_transport (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.reconnect_backoff (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.heartbeat_interval (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.access_token_callback (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.deferred_disconnect (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.custom_logger (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.binary_protocol (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.get_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.list_file_buckets (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.update_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.delete_file_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.empty_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.access_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.upload (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.download (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.move (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.copy (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.remove (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.create_signed_url (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.create_signed_urls (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.create_signed_upload_url (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.upload_with_signed_url (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.update_file (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.file_exists (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.file_info (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.copy_cross_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.move_cross_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.upload_with_metadata (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.url_cache_nonce (no symbols list — cannot confirm implementation exists)

These may have been renamed, removed, or never registered. Please update the capability matrix.
See: https://github.com/supabase/sdk/blob/main/docs/capability-matrix.md

@grdsdev
grdsdev merged commit f285277 into main Aug 13, 2026
54 of 57 checks passed
@grdsdev
grdsdev deleted the fix/sdk-1022-verifyotp-response-review-fixes branch August 13, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants