Descriptor: say the wave 0b routes are served

The 0.32 apps (iOS and Android, release/0.32.0) turn on sealed first
contact, handle certificates, anonymous reads, reusable contact links and
the Listed setting only when the relay descriptor carries
`features.introductions`, `anonymousReads`, `contactLinks` and `unlisted`.
Main has served every one of those routes since 4095ca6 and advertised
none, so against main both apps stayed on 0.31 behaviour for all of them.

All four are true on every relay of this build: the routes are not behind
a switch. `webSearch` stays absent: this relay has no search route.

Test first: "the descriptor names the wave 0b routes this relay serves",
4 issues red, then green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Paul Hitt
2026-10-09 09:45:47 -04:00
co-authored by Claude Opus 5.5
parent da05d6d87f
commit 8ebf83f62c
2 changed files with 32 additions and 1 deletions
+14 -1
View File
@@ -41,6 +41,17 @@ extension Routes {
/// it again, once, so it lands in its own row, and can send its
/// `device_id` with its roster tags.
let perDeviceDigests: Bool
/// Wave 0b (2026-10-07), served on every relay of this build:
/// `POST /e2e/intro`, its challenge, and `GET /e2e/handle-cert`
/// (§14.5); `/e2e/anon/*` and `GET /e2e/devices/me` (§8.11);
/// `POST /e2e/contact-links` (§8.12); and `discoverable` on
/// `/messenger/me` (§8.12). The 0.32 apps turn sealed first
/// contact, anonymous reads, reusable links and the Listed setting
/// on only when these say so.
let introductions: Bool
let anonymousReads: Bool
let contactLinks: Bool
let unlisted: Bool
}
}
@@ -73,7 +84,9 @@ extension Routes {
accountsURL: shared ? Self.accountsURL : nil,
reports: config.contentReportsEnabled,
features: .init(
padAttachments: config.padAttachments, perDeviceDigests: true)
padAttachments: config.padAttachments, perDeviceDigests: true,
introductions: true, anonymousReads: true, contactLinks: true,
unlisted: true)
))
}
@@ -237,4 +237,22 @@ struct PaddingGroundworkTests {
#expect(features?["padAttachments"] as? Bool == true)
}
}
/// The 0.32 apps turn on sealed first contact, reads that name nobody,
/// contact links and the Listed setting only when the descriptor says the
/// relay serves them. Without these four, every one stays off.
@Test("the descriptor names the wave 0b routes this relay serves")
func descriptorWaveZeroB() async throws {
try await withRelay { h in
let res = try await h.routes.relayDescriptor(
h.anonymousRequest(.GET, "/.well-known/flamenet/relay"))
let json = try JSONSerialization.jsonObject(
with: Data(String(buffer: res.body.buffer!).utf8)) as? [String: Any]
let features = json?["features"] as? [String: Any]
for name in ["introductions", "anonymousReads", "contactLinks", "unlisted"] {
#expect(features?[name] as? Bool == true, "\(name) is not advertised")
}
#expect(features?["webSearch"] == nil, "this relay has no search route")
}
}
}