<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinosv3-server.git/names/server.js, branch master</title>
<subtitle>coinos v3 server — payment-name registrar, NWC push, Blossom sync storage, feed</subtitle>
<id>https://git.coinos.io/coinosv3-server.git/atom?h=master</id>
<link rel='self' href='https://git.coinos.io/coinosv3-server.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/'/>
<updated>2026-10-22T05:19:07Z</updated>
<entry>
<title>names: custom offers carry their owner's key; ones that can't reach a wallet are retired</title>
<updated>2026-10-22T05:19:07Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-22T05:19:07Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=6b59316493a9a02f735a19e9747d2f3982d27ce2'/>
<id>urn:sha1:6b59316493a9a02f735a19e9747d2f3982d27ce2</id>
<content type='text'>
Releasing a name disabled its own offer but left its custom offers live
(27 orphans on 2026-10-22, rick@ had 4): a payment to one found no name
and no key, and would have sat in the forward queue for good. Custom
offers now record the owner's pubkey (backfilled at start from the name,
or for an orphaned npub1xxxxxxx@ name from the one current key with that
npub prefix — 4 recovered), and the settle loop forwards by it, so a
released name's offer pays the same key's name now, as the name's own
offer already did. Orphans with no owner to follow are disabled on the
node and dropped (23), as are a released staging name's.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>names: mint nothing payable for a wallet on another network, and retire what was minted</title>
<updated>2026-10-22T05:16:57Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-22T05:16:57Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=5c007a2540d5a033c0934844eff68688af68817c'/>
<id>urn:sha1:5c007a2540d5a033c0934844eff68688af68817c</id>
<content type='text'>
A staging name is a mutinynet wallet, but every claim got a mainnet BOLT12
offer on our node published in its record, and custom offers and POS sales
were minted there too: real sats paid that way had no route onward (2,092
sat parked on 2026-10-22). otherNetwork() — the record's ark address decides,
a staging name without one is mutinynet — now gates the claim's stand-in
offer, custom offers and POS invoices (LNURL already refused staging).

At start, retireOtherNetworkOffers() disables the offers already out there
(83 staging names, 13 custom offers), takes their lno= out of the published
DNS record and drops them from state; idempotent, so a failure retries next
start. npub1x7acf8s@staging.coinos.io keeps its offers: its wallet is mainnet.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>names: a queued payment the float can cover goes now, backoff or not</title>
<updated>2026-10-22T05:03:55Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-22T05:03:55Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=8229ea08caeb6d03efa56205b9526e2751217162'/>
<id>urn:sha1:8229ea08caeb6d03efa56205b9526e2751217162</id>
<content type='text'>
Float top-ups that missed their 60 s settle window landed later (+300k on
2026-10-22 once the ASP's vtxo pool refilled), but only a top-up seen to
settle resets the queue's backoff, so jarryd's 248k sat in a 1-hour wait
with 477k in the float.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>names: a wallet on another ark server gets its own Lightning invoice, one on another network is parked</title>
<updated>2026-10-22T04:43:05Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-22T04:43:05Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=481e1f827d94f9ac3b54ad2a5c087fc5d8ce9a88'/>
<id>urn:sha1:481e1f827d94f9ac3b54ad2a5c087fc5d8ce9a88</id>
<content type='text'>
The float step threw 'address belongs to a different ark server' before the
Lightning step ever ran, so manna and rogerv3 (wallets on Second) were retried
100 times since 10-18 without once asking their wallets for an invoice. The
destination's ark id now decides: the float only on our own server, otherwise
straight to the wallet's CLINK invoice — those wait for the wallet without
paging (waitingOnWallet in /health).

A staging name's tark address paid real sats through its mainnet offer has no
route at all: such a forward is parked (state.parked, with its reason) instead
of retried forever, and /health counts it for the desk monitor. Ten such
payments (2,092 sat, Sep–Oct test payments to @staging.coinos.io names) had
been retried ~900 times each.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>names: deliver to coinos wallets over a circular route, shrink failing float top-ups, report stuck money in /health</title>
<updated>2026-10-22T04:39:11Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-22T04:39:11Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=4c5cd496c321083501dee75da97f702953cb44f5'/>
<id>urn:sha1:4c5cd496c321083501dee75da97f702953cb44f5</id>
<content type='text'>
The ASP's vtxo pool sat empty for 35 hours (2026-10-20/22: 614k in the
rounds wallet against 1.12M needed to refill), and two forwards of ~124k
for jarryd sat in the queue the whole time:

- viaClink paid the wallet's own invoice with a plain pay, but a coinos
  wallet's invoice is minted by our ASP on this very node: a self-payment
  the hold plugin never sees ('Destination said it doesn't know invoice').
  It now goes out and back in over a channel pair (payCircular, shared with
  the float top-up) and waits for the wallet to claim, so a payment is
  delivered whenever the wallet is open, float or no float.
- a float top-up that doesn't settle halves the next ask (down to 20k),
  back to full size after one lands: 79 tries of 200k failed where the
  pool's 100k coins could have funded half of it.
- the retry tick can't overlap itself any more (a circular delivery waits
  up to 4 min; an overlapping tick would forward the same payment twice).
