<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinos-server.git/lib, branch master</title>
<subtitle>coinos server — legacy coinos.io backend (Lightning, on-chain, Liquid)</subtitle>
<id>https://git.coinos.io/coinos-server.git/atom?h=master</id>
<link rel='self' href='https://git.coinos.io/coinos-server.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/'/>
<updated>2026-10-09T06:16:37Z</updated>
<entry>
<title>bolt12: put the requested expiry and single-use on the offer itself</title>
<updated>2026-10-09T06:16:37Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-09T06:16:37Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=0cbfab4779545afcc621d019ec93b30e5aec99df'/>
<id>urn:sha1:0cbfab4779545afcc621d019ec93b30e5aec99df</id>
<content type='text'>
The expiry was only stored on our invoice record, so CLN kept issuing
invoices for the offer after it had expired. Pass it as absolute_expiry,
and accept single_use to cap an offer at one payment.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>users: keep the encrypted nostr key and 2FA seed away from bearer tokens</title>
<updated>2026-10-08T19:15:15Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-08T19:15:15Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=5df9bc39ac48fdf1b19b00b9b457f9ebc1ee157c'/>
<id>urn:sha1:5df9bc39ac48fdf1b19b00b9b457f9ebc1ee157c</id>
<content type='text'>
/me and user emits return a hasnsec flag instead of the encrypted key, which
is now only sent with a password login or registration. /otpsecret refuses
once 2FA is enabled, and disabling 2FA rotates the seed.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Remove response logger</title>
<updated>2026-10-08T19:03:38Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-08T19:03:38Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=b3d6c983719560b6d3e2eb17b413f1147f2522a1'/>
<id>urn:sha1:b3d6c983719560b6d3e2eb17b413f1147f2522a1</id>
<content type='text'>
Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>payments: lowercase payreq before looking up our own invoices</title>
<updated>2026-10-07T04:12:19Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-07T04:12:19Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=f53e70ed98eb723479b4276c5b621b599fe570a0'/>
<id>urn:sha1:f53e70ed98eb723479b4276c5b621b599fe570a0</id>
<content type='text'>
An uppercase bolt11 for a coinos invoice missed the getInvoice lookup, so
it was paid over lightning to our own node instead of internally. The
listener then saw the sender's payment pointer for that bolt11 and skipped
crediting the recipient. Normalize in POST /payments and nwc pay_invoice.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>invoices: a supplied account must belong to the invoice's user</title>
<updated>2026-10-06T22:53:18Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-06T22:53:18Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=7727b97c71c11b4b65f47bcc68460ea981c1b22c'/>
<id>urn:sha1:7727b97c71c11b4b65f47bcc68460ea981c1b22c</id>
<content type='text'>
generate() took any existing account id as the credit target, so an
invoice could carry one user's name while paying into someone else's
account. A supplied aid now has to be in the invoice user's own account
list; otherwise the invoice credits that user's main account.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01KCxLg8s1g8yBwjRwPN4uJR
</content>
</entry>
<entry>
<title>Evicted accounts can't receive or log in; limit errors say what's happening</title>
<updated>2026-10-04T20:38:24Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-04T20:38:24Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=41018c30a2e03f5ab05be64d419542be0cff7943'/>
<id>urn:sha1:41018c30a2e03f5ab05be64d419542be0cff7943</id>
<content type='text'>
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 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_011bvzKaZosXGHkigcGcSzAR
</content>
</entry>
<entry>
<title>v3 bridge: a migrated name's legacy receives are paid on to its v3 wallet</title>
<updated>2026-10-04T20:05:53Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-04T20:05:53Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=1ff2623dbb43148267eac5cbe68c76d2c0639805'/>
<id>urn:sha1:1ff2623dbb43148267eac5cbe68c76d2c0639805</id>
<content type='text'>
A user who moved their name to coinos v3 keeps their legacy account, and
old BOLT12 offers, bolt11 invoices and bitcoin/liquid deposit addresses
keep paying into it. Each confirmed receive of those kinds is now
forwarded as it lands to the name's v3 lightning address (registrar
invoice on the ASP node; the v3 forwarder delivers to the Ark mailbox
even with the wallet closed). Only new receives move; existing balances
stay. Routing cost only: the platform fee is waived (debit exempt), and
the direct channels to the ASP node quote 0. Proof required: the
registrar holds the name for the legacy account's own key, or for the
wallet its session named in a migration grant (/name granted flag).
Autowithdraw stands down for forwarded receives; failures retry with
backoff (v3fwd:retry, one process at a time) and otherwise stay put.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_011bvzKaZosXGHkigcGcSzAR
</content>
</entry>
<entry>
<title>payments: refuse on-chain sends to blocked addresses before debiting</title>
<updated>2026-09-29T15:37:47Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-29T15:37:39Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=41a5819f5d7c662a5a2884952e49a14464e83c41'/>
<id>urn:sha1:41a5819f5d7c662a5a2884952e49a14464e83c41</id>
<content type='text'>
debit() checks blocked_addresses against the payment hash, which for an
on-chain send is the txid, so a blocked destination address was never
matched. Check each output address of the built transaction in sendOnchain
and fail before any debit.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>logging: throttle log lines that clients can trigger at will</title>
<updated>2026-09-29T15:37:47Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-29T15:37:39Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=4900ecb19ab9c6d279c8771b834fcb29e526a1e0'/>
<id>urn:sha1:4900ecb19ab9c6d279c8771b834fcb29e526a1e0</id>
<content type='text'>
Evicted-JWT replays, blocked sends from frozen or limited accounts and
failed payment retries each logged one line per request, so a looping client
could flood the log, and an evicted token replayed across a proxy pool made
atk-autoban.sh block every IP it saw. Add quiet()/suppressed() in
lib/logging.ts: the first occurrence per key logs as before, repeats within
the window are counted and reported on the next line that gets through. The
evicted-auth summary line is worded so the auto-banner ignores it.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>invoices: don't let a supplied id overwrite another user's invoice</title>
<updated>2026-09-29T15:37:47Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-29T15:37:39Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=e96ad1cea4192a608a7f15896e4b690b57bf8fc9'/>
<id>urn:sha1:e96ad1cea4192a608a7f15896e4b690b57bf8fc9</id>
<content type='text'>
generate() writes invoice:&lt;id&gt; wholesale with the caller's uid, and the old
bolt11 pointer keeps resolving to that id, so passing someone else's invoice
id re-pointed their invoice at the caller's account. Invoice ids aren't
secret (LUD-21 verify URLs, invoice pages, receipts), so refuse an existing
id that belongs to a different user, both in generate() and in POST /invoice
for anonymous pay-page callers. Both fail with "invoice not found" so ids
can't be probed for existence.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
