| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
| |
An evicted account no longer gets lightning-address invoices (stops a
scam page's address from minting new ones) or a login token. A send
over the server limit now says withdrawals are temporarily limited
instead of a generic "Problem sending payment" that read as a frozen
account. (Already live since the 2026-10-01 restart.)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_011bvzKaZosXGHkigcGcSzAR
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
GET /pay/:user/:amount and the lnurl callback create a CLN invoice and an
entry in the recipient's invoice list for anyone holding the link, which a
scanner on rotating IPs can do without tripping per-IP limits. Cap fresh
invoices at 120 per recipient per hour (reused invoices don't count).
Also fail cleanly for unknown usernames and skip invoice ids whose records
no longer exist, instead of throwing on the null and breaking the pay page.
Throttle the resulting lnurlp warnings per username.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
| |
A callback id is read once, minutes after the metadata request, and never
again, but the pointer keys were written without an expiry and had grown
to roughly 45% of all keys in the main database. Let the set helper take
a TTL and apply one to both lnurl pointer keys.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
credit() ran fail("memo too long") on memos >5000 chars, but it runs
AFTER settlement: an incoming lightning/bolt12 deposit has already
advanced pay_index, and an internal send has already debited the sender.
The throw was only logged, replay() hit the same throw, and the sats sat
in the house wallet uncredited. The memo is attacker-controllable and was
uncapped via the lnurl comment param and the bolt12 payer_note.
Truncate the memo in credit() instead of throwing (a clipped note is
harmless), and cap the lnurl comment to the advertised 512 at ingress.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Serving local accounts unconditionally sent migrated names (whose legacy
user record still exists) back to the old account, and left v3-only
custom names 500ing — only npub1* names had a Cloudflare redirect.
Resolution order is now: registrar-claimed -> registrar (response handed
through, cached 60s, fail-open to local if the registrar is down), else
local account, else 404. The migrated flag stays out of it: register.ts
stamps it on essentially every account. No loop: we defer only for names
the registrar HAS, and it never queries us for those.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A recent change made this coinos.io lnurlp endpoint defer any
migrated-flagged account to the v3 names registrar and 404 when the
registrar didn't have the name. But registration stamps that flag on
essentially every account and never syncs names to the registrar, so
this broke lightning-address resolution for nearly all accounts.
The v3 registrar is the front for v3 accounts and falls back to this
endpoint, so this endpoint is the fallback target: it must serve its own
accounts directly and must not defer back (which also avoids a loop once
the registrar's fallback is live). Serve the local account; 404 only when
no local account exists.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dpqu6wizYe1c1g4k5Gd8JK
|
| |
|
|
|
|
|
|
|
|
|
|
| |
A `migrated` flag on the user, settable through /user and visible on the
public user endpoint. It changes exactly one thing: lnurlp for that
username defers to the names registrar, so payments to [email protected]
arrive in the person's v3 wallet. The account itself is untouched — same
username, same history, still usable here — which is why this is a flag
and not a rename or a shutdown.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
| |
An address at this domain may now belong to a coinos v3 wallet rather
than a local account. When the username isn't ours, ask the names
registrar and pass its payRequest through unchanged — its callback is
absolute, so the payer talks to it directly from there.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The /lnurl/proxy, /decode and /encode handlers fetched an arbitrary
user-supplied URL via got() and returned the body — an unauthenticated
SSRF reaching internal services. Route those fetches through a new
safeGot() that rejects hosts resolving to loopback/private/link-local/
CGNAT/metadata ranges, re-validates on each redirect hop, restricts the
scheme to http(s), and caps timeout + response size. Also validate the
NIP-57 zap request (kind 9734 + signature) before storing it, instead of
trusting the client-supplied event.
These endpoints can't be removed — they back lightning-address/LNURL
parsing and resolution in the wallet UI.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| | |
|
| |
|
|
| |
Co-Authored-By: Claude Opus 4.6 <[email protected]>
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|