refactor: deprecate the row rebuild, and write down what goes with it
`assemble` reads `GroupSignedEvent` now and rebuilds from `Mantra*` rows only what that table does not hold, which is work signed before it existed. The rebuild is therefore on its way out rather than merely second in line, and this says so where a reader will actually meet it -- at the call site, from the compiler -- instead of only in a paragraph they have to find first. **Nine `@Deprecated` markers, and they are load-bearing as documentation.** The eight `toXEvent()` methods and `ArchiveManager.rebuiltEventsOf`, each carrying the same sentence: this is the fallback for pre-v13 work, read the event off the table instead, and it goes when the last such install does. That raises nine warnings in `commonMain` today, all of them inside the walk itself, so the deprecation is visible in every build without anything failing over it. The level is `WARNING` deliberately -- the code is still called, still correct, and still the only thing standing between an older room and an empty archive. **The checklist is a new section in docs/member-archive.md**, because the interesting part of this removal is not the eight methods, it is everything around them that is easy to take out by association or leave behind by accident. *What goes*: the walk and the version-label recovery inside it, the union in `signedEventsOf`, the eight rebuilds, and `ArchiveRoundTripTest` entire -- all ten cases, which exist to hold the rebuild up and cover nothing else. Its own header still opened with "signed events are not stored as events", which stopped being true two commits ago, so it now says what it is: the gate on a deprecated fallback, deleted with what it guards. *Two already-dead cousins to sweep at the same time*, named because they will look like part of the rebuild to whoever does the removal and are not: `MantraTranslation.toTranslationEvent`, which nothing has ever called, and `MantraTranslationChunkProposal.toTranslationChunkEvent`, on a model that is not even a `@Database` entity. *The tests that seed without recording*: in `ArchiveAssemblyJvmTest` the `apply`-only seeding **is** the rebuild path, and two of its cases are about the union specifically and mean nothing without it. `ArchiveApplyJvmTest` seeds its sender the same way but is testing delivery rather than assembly, so it needs the recording call *added* -- otherwise it quietly starts asserting against an empty archive, which is the same silent-success failure this whole feature is about. **What only looks like it goes, which is the half worth writing down.** The `isArchivable` filter in `signedEventsOf` is not part of the rebuild and becomes the only thing standing. It is there *because* of the record: the walk could only ever produce document kinds, so nothing needed filtering while it was the source, and the table holds every kind the group has signed -- starting with the `GroupKeyStateEvent` every room signs as its first act. Dropping it with the walk turns every room's archive into an `IllegalArgumentException` from `ArchiveEvent.build`. Two cases fail with exactly that if it goes, which is the guard against removing it by association rather than by decision. The verify filter in `assemble` stays too. With the rebuild gone it checks events that were verified before they were recorded, so it cannot fail in practice -- which is the argument for keeping it, not against. "Cannot happen" is the state it exists to preserve. `Mantra*.signature` and `Mantra*.publicKey` are explicitly *not* on the list. They were what made a row rebuildable, and since v13 `groupSignedEventId` says whether the group signed a row and points at the proof -- so they are arguably redundant. But four test files assert on them and `MantraTranslationContributor` builds a contributor list out of one, and it is a twelve-table migration with its own tests to rewrite. It should be decided on its own merits, not ride along. **The precondition cannot be checked, and the section says so plainly.** No query answers "does any install still hold pre-v13 work" -- a device that upgraded is indistinguishable from one that never had any, and the rows that need rebuilding are on other people's devices. What is observable is the `signedEventsOf` log line, which fires only when the rebuild actually contributed something; fleet-wide silence is evidence and not proof. The cost of getting it wrong is named as well, because it is not loud: the member keeps their own rows and reads the room normally, and only loses the ability to *answer* a request with the older half of the group's work -- so a newer member asks, is answered, and receives an archive that is quietly short. No behaviour change. 495 jvm tests and 297 android unit tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -87,6 +87,11 @@ data class MantraArtifact(
|
||||
* wrong here until an archive needed to rebuild an artifact and nothing had
|
||||
* ever called this.
|
||||
*/
|
||||
@Deprecated(
|
||||
"Archive fallback for work signed before the GroupSignedEvent table. Read the " +
|
||||
"event off that table instead; this rebuild goes when the last pre-v13 install " +
|
||||
"does -- see the removal checklist in docs/member-archive.md."
|
||||
)
|
||||
fun toArtifactEvent(versionLabel: String): ArtifactEvent {
|
||||
return ArtifactEvent(
|
||||
id = id,
|
||||
|
||||
@@ -66,6 +66,11 @@ data class MantraArtifactVersion(
|
||||
override val createdAt: Instant = Clock.System.now(),
|
||||
override val updatedAt: Instant = createdAt
|
||||
): OptionalNostrEventEntity, TimestampedEntity {
|
||||
@Deprecated(
|
||||
"Archive fallback for work signed before the GroupSignedEvent table. Read the " +
|
||||
"event off that table instead; this rebuild goes when the last pre-v13 install " +
|
||||
"does -- see the removal checklist in docs/member-archive.md."
|
||||
)
|
||||
fun toArtifactVersionEvent(): ArtifactVersionEvent {
|
||||
return ArtifactVersionEvent(
|
||||
id = id,
|
||||
|
||||
@@ -71,6 +71,11 @@ data class MantraChapter(
|
||||
override val updatedAt: Instant = createdAt
|
||||
): OptionalNostrEventEntity, TimestampedEntity {
|
||||
|
||||
@Deprecated(
|
||||
"Archive fallback for work signed before the GroupSignedEvent table. Read the " +
|
||||
"event off that table instead; this rebuild goes when the last pre-v13 install " +
|
||||
"does -- see the removal checklist in docs/member-archive.md."
|
||||
)
|
||||
fun toChapterEvent(): ChapterEvent {
|
||||
return ChapterEvent(
|
||||
id = id,
|
||||
|
||||
@@ -67,6 +67,11 @@ data class MantraChunk(
|
||||
override val updatedAt: Instant = createdAt
|
||||
): OptionalNostrEventEntity, TimestampedEntity {
|
||||
|
||||
@Deprecated(
|
||||
"Archive fallback for work signed before the GroupSignedEvent table. Read the " +
|
||||
"event off that table instead; this rebuild goes when the last pre-v13 install " +
|
||||
"does -- see the removal checklist in docs/member-archive.md."
|
||||
)
|
||||
fun toChunkEvent(): ChunkEvent {
|
||||
return ChunkEvent(
|
||||
id = id,
|
||||
|
||||
@@ -56,6 +56,11 @@ data class MantraDialect(
|
||||
override val updatedAt: Instant = createdAt
|
||||
): OptionalNostrEventEntity, TimestampedEntity {
|
||||
|
||||
@Deprecated(
|
||||
"Archive fallback for work signed before the GroupSignedEvent table. Read the " +
|
||||
"event off that table instead; this rebuild goes when the last pre-v13 install " +
|
||||
"does -- see the removal checklist in docs/member-archive.md."
|
||||
)
|
||||
fun toDialectEvent(): DialectEvent {
|
||||
return DialectEvent(
|
||||
id = id,
|
||||
|
||||
@@ -75,6 +75,11 @@ data class MantraTranslationArtifactVersion(
|
||||
override val updatedAt: Instant = createdAt
|
||||
): OptionalNostrEventEntity, TimestampedEntity {
|
||||
|
||||
@Deprecated(
|
||||
"Archive fallback for work signed before the GroupSignedEvent table. Read the " +
|
||||
"event off that table instead; this rebuild goes when the last pre-v13 install " +
|
||||
"does -- see the removal checklist in docs/member-archive.md."
|
||||
)
|
||||
fun toTranslationArtifactVersionEvent(): TranslationArtifactVersionEvent {
|
||||
return TranslationArtifactVersionEvent(
|
||||
id = id,
|
||||
|
||||
@@ -70,6 +70,11 @@ data class MantraTranslationChapter(
|
||||
override val createdAt: Instant = Clock.System.now(),
|
||||
override val updatedAt: Instant = createdAt
|
||||
): OptionalNostrEventEntity, TimestampedEntity {
|
||||
@Deprecated(
|
||||
"Archive fallback for work signed before the GroupSignedEvent table. Read the " +
|
||||
"event off that table instead; this rebuild goes when the last pre-v13 install " +
|
||||
"does -- see the removal checklist in docs/member-archive.md."
|
||||
)
|
||||
fun toTranslationChapterEvent(): TranslationChapterEvent {
|
||||
return TranslationChapterEvent(
|
||||
id = id,
|
||||
|
||||
@@ -72,6 +72,11 @@ data class MantraTranslationChunk(
|
||||
override val updatedAt: Instant = createdAt
|
||||
): OptionalNostrEventEntity, TimestampedEntity {
|
||||
|
||||
@Deprecated(
|
||||
"Archive fallback for work signed before the GroupSignedEvent table. Read the " +
|
||||
"event off that table instead; this rebuild goes when the last pre-v13 install " +
|
||||
"does -- see the removal checklist in docs/member-archive.md."
|
||||
)
|
||||
fun toTranslationChunkEvent(): TranslationChunkEvent {
|
||||
return TranslationChunkEvent(
|
||||
id = id,
|
||||
|
||||
@@ -42,8 +42,10 @@ import press.mantra.compose.nostr.frost.GroupKeyStateEvent
|
||||
* signed; `ArchiveRoundTripTest` is what says it is, per kind, against a real
|
||||
* quorum, and it found two faults in the artifact's rebuild the first time it
|
||||
* ran -- both of which would have shipped payloads that every receiver drops as
|
||||
* forgeries without a word. The fallback can go once no install still holds
|
||||
* pre-v13 work.
|
||||
* forgeries without a word. Both it and everything that exists only to hold it
|
||||
* up are marked `@Deprecated`; the fallback can go once no install still holds
|
||||
* pre-v13 work, and docs/member-archive.md's "Retiring the rebuild" is the list
|
||||
* of what goes with it.
|
||||
*
|
||||
* **The allowlist does real work on the way out now.** The rebuild could only
|
||||
* ever produce document kinds; the table holds everything the group has ever
|
||||
@@ -662,7 +664,18 @@ object ArchiveManager {
|
||||
*
|
||||
* It returns everything it can rebuild and lets [signedEventsOf] and the
|
||||
* verify filter decide what can travel.
|
||||
*
|
||||
* Deprecated rather than merely legacy: it is a whole mechanism kept alive
|
||||
* for a shrinking set of rows, and it takes eight `toXEvent()` methods and a
|
||||
* ten-case round-trip suite with it. **docs/member-archive.md, "Retiring the
|
||||
* rebuild", is the checklist** -- what goes, what only looks like it goes,
|
||||
* and the one thing that has to be true before any of it can.
|
||||
*/
|
||||
@Deprecated(
|
||||
"Archive fallback for work signed before the GroupSignedEvent table. " +
|
||||
"Goes when the last pre-v13 install does -- see the removal checklist " +
|
||||
"in docs/member-archive.md."
|
||||
)
|
||||
private suspend fun rebuiltEventsOf(
|
||||
database: MantraDatabase,
|
||||
chatRoomId: String,
|
||||
|
||||
Reference in New Issue
Block a user