# Release Builds

You decide which builds get Buoy.
Most apps use the real SDK in debug builds and the no-op in release builds.

## Use the no-op in release

```kotlin
dependencies {
    debugImplementation("gg.buoy:buoy-android:0.1.0")
    releaseImplementation("gg.buoy:buoy-android-noop:0.1.0")
}
```

`buoy-android-noop` has the same setup calls as `buoy-android`.
They do nothing and return right away.
So your setup code builds in both, with no `if` around it.

The no-op adds no Compose and no Buoy screens to your release APK.
It adds a little code that keeps a few calls working the normal way:

- `BuoyNetwork.interceptor` passes each call straight on.
- `BuoyClock.nowMs()` gives the real time.
- `BuoyPermissions.check` and `request` give Android's real answer.
- `BuoyNotifications.notify` posts the notification as it is.
- `Buoy.start` returns `null`.

To tell "blocked" from "never asked", the no-op keeps a small `gg.buoy.permissions` preferences file.

The real SDK adds the `INTERNET` and `POST_NOTIFICATIONS` permissions. The no-op adds none.
If your app posts its own notifications, put `POST_NOTIFICATIONS` in your own manifest.
Otherwise it works in debug and fails in release.

## Code that only debug builds have

The no-op only covers setup calls.
These are not in it:

- `BuoyAskBuoy.configure` and `AskBuoyConfig`.
- Custom tools: `BuoyTool` and `BuoyDevTools.register`.
- `BuoyAsyncImage` and `Modifier.buoyTrackRenders`. They need Compose.
- The Ask Buoy chat parts, like `AskBuoyHeader`, `MessageList` and `Composer`.

Put code that uses them in `src/debug`.
Then the release build never sees it.

## Ship Buoy to testers on purpose

You can put the real SDK in an internal build, like a QA build.
Give that build type its own line, so it gets the real SDK and not the no-op:

```kotlin
dependencies {
    debugImplementation("gg.buoy:buoy-android:0.1.0")
    "qaImplementation"("gg.buoy:buoy-android:0.1.0")
    releaseImplementation("gg.buoy:buoy-android-noop:0.1.0")
}
```

A build that is not debuggable needs a Pro plan.
Guard `Buoy.start` with your own check, so only your testers get it.

If that build turns on R8, keep your `BuildConfig` fields, or the Env tool shows nothing:

```
-keepclassmembers class com.example.app.BuildConfig { public static final <fields>; }
```

An environment badge or a user role is a label, not a lock.
Use your app's own checks for who can see or change its data.

## Features only for debug builds

Some actions check the build again, even when Buoy runs.
They need a debuggable build:

- Moving the Desktop address with `adb shell setprop debug.buoy.socketUrl`.
- Ask Buoy's simulations, like faking a server answer or driving the screen.
  In other builds, Ask Buoy can still read the app, impersonate and move between screens.
