# Bounty Board — Android

A native Android client for the [Bounty Board](../BountyBoard) consulting work-management
platform. Built with **Kotlin + Jetpack Compose (Material 3)**, it covers the full
role-based feature set — admin, consultant, and developer — over the server's
cookie-session + CSRF API.

The visual identity mirrors the web app's "ledger / bounty-poster" aesthetic: warm
paper grounds, brown/amber ink, hard offset shadows (no blur), 2px corners, ◈ bounty
chips, and the original **Fraunces / Schibsted Grotesk / Spline Sans Mono** typefaces
(bundled, instanced from the web app's variable fonts).

## First run

The app opens on a **Login** page. The default server is
`https://bountyboard.anypreta.com/`. Expand **Server** on the login screen to point the
app at any other Bounty Board instance — the base URL is persisted and every request is
retargeted at runtime. Sign in with email/password, register a developer account, or use
"Forgot password". A forced password change is handled automatically when the server
requires it.

## Features

- **Auth** — login (with configurable base URL), self-registration, forgot password,
  forced password change. Session + CSRF are handled transparently by a persistent
  cookie jar and a double-submit interceptor.
- **Developer** — bounty board with search / project / min-bounty / sort filters and
  claim flow; My Tasks kanban (Assigned · In progress · In review · Done); per-task
  start / submit / abandon / withdraw; comments; time logging; metrics dashboard;
  leaderboard.
- **Consultant** — atomization board (grouped by project, status filters, quick
  publish); subdivide / extend / edit / publish; reviews queue with an acceptance-
  criteria checklist; approve / decline claims; assign-to-AI; developer pool management;
  metrics.
- **Admin** — users (roles, disable, force-reset, delete); projects/customers wizard
  (per-system credential fields, test connection, sync now); runtime settings; audit
  log; live service-status panel.
- **Shared** — task detail with full role-aware action bar and timeline; real-time-feel
  messaging (DMs, group/project conversations, image + file attachments, read receipts);
  notification center with deep links; profile (avatar upload, bio/contact, theme
  picker with all six themes, leaderboard opt-out, sign-out-everywhere); public profile
  cards.

## Architecture

```
data/        AppContainer (manual DI) · Repository · SessionManager · SettingsStore (DataStore)
  net/       Retrofit ApiService · PersistentCookieJar · CSRF + dynamic-host interceptors · DTOs
  model/     wire data classes
ui/
  theme/     palette (6 themes) · typography · 2px shapes · hard-offset shadow modifier
  components/ BBButton · BBCard · BountyChip · StatusBadge · BBAvatar · BBTextField · dialogs · TaskCard
  nav/       AppRoot (bootstrap/auth gate) · MainShell (role drawer + NavHost) · Routes
  auth/ developer/ consultant/ admin/ task/ messaging/ shared/ profile/   feature screens + ViewModels
```

- **Networking**: OkHttp + Retrofit (Gson). The base URL is dynamic — a host-selection
  interceptor rewrites scheme/host/port per request, so changing the server on the login
  screen takes effect immediately without rebuilding Retrofit. Coil shares the OkHttp
  stack so `/files/{id}` image loads carry the session cookie.
- **Auth**: cookie-session only. `bb_session` (httpOnly) and `bb_csrf` are persisted in a
  `PersistentCookieJar`; mutating requests echo `bb_csrf` into the `X-CSRF-Token` header.
- **State**: ViewModels expose Compose `mutableStateOf` snapshots; screens are stateless
  and driven by `LocalAppContainer`.

## Building

Requirements: **JDK 17 or 21** (AGP 8.5 does not support newer JDKs as the build JVM),
the Android SDK with **platform 34** and **build-tools 34.0.0**, and Gradle 8.9+.

The easiest path is to open the project in **Android Studio** (Koala / 2024.1+), let it
sync, and Run.

From the CLI (the Gradle wrapper is included; point `JAVA_HOME` at a JDK 17–21):

```bash
cd BountyBoard_android
JAVA_HOME=/path/to/jdk-21 ./gradlew assembleDebug   # APK → app/build/outputs/apk/debug/
JAVA_HOME=/path/to/jdk-21 ./gradlew installDebug    # install on a connected device/emulator
```

A prebuilt debug APK is committed at **`BountyBoard-debug.apk`** in the project root —
`adb install -r BountyBoard-debug.apk` to side-load it directly.

`local.properties` already points `sdk.dir` at `~/Android/Sdk`; adjust if your SDK lives
elsewhere. The app allows cleartext traffic so you can point it at a local `http://`
dev server.

### Sign-in

Local email/password **and** OIDC SSO both work. "Sign in with SSO" opens the server's
OIDC redirect flow in an in-app browser; once the IdP redirects back, the session cookies
are captured into the app's HTTP stack and you're signed in. If the server has no OIDC
configured, the app reports that instead of failing silently.

## Notes

- `minSdk 26`, `targetSdk 34`. No proprietary services; the launcher icon, splash, and
  fonts are all bundled.
- The server contract is documented in `../BountyBoard/api/openapi.yaml` and
  `../BountyBoard/specification.md`; this client implements the §6 application API.
