M12e: contract pass (pair invite kind, admin name in invite links, sync failed flag, rejection actor, device version name, template id, update check result, untouched accounts, D-027 re-stamp, PushEvent in :core:model, snackbar hosts)

Server: E-3 invite_kind; E-12 link ?from=<admin name>, E-4 passes it into kvitt://invite;
X-Kvitt-App-Version-Name stored in devices.app_version_name (migration 0003, schema 3);
OpenAPI and examples follow. Phone: :core:model, :core:fakes, :data, features and :app
updated together; goldens re-recorded for S-20 (version name) and new S-1/S-22 states.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
2026-10-18 15:00:50 +02:00
parent 6159e18198
commit 8c607153c0
96 changed files with 1090 additions and 298 deletions
@@ -33,6 +33,19 @@ class AppLinksTest {
assertEquals(AppLink.Invite("https://icehack.asuscomm.com:8443", "ABCDEFGHJKMN"), link)
}
@Test
fun linksWithTheAdminNameCarryIt_andOldLinksStillParse() {
assertEquals(
AppLink.Invite("https://icehack.asuscomm.com:8443", "ABCDEFGHJKMN", "Åsa Berg"),
AppLinks.parseUri("https://icehack.asuscomm.com:8443/i/ABCDEFGHJKMN?from=%C3%85sa%20Berg"),
)
assertEquals(
AppLink.Invite("https://icehack.asuscomm.com:8443", "ABCDEFGHJKMN", "Jacob"),
AppLinks.parseUri("kvitt://invite?server=https%3A%2F%2Ficehack%2Easuscomm%2Ecom%3A8443&code=ABCDEFGHJKMN&from=Jacob"),
)
assertNull(AppLinks.parseUri("https://icehack.asuscomm.com:8443/i/ABCDEFGHJKMN")?.adminName)
}
@Test
fun otherLinksAreIgnored() {
assertNull(AppLinks.parseUri(null))
@@ -10,7 +10,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
import se.hagstedt.kvitt.adapter.fcm.PushEvent
import se.hagstedt.kvitt.model.PushEvent
import se.hagstedt.kvitt.link.OpenTarget
import se.hagstedt.kvitt.model.Role
import se.hagstedt.kvitt.model.User