Android: portless fixture URLs after D-124
D-124 serves Kvitt at https://<host> on 443. The README, the AppBuildInfo and AboutRepositoryImpl comments, the S-21/S-22 fake scenarios and the :data test fixtures drop the :8443 port. S-21's invite-created goldens and every S-22 golden re-recorded (link and server row now portless). The release-URL normaliser test checks a portless URL and keeps one explicit-port case (a typed port survives), on example.org instead of the owner's old host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
@@ -7,7 +7,7 @@ compile, unit tests (including every vector of `contracts/test-vectors/`), lint
|
||||
|
||||
**Public host (D-121).** The release server's host name is the build property `kvitt.publicHost`, never a literal in
|
||||
the code: `:app` exposes it as `BuildConfig.PUBLIC_HOST`, as the manifest placeholder `publicHost` (the host of the
|
||||
`https://<host>:8443/i/<CODE>` invite links, AC-2.6) and as `RELEASE_SERVER_URL` = `https://<host>:8443`, which S-1
|
||||
`https://<host>/i/<CODE>` invite links, AC-2.6) and as `RELEASE_SERVER_URL` = `https://<host>`, which S-1
|
||||
prefills (AC-2.7). Gradle takes `-Pkvitt.publicHost=…` first (`infra/publish-apk.sh` passes it), else the key
|
||||
`kvitt.publicHost` in `android/local.properties`, where the owner sets it (git-ignored, never committed), else the
|
||||
placeholder `kvitt.example.invalid`, so a release built without it cannot talk to a real host. Debug builds pair with
|
||||
|
||||
@@ -71,7 +71,7 @@ object FakeScenarios {
|
||||
clockSkew = false,
|
||||
syncRunning = false,
|
||||
update = UpdateState.None,
|
||||
about = AboutState("dev", 1, "https://kvitt.example.org:8443", null, null),
|
||||
about = AboutState("dev", 1, "https://kvitt.example.org", null, null),
|
||||
online = true,
|
||||
today = "2026-10-17",
|
||||
now = "2026-10-17T06:00:00.000Z",
|
||||
|
||||
@@ -116,7 +116,7 @@ object SettingsScenarios {
|
||||
devices = devices,
|
||||
invites = listOf(pendingDeviceInvite),
|
||||
lastSuccessAt = "2026-10-17T11:59:00.000Z",
|
||||
about = AboutState("1.1", 11, "https://kvitt.example.org:8443", "1.1.0", 3),
|
||||
about = AboutState("1.1", 11, "https://kvitt.example.org", "1.1.0", 3),
|
||||
today = "2026-10-17",
|
||||
now = "2026-10-17T12:02:00.000Z",
|
||||
defaultAccountId = huset.id,
|
||||
|
||||
@@ -88,7 +88,7 @@ import javax.inject.Qualifier
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* What `:app` provides: its version (§10.6), build type (AC-2.8, AC-16.5) and release server `https://<host>:8443`
|
||||
* What `:app` provides: its version (§10.6), build type (AC-2.8, AC-16.5) and release server `https://<host>`
|
||||
* (`RELEASE_SERVER_URL`, from the Gradle property `kvitt.publicHost`, D-121), which S-22 shows before pairing (D-122).
|
||||
*/
|
||||
data class AppBuildInfo(val versionCode: Int, val versionName: String, val debug: Boolean, val releaseServerUrl: String)
|
||||
|
||||
@@ -388,7 +388,7 @@ class AboutRepositoryImpl(
|
||||
private val gate: OnlineGate,
|
||||
private val versionName: String,
|
||||
private val versionCode: Int,
|
||||
/** Shown while no server is paired: `AppBuildInfo.releaseServerUrl`, `https://<kvitt.publicHost>:8443` (D-122). */
|
||||
/** Shown while no server is paired: `AppBuildInfo.releaseServerUrl`, `https://<kvitt.publicHost>` (D-122, D-124). */
|
||||
private val releaseServerUrl: String,
|
||||
) : AboutRepository {
|
||||
override fun about(): Flow<AboutState> {
|
||||
|
||||
@@ -188,7 +188,7 @@ class Harness {
|
||||
companion object {
|
||||
const val APP_VERSION = 41
|
||||
const val APP_VERSION_NAME = "1.1"
|
||||
const val BASE_URL = "https://kvitt.test:8443"
|
||||
const val BASE_URL = "https://kvitt.test"
|
||||
const val TOKEN = "kvt_testtoken0000000000000000000000000000000000"
|
||||
const val ME = "0192a000-0000-7000-8000-000000000001"
|
||||
const val PARTNER = "0192a000-0000-7000-8000-000000000002"
|
||||
|
||||
@@ -528,6 +528,6 @@ class RepositoriesTest {
|
||||
private companion object {
|
||||
const val OLDER = "0192a003-0000-7000-8000-000000000002"
|
||||
/** `AppBuildInfo.releaseServerUrl` of the tests: a fixed host, not `:app`'s `kvitt.publicHost` (D-122). */
|
||||
const val RELEASE_SERVER_URL = "https://kvitt.example.org:8443"
|
||||
const val RELEASE_SERVER_URL = "https://kvitt.example.org"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,14 +60,14 @@ class SessionRepositoryTest {
|
||||
@Test
|
||||
fun pair_storesCredentials_writesTheHousehold_andStartsAFullSync() = runSync {
|
||||
acceptAs(ME)
|
||||
val result = repo().pair("https://kvitt.test:8443/ ", "7k3m-qx9d-2hpa", "Jacob", "Galaxy S26")
|
||||
val result = repo().pair("https://kvitt.test/ ", "7k3m-qx9d-2hpa", "Jacob", "Galaxy S26")
|
||||
assertEquals(ME, (result as OnlineResult.Ok).value.user.id.value)
|
||||
assertEquals(InviteKind.ADMIN_SETUP, result.value.inviteKind)
|
||||
val request = h.requests.single()
|
||||
assertEquals("https://kvitt.test:8443/invites/accept", request.url.toString())
|
||||
assertEquals("https://kvitt.test/invites/accept", request.url.toString())
|
||||
val credentials = h.credentials.credentials()
|
||||
assertEquals("kvt_new", credentials?.token)
|
||||
assertEquals("https://kvitt.test:8443", credentials?.baseUrl)
|
||||
assertEquals("https://kvitt.test", credentials?.baseUrl)
|
||||
assertEquals("d2", credentials?.deviceId)
|
||||
val session = repo().session.first()
|
||||
assertTrue(session is SessionState.Paired)
|
||||
@@ -98,7 +98,9 @@ class SessionRepositoryTest {
|
||||
|
||||
@Test
|
||||
fun serverUrls_releaseHttpsOnly_debugAlsoLocalHttp() {
|
||||
assertEquals("https://icehack.asuscomm.com:8443", SessionRepositoryImpl.normaliseServerUrl("https://icehack.asuscomm.com:8443/", debugBuild = false))
|
||||
assertEquals("https://kvitt.example.org", SessionRepositoryImpl.normaliseServerUrl("https://kvitt.example.org/", debugBuild = false))
|
||||
// An explicit port survives normalisation (D-124 serves on 443, but a typed port is the owner's choice).
|
||||
assertEquals("https://kvitt.example.org:8443", SessionRepositoryImpl.normaliseServerUrl("https://kvitt.example.org:8443/", debugBuild = false))
|
||||
assertNull(SessionRepositoryImpl.normaliseServerUrl("http://192.168.1.10:8080", debugBuild = false))
|
||||
for (ok in listOf("http://localhost:8080", "http://10.0.2.2:8080", "http://10.1.2.3", "http://172.16.0.1", "http://172.31.255.1", "http://192.168.1.10:8080")) {
|
||||
assertEquals(ok, SessionRepositoryImpl.normaliseServerUrl(ok, debugBuild = true))
|
||||
|
||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |