Files
Paul HittandClaude Opus 5.5 9099b6866c
ci / vectors-head (pull_request) Successful in 11s
ci / secret-sweep (pull_request) Successful in 22s
ci / parity-scrub (pull_request) Failing after 13s
ci / unit-tests (pull_request) Failing after 30m2s
ci / ui-tests (pull_request) Failing after 30m2s
ci: move CI to Gitea Actions
Translates .gitlab-ci.yml to .gitea/workflows/ci.yml and deletes it.
Every gate is kept: secret sweep, unit tests with the vector pin check and
the 700-test floor, UI tests with the 10-ran floor, vectors-head (advisory),
parity scrub.

Xcode jobs run on the pauls-imac runner; the sweep, vectors-head and the
scrub run on mac1/mac2. Builds and tests only, no signing.

The Obfs4 submodule and the sibling clones now come from
git.extant2000.com/extant2000, as do the README links.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:03:09 -04:00

6.7 KiB

The original nine

Verified by driving the apps and the relays, not by reading code. Where something is unproven it says so.

Re-checked 45 commits after the baseline. Three rows moved. What was re-run this time is marked; anything not marked is carried forward from the baseline and has not been re-driven.

# Item Status
1 Sign-up on managed / shared self-hosted / local self-hosted, iOS and Android done, with one caveat
2 Sign-up against each type, both platforms done
3 Messages between relay types server yes, iOS built, Android no
4 Everything wired and usable, repeat rounds done on the managed relay
5 iOS → Android message done
6 api-docs self-hosting documentation done
7 Public / donation / comparison pages done
8 Relay deployed to relay.flamenet.io deployed and current
9 Self-hosted accounts. Files optional done

1 & 2, sign-up across relay types

Both platforms, all four relays.

relay kind iOS Android
relay.flamenet.io managed (accounts: shared) yes yes
relay2.flamenet.io shared self-hosted yes yes
relay1.flamenet.io local self-hosted (accounts: local) yes yes
relay3.flamenet.io local self-hosted n/a yes

"Three clean rounds" cannot be run back to back against a shared account service, and that is correct. It allows 3 new accounts per hour per IP; rounds 2 and 3 exhaust it and the service answers 429 Too many accounts created from here recently, which the app shows verbatim. The suites report that as SKIP, not FAIL, a suite that fails for a service working properly teaches everyone to ignore it.

Only local self-hosted survives repeated rounds, because it keeps its own accounts and has no such quota.

Repeatable via Scripts/android-signup.sh and RelayTypesUITests.

3, cross-relay messaging

The relays do it. test/federation.mjs (in flamenet-e2e since the split) against the live fleet: 11 passed, 0 failed: relay1 fetches bob's devices from relay2, sends across the boundary, bob's relay accepts exactly one envelope, he polls and it is there, it carries no sender attribution across the boundary, a relay off the allowlist is refused, and an unknown address is reported rather than silently dropped.

Re-run against the live fleet: 11 passed, 0 failed. Unchanged.

iOS now has the client path; Android still does not. E2EClient gained remoteDevices, remoteBundles and sendRemote, and E2EInbox gained transmitRemote, deliverRemote and a separate remoteThreads keyed on fnid@relay. Android calls none of it, it still reads the federation field from the descriptor and never acts on it.

Built is not proven. The iOS path compiles and its unit tests pass; it has NOT been driven across a real relay boundary from the app. The distinction matters here more than anywhere else on this list, because the Node harness passing is exactly what made the previous row look better than it was.

The comparison page still overstates it. "Servers can talk to each other Yes" is now true of the relay and of one client out of two. Reword the row or finish Android; a row that is half true reads as false to the half it is false for.

8, deployed

Deployed and current, verified by checksum. Re-checked after two deploys: Config.swift, RoutesAccount.swift and Retention.swift on the box are md5-identical to flamenet-relay HEAD. Production has the signup rate limit (verified live: five signups pass, the sixth is 429), the reset-token sweep, and retention logging at a level that is actually visible.

Since the split, deploys rsync from a flamenet-relay checkout, flamenetmessenger/server/ no longer exists.

Production also runs FN_LOG_LEVEL=error, which suppresses the hourly retention line entirely. Retention is working, verified by querying the database directly and finding zero rows past any window, oldest envelope hours old, but there is no way to see that from the logs, which is the same unverifiable claim the retention code says it exists to avoid.

4, wired and usable

Three consecutive demo rounds on the managed relay, both directions, with the group visible each time, DemoRoundUITests plus the Android half. Not run against the other relay types.

6, documentation

api-docs.relay.flamenet.io now carries a compose file, every environment variable with whether it is actually required, and curl commands to check a relay is up. It previously documented the protocol thoroughly and never said how to start one.

7, public pages

Live and on production keys: sk_live / pk_live confirmed on the box. Stripe.js loads, the form is present, and the card fields appear after Continue by design.

Not exercised: a payment taken end to end. Doing so means creating a real PaymentIntent on the live connected account, so it was left alone. Closed on the owner's call. Recorded here rather than dropped, because "we verified the donation page" and "we watched a payment complete" are different claims and only one of them is true.

Found after the baseline

Android silently lost messages. A send to somebody with no registered device, anyone signed out, looped over an empty device list, made no request, and returned an empty failure map, which every caller reads as success. 1:1 text wrote nothing to the thread at all; group text wrote a bubble nobody received. iOS never had this. Fixed, with a regression test proved failing without the guard, and both platforms now hold undelivered messages in an outbox and retry rather than dropping them.

Android → iOS calls do not connect, cause unknown. Ruled out: wire shapes match, iOS hooks onCallSignal eagerly at sign-in, Android sets no from_addr so the federated fork is not swallowing it, and every clock agrees within a second so the 45s staleness check is not misfiring. The real defect found was that Android discarded the send result entirely, so an offer that reached nobody was indistinguishable from one that rang. Both sides are now instrumented; the next attempt will say where it stopped.

iOS conversation history had been written and never merged. The encrypted store sat alone on a parked branch while main moved 174 commits past it, so the app discarded every conversation on quit. Restored and now covered by five tests.

Known gaps at this tag

  • iOS push is built and never observed: needs a .p8 and a real device.
  • Call audio has never been heard by anyone.
  • No third-party audit, no reproducible builds, no post-quantum below iOS 26.
  • FN_DELETE_ON_ACK is off and must stay off until it has an end-to-end test. It deleted a message on production.