FN_SIGNUP_POW_BITS has been written, tested and off since it landed, and it could not simply be switched on. The gate refused any sign-up arriving without a challenge, so enabling it would have broken account creation for every build already in somebody's hand — and broken it invisibly, as an app that does not work.
The issue's first bullet has an answer, and it is not the one assumed
The issue asks to "confirm which shipped builds carry SignupProofOfWork (Android has it…)".
Android does not have it in the field. The published APK is 0.6, released 2026-08-31. client/src/main/kotlin/io/flamenet/client/SignupProofOfWork.kt was added 2026-09-01 — one day later. iOS has it on main and has not shipped at all.
So the shipped floor on both platforms is a client that cannot answer a challenge, which is exactly the case the wall would have hit.
What changed
A client that sends no challenge now drops to a strict per-address allowance instead of being refused:
allowance
answers the challenge
FN_SIGNUP_MAX_PER_HOUR — 50/hr
cannot answer
FN_SIGNUP_MAX_PER_HOUR_WITHOUT_POW — 5/hr
answers it wrong
refused, challenge_failed
Five per address per hour is the accidental backstop that existed before relay#9 raised the limit to 50 — restored, but only for callers that cannot do the work rather than for everybody. Doing the work is what buys the generous allowance, so the opt-out costs something.
A wrong answer is still refused outright. Sending garbage must not be a cheaper route to the lenient path than sending nothing, or the work is optional for anyone who reads the file.
0 restores the wall — the right setting once both shipped clients solve challenges, and deliberately still reachable.
Falsified, not just passed
Six new tests. Both halves were checked against the unfixed code:
disabling the fallback branch → a client that cannot answer still gets an account and skipping the work drops the caller to the strict allowance both go red with challenge_required
charging the generous limit in the fallback instead of the strict one → the second goes red on its own: an error was expected but none was thrown
19/19 in the file, locally.
Honest about what this buys
Per-address is trivially rotated, so the strict fallback bounds a lazy attacker and not a determined one. That limit is written into the code comment, not only here. The gain is not that the fallback is strong — it is that the strong thing can now be enabled at all, without stranding real people on an old build.
Not done here
Actually setting FN_SIGNUP_POW_BITS in production. That is now safe for shipped clients and is an ops decision, so it is left to be taken deliberately rather than smuggled into a code change.
Closes #52.
## What was wrong
`FN_SIGNUP_POW_BITS` has been written, tested and **off** since it landed, and it could not simply be switched on. The gate refused any sign-up arriving without a challenge, so enabling it would have broken account creation for every build already in somebody's hand — and broken it invisibly, as an app that does not work.
## The issue's first bullet has an answer, and it is not the one assumed
The issue asks to *"confirm which shipped builds carry `SignupProofOfWork` (Android has it…)"*.
**Android does not have it in the field.** The published APK is 0.6, released **2026-08-31**. `client/src/main/kotlin/io/flamenet/client/SignupProofOfWork.kt` was added **2026-09-01** — one day later. iOS has it on `main` and has not shipped at all.
So the shipped floor on *both* platforms is a client that cannot answer a challenge, which is exactly the case the wall would have hit.
## What changed
A client that sends no challenge now drops to a strict per-address allowance instead of being refused:
| | allowance |
|---|---|
| answers the challenge | `FN_SIGNUP_MAX_PER_HOUR` — 50/hr |
| cannot answer | `FN_SIGNUP_MAX_PER_HOUR_WITHOUT_POW` — 5/hr |
| answers it **wrong** | refused, `challenge_failed` |
Five per address per hour is the accidental backstop that existed before relay#9 raised the limit to 50 — restored, but only for callers that cannot do the work rather than for everybody. **Doing the work is what buys the generous allowance**, so the opt-out costs something.
A *wrong* answer is still refused outright. Sending garbage must not be a cheaper route to the lenient path than sending nothing, or the work is optional for anyone who reads the file.
`0` restores the wall — the right setting once both shipped clients solve challenges, and deliberately still reachable.
## Falsified, not just passed
Six new tests. Both halves were checked against the *unfixed* code:
- disabling the fallback branch → *a client that cannot answer still gets an account* and *skipping the work drops the caller to the strict allowance* both go red with `challenge_required`
- charging the generous limit in the fallback instead of the strict one → the second goes red on its own: `an error was expected but none was thrown`
19/19 in the file, locally.
## Honest about what this buys
Per-address is trivially rotated, so the strict fallback bounds a lazy attacker and not a determined one. That limit is written into the code comment, not only here. The gain is not that the fallback is strong — it is that **the strong thing can now be enabled at all**, without stranding real people on an old build.
## Not done here
Actually setting `FN_SIGNUP_POW_BITS` in production. That is now safe for shipped clients and is an ops decision, so it is left to be taken deliberately rather than smuggled into a code change.
added 4 commits
<ul><li>487efd18...7e1792f6 - 2 commits from branch <code>main</code></li><li>01625a6c - Switching the sign-up work on no longer walls out an old build (relay#52)</li><li>a0687864 - Regenerate the configuration page after editing its source</li></ul>
[Compare with previous version](/paulhitt/flamenet-relay/-/merge_requests/74/diffs?diff_id=2009243271&start_sha=487efd187fd9769fdfec04f562418ee26b24f606)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #52.
What was wrong
FN_SIGNUP_POW_BITShas been written, tested and off since it landed, and it could not simply be switched on. The gate refused any sign-up arriving without a challenge, so enabling it would have broken account creation for every build already in somebody's hand — and broken it invisibly, as an app that does not work.The issue's first bullet has an answer, and it is not the one assumed
The issue asks to "confirm which shipped builds carry
SignupProofOfWork(Android has it…)".Android does not have it in the field. The published APK is 0.6, released 2026-08-31.
client/src/main/kotlin/io/flamenet/client/SignupProofOfWork.ktwas added 2026-09-01 — one day later. iOS has it onmainand has not shipped at all.So the shipped floor on both platforms is a client that cannot answer a challenge, which is exactly the case the wall would have hit.
What changed
A client that sends no challenge now drops to a strict per-address allowance instead of being refused:
FN_SIGNUP_MAX_PER_HOUR— 50/hrFN_SIGNUP_MAX_PER_HOUR_WITHOUT_POW— 5/hrchallenge_failedFive per address per hour is the accidental backstop that existed before relay#9 raised the limit to 50 — restored, but only for callers that cannot do the work rather than for everybody. Doing the work is what buys the generous allowance, so the opt-out costs something.
A wrong answer is still refused outright. Sending garbage must not be a cheaper route to the lenient path than sending nothing, or the work is optional for anyone who reads the file.
0restores the wall — the right setting once both shipped clients solve challenges, and deliberately still reachable.Falsified, not just passed
Six new tests. Both halves were checked against the unfixed code:
challenge_requiredan error was expected but none was thrown19/19 in the file, locally.
Honest about what this buys
Per-address is trivially rotated, so the strict fallback bounds a lazy attacker and not a determined one. That limit is written into the code comment, not only here. The gain is not that the fallback is strong — it is that the strong thing can now be enabled at all, without stranding real people on an old build.
Not done here
Actually setting
FN_SIGNUP_POW_BITSin production. That is now safe for shipped clients and is an ops decision, so it is left to be taken deliberately rather than smuggled into a code change.added 4 commits
main01625a6c- Switching the sign-up work on no longer walls out an old build (relay#52)a0687864- Regenerate the configuration page after editing its sourceCompare with previous version
mentioned in commit
ebea63a3ffchanged the description