Investigating an App Store review reporting that NIP-98 HTTP-auth signing (sign_event kind:27235 — used by gitworkshop, nsite, and media uploads) did not work: "lacking parity with Amber. wasnt able to HTTP Auth challenge requests." Review is mild (4-star, "seems promising"), no repro steps, and no matching GitHub account/issue exists from the reviewer. This issue reports what live testing against Clave's real signing code actually found — two confirmed bugs, one path cleared, and what's still unconfirmed.
Confirmed via live wire tests
research/nip98-signing-repro/run.sh drives ClaveTests/LightSignerNip98WireSmokeTests — Clave's actual LightSigner.handleRequest — against a local nak serve relay, then decrypts and checks the kind:24133 responses with nak.
Cleared: a spec-compliant sign_event(kind:27235) request auto-signs correctly on medium trust (the default bunker pairing). The signed event passes all four NIP-98 server checks (kind, exact u/method tags, created_at within the suggested 60s window) and the signature verifies. This path is not broken.
Bug A — malformed RPC params hang the client silently, on any trust level. LightSigner.swift:145-158: if a client sends sign_event with params shaped as [{...}] (a nested object) instead of the spec-required [json_stringified_string], decode fails and params degrades to []. Because extractEventKind then returns nil, LightSigner.swift:374-377 forces allowed = false before trust level is even consulted — so the request gets queued for approval even on medium/full trust, and per NIP-46's "no terminal error while a request is pending" rule, Clave sends no response at all. A spec-compliant client (nostr-tools/NDK — what gitworkshop and nsyte are built on) has no client-side timeout; it just hangs. The queued entry doesn't even carry a kind number to show the user (eventKind is nil, not 27235).
Bug B — a delayed low-trust approval delivers an already-stale event. LightEvent.swift:110 (signUnsignedEvent) uses the client-supplied created_at verbatim; Clave never refreshes it to the actual signing moment. If a user on low trust takes more than NIP-98's suggested 60s to approve — plausible, since the prompt shows no kind label explaining what's being approved (see below) — the delivered event is already outside the freshness window the instant Clave signs it. Clave reports "signed" successfully; the failure only surfaces one hop later, at the HTTP server's 401.
Already-known parity gaps (static, not re-litigated here)
- Approval prompt has no label for kind 27235 —
KnownKinds.names (ClientPermissions.swift:261-291) has no entry, so a low-trust prompt shows bare "Kind 27235".
- Clave ignores the optional
perms param clients request at connect (nothing reads it).
Not confirmed
- The reviewer's exact failure — no repro steps to match against.
- The push/NSE cold-start wake path. The iOS Simulator has no push, so this couldn't be exercised here. If the reviewer's device was backgrounded when the RPC arrived, this path — not the two bugs above — is the more likely culprit, and it remains untested.
- An end-to-end run against actual gitworkshop.dev or nsyte. The tests above drive Clave's real signing code with the exact wire shape those clients' underlying libraries produce, but don't exercise gitworkshop's/nsyte's own client code.
Repro
research/nip98-signing-repro/run.sh <simulator-udid>
Starts a local nak serve relay, runs ClaveTests/LightSignerNip98WireSmokeTests, decrypts the wire responses with nak, and checks Bugs A and B live against the actual signed events.
Source: App Store review triage, 2026-08-23.
Investigating an App Store review reporting that NIP-98 HTTP-auth signing (
sign_eventkind:27235 — used by gitworkshop, nsite, and media uploads) did not work: "lacking parity with Amber. wasnt able to HTTP Auth challenge requests." Review is mild (4-star, "seems promising"), no repro steps, and no matching GitHub account/issue exists from the reviewer. This issue reports what live testing against Clave's real signing code actually found — two confirmed bugs, one path cleared, and what's still unconfirmed.Confirmed via live wire tests
research/nip98-signing-repro/run.shdrivesClaveTests/LightSignerNip98WireSmokeTests— Clave's actualLightSigner.handleRequest— against a localnak serverelay, then decrypts and checks the kind:24133 responses withnak.Cleared: a spec-compliant
sign_event(kind:27235)request auto-signs correctly on medium trust (the default bunker pairing). The signed event passes all four NIP-98 server checks (kind, exactu/methodtags, created_at within the suggested 60s window) and the signature verifies. This path is not broken.Bug A — malformed RPC
paramshang the client silently, on any trust level.LightSigner.swift:145-158: if a client sendssign_eventwithparamsshaped as[{...}](a nested object) instead of the spec-required[json_stringified_string], decode fails andparamsdegrades to[]. BecauseextractEventKindthen returnsnil,LightSigner.swift:374-377forcesallowed = falsebefore trust level is even consulted — so the request gets queued for approval even on medium/full trust, and per NIP-46's "no terminal error while a request is pending" rule, Clave sends no response at all. A spec-compliant client (nostr-tools/NDK — what gitworkshop and nsyte are built on) has no client-side timeout; it just hangs. The queued entry doesn't even carry a kind number to show the user (eventKindisnil, not27235).Bug B — a delayed low-trust approval delivers an already-stale event.
LightEvent.swift:110(signUnsignedEvent) uses the client-suppliedcreated_atverbatim; Clave never refreshes it to the actual signing moment. If a user on low trust takes more than NIP-98's suggested 60s to approve — plausible, since the prompt shows no kind label explaining what's being approved (see below) — the delivered event is already outside the freshness window the instant Clave signs it. Clave reports"signed"successfully; the failure only surfaces one hop later, at the HTTP server's 401.Already-known parity gaps (static, not re-litigated here)
KnownKinds.names(ClientPermissions.swift:261-291) has no entry, so a low-trust prompt shows bare "Kind 27235".permsparam clients request atconnect(nothing reads it).Not confirmed
Repro
Starts a local
nak serverelay, runsClaveTests/LightSignerNip98WireSmokeTests, decrypts the wire responses withnak, and checks Bugs A and B live against the actual signed events.Source: App Store review triage, 2026-08-23.