Skip to content

build: enable explicit API mode for api, ui and telemetry - #1023

Merged
swolfand merged 1 commit into
mainfrom
mike/explicit-api-mode
Oct 7, 2026
Merged

swolfand merged 1 commit into
mainfrom
mike/explicit-api-mode

Conversation

@swolfand

@swolfand swolfand commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Why

Finding #6 of the architecture review: there is no explicitApi(), and some types are public by accident. With explicit API mode on, a declaration can't become public just because someone left off a modifier. Visibility has to be a deliberate choice, and the ABI check from the previous PR catches any change to it.

This is PR 2 of 3, and it stacks on #1022:

  1. ABI validation with checked-in dumps
  2. This PR: explicitApi() in api, ui and telemetry
  3. Hiding the API that is public by accident

Scope

  • kotlin { explicitApi() } in :source:api, :source:ui and :source:telemetry.

  • Mechanical edits only, all driven by compiler errors:

    • public added to the ~860 declarations that were public by default.
    • Explicit return types added where explicit API mode requires them: const vals, OAuthProvider constants, ClerkLog functions (Int), ClerkButtonDefaults factories, PasswordKeyboardOptions, the two custom-navigator CompositionLocals, and a few extension functions. Each type is the one the compiler had already inferred.
    • No visibility was narrowed or widened. That is what the next PR does.
  • AutoMap workaround (source/api/build.gradle.kts):

    • AutoMap's KSP output (*.toMap() extensions) has no visibility modifier on public declarations, and explicit API mode rejects that.
    • AutoMap always writes a modifier on non-public output, so a doLast on the KSP tasks rewrites a bare top-level fun to public fun .
    • It only handles a line-leading fun (the only shape AutoMap generates today). Anything else AutoMap might emit later (public classes, properties, indented or annotated functions) fails explicit API mode instead of being silently rewritten. The build-file comment only states the AutoMap limitation, not how the regex works.
    • This should be removed once clerk/AutoMap emits public itself. It needs a small upstream change.
  • config/detekt/detekt-baseline.xml: one existing LongParameterList entry for ClerkTypographyBuilder updated. Its ID contains the constructor signature, which now includes public. This is the same finding as before, not a new suppression.

  • Rebased onto the updated build: check the public ABI against checked-in dumps #1022 (now on main at 1385b1f). User.kt conflicted with fix(user): apply the fetched client in User.reload and return the fresh user #1029: I took main's User.reload body and only added public. Earlier: Clerk.kt, Auth.kt, BiometricCredentials.kt, RestoreCredentials.kt, SignIn.kt, SignInExtensions.kt and SignUp.kt conflicted with the Clerk.auth facade stack; I kept main's bodies and re-added the modifiers the compiler asked for, including on main's new declarations (transferToSignIn/transferToSignUp, EnterpriseSsoBuilder.redirectUrl, SignInIdentifierBuilder.identifier, the sendEmailLink(redirectUri) and hidden-deprecated overloads, Clerk.setDeviceToken).

Blast Radius

  • No ABI change. apiCheck passes against the dumps from PR 1 without regenerating them, which shows that the effective visibility and signatures are identical.
  • Contributors: new public declarations in these modules must state their visibility, and the return type where the compiler can't infer it.
  • Merge conflicts: this touches ~150 files with one-word edits. Other in-flight structural PRs that touch public declarations (items 7–13) will conflict trivially. Resolve by keeping the public modifier, or re-run the compile and add the modifiers it asks for.

Testing

  • ./gradlew apiCheck: passes, with the dumps unchanged from PR 1 (re-verified after the rebase).
  • ./gradlew spotlessApply detekt :source:api:testDebugUnitTest :source:ui:testDebugUnitTest apiCheck and :source:telemetry:testAndroidHostTest: pass after the rebase.
  • ./gradlew :source:api:testDebugUnitTest :source:ui:testDebugUnitTest :source:telemetry:testAndroidHostTest: pass.
  • ./gradlew :source:{api,ui,telemetry}:spotlessApply :source:{api,ui,telemetry}:detekt: pass.
  • No UI rendering changes, so I didn't run Paparazzi on this PR. It does run on PR 3.

🤖 Generated with Claude Code

Rebuilt on main after #1022