- /health reports pendingSat, oldestPendingAt, the top-up failure streak
  and last error, and payments for wallets on another ark server apart
  (undeliverable): the desk float monitor pages on these.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>live: a name streams a day after it's claimed (the registrar now records when; older records count from their last update), never if banned; GET /live/allowed says which and until when. Viewers can report a stream (POST /live/&lt;id&gt;/report, NIP-98): kept in .reports.jsonl and DM'd to the admins from the welcome key. An admin takes a stream down (POST /live/&lt;id&gt;/remove {ban}): it ends, its playlists and segments answer 410, its files move to .removed/ (kept for reporting, never trimmed), and a ban stops its sender streaming.</title>
<updated>2026-10-19T06:03:57Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-19T06:03:57Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=07fb145efbc32cdfe2dc488c65d8708260f6f648'/>
<id>urn:sha1:07fb145efbc32cdfe2dc488c65d8708260f6f648</id>
<content type='text'>
Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_013ZDf1cyCQLkfjftYhymZAg
</content>
</entry>
<entry>
<title>names: keep state in SQLite</title>
<updated>2026-10-16T19:57:19Z</updated>
<author>
<name>Adam Soltys</name>
<email>asoltys@gmail.com</email>
</author>
<published>2026-10-16T19:57:19Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=a3d2dc2e05a4f7c5ab0d6e7689498da9ca63de7b'/>
<id>urn:sha1:a3d2dc2e05a4f7c5ab0d6e7689498da9ca63de7b</id>
<content type='text'>
persist() rewrote the whole state file, close to 10 MB, on every settled
payment and every queue tick, so one crash during a write could take every
name with it. State now lives in SQLite (bun:sqlite, WAL,
synchronous=FULL): one row per name, offer, invoice and so on, with the
forwarder wallet's state kept as a single row. Each persist() is one
transaction that writes only the rows that changed, so a crash leaves the
previous state or the new one, never a torn file.

The in-memory state object and every persist() call stay as they were. On
the first start the JSON state file is imported, and a corrupt one stops
startup. The file is left in place, so a rollback to the JSON build still
finds its data. store.snapshot() makes a consistent copy while the service
runs, for backups.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Make this the coinosv3-server repo: the services, with coinosv3 pinned</title>
<updated>2026-10-16T19:57:19Z</updated>
<author>
<name>Adam Soltys</name>
<email>asoltys@gmail.com</email>
</author>
<published>2026-10-16T19:57:19Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=1dd70cc2c2b9b0a9f65a704ded9e322afabf736f'/>
<id>urn:sha1:1dd70cc2c2b9b0a9f65a704ded9e322afabf736f</id>
<content type='text'>
Carved out of coinosv3 (names, feed, nwcpush, blossom, vmedia, bridge and
their tests, with history). The shared wallet code they import (src/ark,
noffer, bolt12, popular-feed) now comes from a coinosv3 submodule pinned at
082fc2e, the commit the services have actually run on, so moving here changes
no behaviour; bumping it is its own commit. The two text helpers translation
uses arrived on the server later than that commit and are vendored under
names/vendor at the versions deployed, until the pin moves past them.

Root package.json pins the npm versions installed on the server. compose.yml
runs names, nwcpush and blossom from this checkout (read-only) with configs
and state under $STATE, outside the repo, and pins the Bun image.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>names: refuse a corrupt state file; flush before replacing it</title>
<updated>2026-10-16T19:54:48Z</updated>
<author>
<name>Adam Soltys</name>
<email>asoltys@gmail.com</email>
</author>
<published>2026-10-16T19:54:48Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=c88f0d860c089e49cebabd53d652859d04143457'/>
<id>urn:sha1:c88f0d860c089e49cebabd53d652859d04143457</id>
<content type='text'>
The loader treated any read or parse error as a fresh registrar and started
with no names, then persisted that empty state over the real one. A crash
can leave the state file truncated, because persist() renamed the new file
into place without flushing it. Now a missing file is a fresh start, an
unreadable one stops startup, and persist() fsyncs the file and its
directory around the rename.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>names: bring in the registrar as it ran on cs</title>
<updated>2026-10-16T19:54:42Z</updated>
<author>
<name>Adam Soltys</name>
<email>asoltys@gmail.com</email>
</author>
<published>2026-10-16T19:54:42Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3-server.git/commit/?id=04b395feba38e50506174c03fa537911d3f15459'/>
<id>urn:sha1:04b395feba38e50506174c03fa537911d3f15459</id>
<content type='text'>
The deployed registrar carried changes made directly on the server between
Oct 10 and Oct 14 that never reached the repo:

- forward() delivers to the same key's current name when the paid name was
  released in the meantime (a v2 migration swaps its throwaway npub name for
  the real one seconds after a payment can settle)
- "nowhere to send" throws, so the payout stays queued instead of dropping
- the forwarder float merges small coins (consolidateFloat) before a send
  hits the input cap
- floatUpkeep skips coins already past expiry, which the server's sweeper
  has taken and whose refresh never settles

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