Release 0.12.0 — relay-AUTH crash fix + bunker sign-in #6

Merged
laoc merged 6 commits from release/0.12.0 into main 2026-08-06 10:25:47 +00:00
Owner

Both streams together for a joint test, as asked. Supersedes #4 and #5, which are merged into this branch.

0955d3d  Launch the signer intent on the main thread   (the reported crash)
0c553d6  Sign in with a bunker code                    (NIP-46)
d0f1e73  Wait for the auth relay's socket              (harness)
86bf673  Bump to 0.12.0 / versionCode 15

0.12.0 rather than 0.11.2 because a second way to sign in is a feature, not a patch — 0.11.1 users get a new capability, not just a repair. One line to change if you disagree.

Verification

55/55 instrumented, 0 failures
JVM unit suite green

One thing worth reporting rather than hiding: the first full run of the combined branch came back 54/55, with AuthRelayE2ETest failing on "No relay accepted it: relay not connected". It passed in isolation and passed on the re-run — a flake, not a regression from either branch.

I did not leave it there. The harness was the likely cause: the plain relay gets a real nak req readiness probe, while the auth relay only got kill -0, which says the process exists and nothing about whether it is listening. An anonymous req is refused by that relay by design, so the probe now waits for the socket to accept a TCP connection. Green on the run after.

Testing build

~/Nextcloud/Stash/stash-0.12.0-debug.apk (+ a .txt with what to try), sha256 1b4d428a…, versionCode 15 so it upgrades your current sideload.

Still not proven

The original crash has not been reproduced with real Amber — no signer app on the emulator. What is measured is the off-main AUTH callback and the main-thread requirement of the Activity Result API. Your phone is where the fix actually gets proven, which is what this build is for — and the reporter's logcat would still be worth having.

Both streams together for a joint test, as asked. Supersedes #4 and #5, which are merged into this branch. ``` 0955d3d Launch the signer intent on the main thread (the reported crash) 0c553d6 Sign in with a bunker code (NIP-46) d0f1e73 Wait for the auth relay's socket (harness) 86bf673 Bump to 0.12.0 / versionCode 15 ``` **0.12.0 rather than 0.11.2** because a second way to sign in is a feature, not a patch — 0.11.1 users get a new capability, not just a repair. One line to change if you disagree. ### Verification ``` 55/55 instrumented, 0 failures JVM unit suite green ``` **One thing worth reporting rather than hiding:** the first full run of the combined branch came back **54/55**, with `AuthRelayE2ETest` failing on `"No relay accepted it: relay not connected"`. It passed in isolation and passed on the re-run — a flake, not a regression from either branch. I did not leave it there. The harness was the likely cause: the plain relay gets a real `nak req` readiness probe, while the auth relay only got `kill -0`, which says the process exists and nothing about whether it is listening. An anonymous req is refused by that relay by design, so the probe now waits for the socket to accept a TCP connection. Green on the run after. ### Testing build `~/Nextcloud/Stash/stash-0.12.0-debug.apk` (+ a `.txt` with what to try), sha256 `1b4d428a…`, versionCode 15 so it upgrades your current sideload. ### Still not proven The original crash has not been reproduced with real Amber — no signer app on the emulator. What is measured is the off-main AUTH callback and the main-thread requirement of the Activity Result API. **Your phone is where the fix actually gets proven**, which is what this build is for — and the reporter's logcat would still be worth having.
Asked for on Zapstore against v0.11.0: "it would be even better if it had
a way to login with a bunker code". Stash signs only over NIP-55 today, so
anyone without a signer app installed reaches "No Nostr signer found on
this device" and stops there.

NostrConnectSigner is a third NostrSigner implementation. No caller
changes: the repository does not know which signer it was handed.

Tested against a REAL bunker, not a fake. scripts/e2e-direct.sh now runs
`nak bunker` with a fixed key on its own relay, so the emulator pairs over
a websocket and the event that comes back is signed by a key this process
has never seen — which is the whole point of NIP-46 and the one thing a
fake signer could not show.

One thing the tests found: the Duration handed to NostrConnect does NOT
bound the attempt. Configured at 20s, a dead relay still took 30093ms to
give up. The bound is now enforced at our own boundary with
withTimeoutOrNull, and the test asserts 25s rather than 30 — a 30s
assertion would have passed on the binding's own behaviour and never
noticed ours had stopped working.

A failure is reported as Failed, never Rejected: NIP-46 returns an error
string, so a user declining and a relay dropping arrive identically, and
Rejected drives UI that says the user declined.
Sign in with a bunker code
All checks were successful
build / build (push) Successful in 6m46s
build / build (pull_request) Successful in 6m51s
0c553d6ae0
Completes the NIP-46 path: encrypted session storage, restore at startup,
a login UI, and a settings label that is not a sentinel string.

The client key is sealed by SecretBox — AES-GCM with a key held in
AndroidKeyStore — not stored beside the relay list in the clear. Not
androidx.security:security-crypto: that is a new dependency, it is
deprecated, and what it gives us here is sixty lines of platform API. The
key is deliberately NOT user-authentication-bound, because the app signs
in the background for relay AUTH and a key demanding a screen unlock
would fail those with nothing to ask.

Restore is asynchronous and silent on failure. The library is already on
screen from cache and reading needs no signer, so "signer unavailable" on
every cold start with a sleeping bunker would be noise; it surfaces when
signing is actually attempted.

The login screen distinguishes waiting from broken. Pairing blocks on a
human approving on another device, and a bare spinner cannot tell the
user which of those is happening — that is how these features come to
feel broken.

Logout drops both halves: the sealed session and the keystore key that
opens it.
Launch the signer intent on the main thread
All checks were successful
build / build (pull_request) Successful in 6m56s
0955d3d950
Carries two things: the relay-AUTH crash fix, and bunker (NIP-46) sign-in.

0.12.0 rather than 0.11.2 because a second way to sign in is a feature,
not a patch — 0.11.1 users get a new capability, not just a repair. Say
the word if you would rather it were a patch release; it is one line.
Wait for the auth relay's socket, not just its process
All checks were successful
build / build (pull_request) Successful in 6m41s
d0f1e73ead
AuthRelayE2ETest failed once in a full run with "relay not connected",
passed in isolation, and passed on the re-run — a flake, and the harness
was the likely cause: the plain relay gets a real `nak req` probe, while
the auth relay only got `kill -0`, which says the process exists and
nothing about whether it is listening.

An anonymous req is refused by this relay by design, so the probe waits
for the socket to accept a TCP connection instead.
laoc merged commit 00461220c2 into main 2026-08-06 10:25:47 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
laoc/stash-bookmark!6
No description provided.