Main moved a long way (typed Strategy, unknown-enum fallback, OAuthResult.Outcome, the telemetry library change, #1021's formatting), and rebasing the original commit conflicted in 25 files. So the branch is now one commit rebuilt from current main: the same build config (explicitApi() in api, ui and telemetry, now a plain Android library; the AutoMap ksp doLast), with public and explicit types added exactly where the compiler asked.

Summary by CodeRabbit

  • New Features
    • Expanded the public API across authentication, billing, organizations, user management, UI, and telemetry, making these components available for direct integration and customization.
  • Improvements
    • Added API compatibility checks to automated builds to help keep public interfaces consistent.

@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Repository: clerk/clerk-android/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Team
  • Run ID: d2a04e0c-6c84-459d-b14f-9303f33b634b
📥 Commits

Reviewing files that changed from the base of the PR and between 51ee75c and 47ea4f3.

📒 Files selected for processing (155)
  • .github/workflows/android-test.yml
  • build.gradle.kts
  • config/detekt/detekt-baseline.xml
  • gradle/libs.versions.toml
  • source/api/api/api.api
  • source/api/build.gradle.kts
  • source/api/src/main/kotlin/com/clerk/api/AuthFlowRegistration.kt
  • source/api/src/main/kotlin/com/clerk/api/Clerk.kt
  • source/api/src/main/kotlin/com/clerk/api/Constants.kt
  • source/api/src/main/kotlin/com/clerk/api/FrameworkIntegrationApi.kt
  • source/api/src/main/kotlin/com/clerk/api/SharedSessionSyncConfig.kt
  • source/api/src/main/kotlin/com/clerk/api/auth/Auth.kt
  • source/api/src/main/kotlin/com/clerk/api/auth/AuthEvent.kt
  • source/api/src/main/kotlin/com/clerk/api/auth/HostedAuthMode.kt
  • source/api/src/main/kotlin/com/clerk/api/auth/builders/CommonBuilders.kt
  • source/api/src/main/kotlin/com/clerk/api/auth/builders/SignInBuilders.kt
  • source/api/src/main/kotlin/com/clerk/api/auth/builders/SignUpBuilders.kt
  • source/api/src/main/kotlin/com/clerk/api/auth/types/IdTokenProvider.kt
  • source/api/src/main/kotlin/com/clerk/api/auth/types/MfaType.kt
  • source/api/src/main/kotlin/com/clerk/api/auth/types/VerificationType.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/Billing.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/BillingCreditBalance.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/BillingCreditLedger.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/BillingMoneyAmount.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/BillingParams.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/BillingPayment.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/BillingPaymentMethod.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/BillingPlan.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/BillingStatement.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/BillingSubscription.kt
  • source/api/src/main/kotlin/com/clerk/api/billing/Feature.kt
  • source/api/src/main/kotlin/com/clerk/api/biometriccredential/BiometricCredential.kt
  • source/api/src/main/kotlin/com/clerk/api/biometriccredential/BiometricCredentialAvailability.kt
  • source/api/src/main/kotlin/com/clerk/api/biometriccredential/BiometricCredentialChallenge.kt
  • source/api/src/main/kotlin/com/clerk/api/biometriccredential/BiometricCredentialKeyManager.kt
  • source/api/src/main/kotlin/com/clerk/api/biometriccredential/BiometricCredentialPolicy.kt
  • source/api/src/main/kotlin/com/clerk/api/biometriccredential/BiometricCredentialValidation.kt
  • source/api/src/main/kotlin/com/clerk/api/biometriccredential/BiometricCredentials.kt
  • source/api/src/main/kotlin/com/clerk/api/credentials/CredentialFlowException.kt
  • source/api/src/main/kotlin/com/clerk/api/emailaddress/EmailAddress.kt
  • source/api/src/main/kotlin/com/clerk/api/emailaddress/EmailAddressExtensions.kt
  • source/api/src/main/kotlin/com/clerk/api/extensions/SortExtensions.kt
  • source/api/src/main/kotlin/com/clerk/api/externalaccount/ExternalAccount.kt
  • source/api/src/main/kotlin/com/clerk/api/log/ClerkLog.kt
  • source/api/src/main/kotlin/com/clerk/api/magiclink/NativeMagicLinkManager.kt
  • source/api/src/main/kotlin/com/clerk/api/network/ClerkPaginatedResponse.kt
  • source/api/src/main/kotlin/com/clerk/api/network/api/OrganizationApi.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/account/EnterpriseAccount.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/backupcodes/BackupCodeResource.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/client/Client.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/deleted/DeletedObject.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/environment/CommerceSettings.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/environment/InstanceEnvironmentType.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/environment/UserSettings.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/error/ClerkErrorResponse.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/factor/Factor.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/image/ImageResource.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/token/TokenResource.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/totp/TOTPResource.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/userdata/PublicUserData.kt
  • source/api/src/main/kotlin/com/clerk/api/network/model/verification/Verification.kt
  • source/api/src/main/kotlin/com/clerk/api/network/serialization/ClerkResult.kt
  • source/api/src/main/kotlin/com/clerk/api/network/serialization/Extensions.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/Organization.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/OrganizationCreationDefaults.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/OrganizationDomain.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/OrganizationInvitation.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/OrganizationMembership.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/OrganizationMembershipRequest.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/OrganizationSuggestion.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/Permission.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/PublicOrganizationData.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/Role.kt
  • source/api/src/main/kotlin/com/clerk/api/organizations/UserOrganizationInvitation.kt
  • source/api/src/main/kotlin/com/clerk/api/passkeys/Passkey.kt
  • source/api/src/main/kotlin/com/clerk/api/phonenumber/PhoneNumber.kt
  • source/api/src/main/kotlin/com/clerk/api/phonenumber/PhoneNumberExtensions.kt
  • source/api/src/main/kotlin/com/clerk/api/restorecredentials/RestoreCredentials.kt
  • source/api/src/main/kotlin/com/clerk/api/session/Session.kt
  • source/api/src/main/kotlin/com/clerk/api/session/SessionAuthorization.kt
  • source/api/src/main/kotlin/com/clerk/api/session/SessionTokenFetcher.kt
  • source/api/src/main/kotlin/com/clerk/api/session/SessionVerification.kt
  • source/api/src/main/kotlin/com/clerk/api/session/SessionVerificationConvenienceExtensions.kt
  • source/api/src/main/kotlin/com/clerk/api/session/SessionVerificationExtensions.kt
  • source/api/src/main/kotlin/com/clerk/api/signin/SignIn.kt
  • source/api/src/main/kotlin/com/clerk/api/signin/SignInExtensions.kt
  • source/api/src/main/kotlin/com/clerk/api/signin/SignInPasskeyExtensions.kt
  • source/api/src/main/kotlin/com/clerk/api/signup/SignUp.kt
  • source/api/src/main/kotlin/com/clerk/api/signup/SignUpExtensions.kt
  • source/api/src/main/kotlin/com/clerk/api/sso/GoogleCredentialManager.kt
  • source/api/src/main/kotlin/com/clerk/api/sso/OAuthProvider.kt
  • source/api/src/main/kotlin/com/clerk/api/sso/SSOResult.kt
  • source/api/src/main/kotlin/com/clerk/api/ui/ClerkColors.kt
  • source/api/src/main/kotlin/com/clerk/api/ui/ClerkDesign.kt
  • source/api/src/main/kotlin/com/clerk/api/ui/ClerkTheme.kt
  • source/api/src/main/kotlin/com/clerk/api/ui/ClerkTypography.kt
  • source/api/src/main/kotlin/com/clerk/api/ui/ClerkTypographyDefaults.kt
  • source/api/src/main/kotlin/com/clerk/api/user/User.kt
  • source/api/src/main/kotlin/com/clerk/api/user/UserExtensions.kt
  • source/telemetry/api/android/telemetry.api
  • source/telemetry/build.gradle.kts
  • source/telemetry/src/androidHostTest/kotlin/com/clerk/telemetry/ClerkTelemetryEnvironmentTest.kt
  • source/telemetry/src/androidMain/kotlin/com/clerk/telemetry/AndroidTelemetryEventThrottler.kt
  • source/telemetry/src/androidMain/kotlin/com/clerk/telemetry/ClerkTelemetryEnvironment.kt
  • source/telemetry/src/androidMain/kotlin/com/clerk/telemetry/TelemetryModule.kt
  • source/telemetry/src/commonMain/kotlin/com/clerk/telemetry/TelemetryCollector.kt
  • source/telemetry/src/commonMain/kotlin/com/clerk/telemetry/TelemetryEnvironment.kt
  • source/telemetry/src/commonMain/kotlin/com/clerk/telemetry/TelemetryEventThrottler.kt
  • source/telemetry/src/commonMain/kotlin/com/clerk/telemetry/TelemetryEvents.kt
  • source/telemetry/src/commonMain/kotlin/com/clerk/telemetry/TelemetryTypes.kt
  • source/ui/api/ui.api
  • source/ui/build.gradle.kts
  • source/ui/src/main/java/com/clerk/ui/auth/AuthMode.kt
  • source/ui/src/main/java/com/clerk/ui/auth/AuthStartView.kt
  • source/ui/src/main/java/com/clerk/ui/auth/AuthView.kt
  • source/ui/src/main/java/com/clerk/ui/core/avatar/AvatarView.kt
  • source/ui/src/main/java/com/clerk/ui/core/badge/ClerkBadge.kt
  • source/ui/src/main/java/com/clerk/ui/core/button/social/ClerkSocialButton.kt
  • source/ui/src/main/java/com/clerk/ui/core/button/social/ClerkSocialRow.kt
  • source/ui/src/main/java/com/clerk/ui/core/button/standard/ClerkButton.kt
  • source/ui/src/main/java/com/clerk/ui/core/button/standard/ClerkButtonDefaults.kt
  • source/ui/src/main/java/com/clerk/ui/core/button/standard/ClerkTextButton.kt
  • source/ui/src/main/java/com/clerk/ui/core/input/ClerkCodeInputField.kt
  • source/ui/src/main/java/com/clerk/ui/core/input/ClerkPhoneNumberField.kt
  • source/ui/src/main/java/com/clerk/ui/core/input/ClerkTextField.kt
  • source/ui/src/main/java/com/clerk/ui/core/input/PasswordKeyboardOptions.kt
  • source/ui/src/main/java/com/clerk/ui/navigation/ClerkHostBackAction.kt
  • source/ui/src/main/java/com/clerk/ui/organizationlist/OrganizationListView.kt
  • source/ui/src/main/java/com/clerk/ui/organizationprofile/OrganizationProfileView.kt
  • source/ui/src/main/java/com/clerk/ui/organizationprofile/custom/OrganizationProfileCustomNavigator.kt
  • source/ui/src/main/java/com/clerk/ui/organizationprofile/custom/OrganizationProfileCustomRow.kt
  • source/ui/src/main/java/com/clerk/ui/organizationswitcher/OrganizationSwitcher.kt
  • source/ui/src/main/java/com/clerk/ui/signin/SignInFactorOneView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/SignInFactorTwoView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/alternativemethods/SignInFactorAlternativeMethodsView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/backupcode/SigninFactorTwoBackupCodeView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/clienttrust/SignInClientTrustView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/code/SignInFactorCodeView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/emaillink/SignInFactorOneEmailLinkView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/help/SignInGetHelpView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/passkey/SignInFactorOnePasskeyView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/passkey/SignInFactorTwoPasskeyView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/password/forgot/SignInFactorOneForgotPasswordView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/password/reset/SignInSetNewPasswordView.kt
  • source/ui/src/main/java/com/clerk/ui/signin/password/set/SignInFactorOnePasswordView.kt
  • source/ui/src/main/java/com/clerk/ui/signup/code/SignUpCodeView.kt
  • source/ui/src/main/java/com/clerk/ui/signup/collectfield/SignUpCollectFieldView.kt
  • source/ui/src/main/java/com/clerk/ui/signup/completeprofile/SignUpCompleteProfileView.kt
  • source/ui/src/main/java/com/clerk/ui/signup/emaillink/SignUpEmailLinkView.kt
  • source/ui/src/main/java/com/clerk/ui/userbutton/UserButton.kt
  • source/ui/src/main/java/com/clerk/ui/userprofile/UserProfileView.kt
  • source/ui/src/main/java/com/clerk/ui/userprofile/custom/UserProfileCustomNavigator.kt
  • source/ui/src/main/java/com/clerk/ui/userprofile/custom/UserProfileCustomRow.kt
  • source/ui/src/main/java/com/clerk/ui/userprofile/detail/UserProfileDetailView.kt
  • source/ui/src/main/java/com/clerk/ui/userprofile/verify/UserProfileVerifyView.kt
 ____________________________________________________________
< When you say, “I meant to do that,” I totally believe you. >
 ------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Turn on explicitApi() in the three published modules so every public
declaration states its visibility and type. This adds `public` or an
explicit type where the compiler asked and changes no ABI: apiCheck
passes against the checked-in dumps unchanged.

AutoMap's KSP output declares public functions without a modifier, so a
doLast on the ksp tasks adds `public` to bare top-level `fun`s until
AutoMap emits it itself.
@swolfand
swolfand force-pushed the mike/explicit-api-mode branch from 47ea4f3 to 66d2a61 Compare October 7, 2026 00:30
@swolfand
swolfand merged commit e083e0b into main Oct 7, 2026
11 checks passed
@swolfand
swolfand deleted the mike/explicit-api-mode branch October 7, 2026 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant