Put the app back to the last state that worked

Tonight's merges left sign-in, messages, calls and stories broken. Restores
app, engine and client to fa92581 — the tree that shipped as v8 and works.

Why they broke: those features are not independent. A message, a call
signal, a story and a story reply are the same content envelope with a
different kind, so they run through the same few functions in Content.kt.
Twenty-three MRs, each written against an older main and green on its own
branch, had never existed together until they were merged in one evening.

The conflicts that produced were resolved mechanically — union a parameter
list, merge a condition — and that produces code which compiles and passes
while being wrong: a field on the wrong struct, an argument in the wrong
order, a term in the wrong condition. Three were caught by the compiler.
The ones the compiler cannot see are why calls stopped connecting.

And the gate could not see any of it. 489 unit tests stayed green through
every break, because they test units: "assemble produces this JSON" is a
unit test, "Android shows what iOS sent" is not.

versionCode 10 so it installs over the broken v9.

Nothing is lost — every MR is still a merged commit with its branch on the
remote, and re-lands in small batches once there is a test that actually
sends a message between two devices.
This commit is contained in:
Paul Hitt
2026-09-02 19:03:30 -04:00
parent 1f126f2cee
commit aebf41ed95
41 changed files with 67 additions and 5016 deletions
@@ -1,93 +0,0 @@
package io.flamenet.e2e
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
/**
* A private archive of your own stories (ios#54).
*
* 🔴 **This keeps something the interface said would disappear.** So it is
* opt-in, and it only ever holds stories this account posted — an archive of
* other people's expiring stories is the exact opposite of what they were
* promised, and "it is private to you" does not repair that.
*/
class StoryArchiveTest {
private fun story(id: String, mine: Boolean, at: Long) = Vault.Story(
id = id, authorId = if (mine) 1L else 7L, mine = mine,
ref = Attachment.Ref(
kind = Attachment.STORY, id = "b$id", key = ByteArray(32),
digest = ByteArray(32), bytes = 1, mime = "image/jpeg",
width = 1, height = 1, duration = 0.0, expires = 1.0,
),
caption = "c$id", postedAt = at,
)
@Test
fun `your own expired story is kept`() {
assertEquals(listOf("1"),
Vault.archive(emptyList(), listOf(story("1", true, 100))).map { it.id })
}
/** 🔴 The rule the whole feature turns on. */
@Test
fun `somebody elses expired story is never kept`() {
assertTrue(Vault.archive(emptyList(), listOf(story("2", false, 100))).isEmpty())
}
@Test
fun `a mixed batch keeps only your own`() {
val result = Vault.archive(emptyList(), listOf(
story("1", true, 100), story("2", false, 200), story("3", true, 300)))
assertEquals(setOf("1", "3"), result.map { it.id }.toSet())
}
/** ⚠️ The sweep runs on every load; without this, one story piles up. */
@Test
fun `archiving is idempotent`() {
val one = story("1", true, 100)
val first = Vault.archive(emptyList(), listOf(one))
assertEquals(1, Vault.archive(first, listOf(one)).size)
}
/** ⚠️ Newest first, so the screen needs no sort. */
@Test
fun `the archive is newest first`() {
val result = Vault.archive(emptyList(), listOf(
story("1", true, 100), story("3", true, 300), story("2", true, 200)))
assertEquals(listOf("3", "2", "1"), result.map { it.id })
}
private class MapStorage : Vault.Storage {
val records = LinkedHashMap<String, ByteArray>()
override fun read(name: String) = records[name]
override fun write(name: String, bytes: ByteArray) { records[name] = bytes }
override fun delete(name: String) { records.remove(name) }
override fun names() = records.keys.toList()
}
private fun key() = javax.crypto.KeyGenerator.getInstance("AES")
.apply { init(256) }.generateKey()
/** ⚠️ Kept in the vault, like everything else about somebody's stories. */
@Test
fun `the archive round-trips through the vault`() {
val vault = Vault(MapStorage(), key())
assertTrue(vault.storyArchive().isEmpty())
vault.saveStoryArchive(listOf(story("1", true, 100)))
assertEquals(listOf("1"), vault.storyArchive().map { it.id })
}
/**
* 🔴 The archive must NOT be swept by the expiry rule the live set uses —
* everything in it is expired by definition, so reusing `saveStories`
* would empty it on the next write.
*/
@Test
fun `an expired story survives in the archive`() {
val vault = Vault(MapStorage(), key())
vault.saveStoryArchive(listOf(story("1", true, 100)))
assertEquals(1, vault.storyArchive().size)
}
}