Blocking somebody now cancels their sealed passes too
§21.4 gave a lever to cut off one contact and nothing pulled it. That is the failure this project has been fixing all day in other places — a capability built and left unreachable. Blocking is where it belongs, and the reason is stronger than convenience. The relay CANNOT enforce a block against a sealed sender: the request carries no sender to compare against a block list, and the send route's own comment says so. So blocking stopped the identified path and nothing else, and a blocked person's sealed messages were dropped by the app after decryption rather than refused at the door. Revoking their capabilities is what closes that. The copy changes with it, because "buddies you block can't send you messages" was not true and is the kind of overclaim a safety screen must not make. It now says what blocking does, and names the gap left: the shared key everybody holds is not that person's alone, so it takes replacing to close completely — with the cost of that stated in the same breath rather than in a different screen. The sealed-sender section changes for the same reason. It said replacing the key is "the only way" to cut somebody off, which was true when it was written and is not now. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
79c2734f86
commit
8061f54e96
@@ -271,6 +271,37 @@ class DeliveryTokenTest {
|
||||
assertEquals(first, vault.issuedTokens(42).toSet())
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔴 **This is the act the whole section exists to make possible.** The
|
||||
* relay cannot enforce a block against a sealed sender — the request
|
||||
* carries no sender to compare against a block list — so before §21.4,
|
||||
* blocking stopped the identified path and nothing else, and a blocked
|
||||
* person's sealed messages were dropped by the app after decryption rather
|
||||
* than refused at the door.
|
||||
*
|
||||
* The view model calls this alongside the block; asserted at this layer
|
||||
* because it is where the behaviour lives.
|
||||
*/
|
||||
@Test
|
||||
fun `revoking is what stops a sealed sender the relay cannot identify`() {
|
||||
val c = withDeliveryKey()
|
||||
c.send(toUserId = 42, text = "hello")
|
||||
assertEquals(64, held.size)
|
||||
|
||||
c.revokeDeliveryTokens(forUserId = 42)
|
||||
|
||||
// Every capability that person held is gone from the relay, so their
|
||||
// next sealed send is refused with no sender ever named.
|
||||
assertEquals(0, held.size)
|
||||
assertTrue(vault.issuedTokens(42).isEmpty())
|
||||
}
|
||||
|
||||
/** Revoking a contact who never held any is not an error. */
|
||||
@Test
|
||||
fun `revoking somebody with no batch does nothing and says so`() {
|
||||
assertEquals(0, withDeliveryKey().revokeDeliveryTokens(forUserId = 99))
|
||||
}
|
||||
|
||||
// MARK: - Receiving a batch
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user