# TASK-011: Sign in and list accessible repositories Status: complete Owner: Codex Reviewer: Claude ## Outcome A user can sign in to the configured company Gitea through the system browser and see every repository visible to that account in a localized read-only list. ## Scope - Included: system-browser OAuth, verified HTTPS App Link callback, PKCE code exchange, authenticated identity check, Keystore-backed token storage, logout, paged `/user/repos` loading, and login/loading/content/empty/error UI states. - Excluded: branches, file browsing, commits, diffs, pull requests, issues, offline repository caching, and every write operation. ## Writable paths - `app/build.gradle.kts` - `gradle/libs.versions.toml` - `app/src/main/AndroidManifest.xml` - `app/src/main/java/com/ubisam/ubgitea/MainActivity.kt` - `app/src/main/java/com/ubisam/ubgitea/core/auth/android/` - `app/src/main/java/com/ubisam/ubgitea/core/network/` - `app/src/main/java/com/ubisam/ubgitea/data/auth/` - `app/src/main/java/com/ubisam/ubgitea/data/repositories/` - `app/src/main/java/com/ubisam/ubgitea/feature/repositories/` - Matching test paths - `app/src/main/res/values/strings_repositories.xml` - `app/src/main/res/xml/data_extraction_rules.xml` - `tasks/002b-oauth-android-integration.md` - `tasks/004-gitea-api-client.md` - `tasks/005-repository-branch-ui.md` - `tasks/011-login-repository-list.md` - `docs/development-log.md` ## Acceptance criteria - [x] Login opens an external browsable HTTPS intent and no WebView dependency or component exists. - [x] The manifest accepts only the configured verified HTTPS callback host and path. - [x] Callback processing uses TASK-002A validation and clears pending verifier/state on every terminal result. - [x] Code exchange sends client ID, redirect URI, original verifier, and no client secret. - [x] Access/refresh tokens are encrypted with an Android Keystore key, excluded from backup, redacted from string output, and removed on logout. - [x] The authenticated `/api/v1/user` call confirms the account before repository loading. - [x] `/api/v1/user/repos` follows pagination to completion, deduplicates by stable repository ID, and has a bounded page count. - [x] DTOs remain in data packages; UI models contain no token, HTTP, or Android persistence types. - [x] UI has localized signed-out, browser-waiting, loading, content, empty, authentication-expired, permission-denied, offline, and server-error states. - [x] Repository rows identify owner/name, visibility, optional description, and default branch; logout is explicit. - [x] Unit tests cover exchange form, callback terminal clearing, token codec, repository mapping/pagination/deduplication, and error mapping. - [x] Build, unit tests, lint, focused tests, secret scan, and independent review pass. ## External evidence - OAuth application is configured as a public client with the registered redirect URI. - `https://gitea.ubisampaju.synology.me/.well-known/assetlinks.json` publicly serves `com.ubisam.ubgitea` with both development certificate fingerprints. ## Required checks ```text ./gradlew assembleDebug ./gradlew testDebugUnitTest ./gradlew lintDebug ``` ## Evidence - `./gradlew testDebugUnitTest assembleDebug lintDebug` — passed; 57 tests across 16 suites, 0 failures/errors; debug APK and lint report generated. - Focused authentication, callback, token-codec, HTTP transport, repository pagination/mapping, error mapping, and immutable UI-state tests passed. - `git diff --check` and the sensitive-pattern scan passed; no WebView or production client secret exists. - Independent review confirmed the browser/App Link, PKCE, Keystore/backup, identity-before-repositories, and bounded pagination design. Its P1 browser-cancellation, response-read, and token-retained error-recovery findings were fixed, together with signed-in error/logout UX, nullable DTO validation, immutable snapshots, and focused regression tests. Final re-review found no remaining P0/P1. - Hosted `assetlinks.json` was visually confirmed by the product owner with both development signing fingerprints. - Product-owner device E2E on 2026-08-25 passed: account login returned through the verified App Link and the app displayed the accessible internal repository list from the production Gitea instance.