diff options
| author | Adam Soltys <[email protected]> | 2026-08-28 20:53:13 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-28 20:53:13 -0700 |
| commit | ef1ed09ec688ce27b8a2c3c957515f4dc7ab0596 (patch) | |
| tree | 33a4ba8ee92f467cb5fcd9fa4796a862d07c80ff | |
| parent | a056ea615498ee62e4180c1e09b3ce0a5a03de0f (diff) | |
| download | coinosv3-ef1ed09ec688ce27b8a2c3c957515f4dc7ab0596.tar.gz coinosv3-ef1ed09ec688ce27b8a2c3c957515f4dc7ab0596.zip | |
A name's proof is its key, not a flag: takenByCoinosUser stops trusting `migrated` (which let poppy get squatted) — an existing coinos.io name yields only to a claim signed by that account's own nostr key; the squatted record, its DNS entry and its offer are evicted
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
| -rw-r--r-- | names/server.js | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/names/server.js b/names/server.js index e49da51..e713ff4 100644 --- a/names/server.js +++ b/names/server.js @@ -572,15 +572,18 @@ const npubPrefixOwner = (name) => (/^npub1[a-z0-9]+$/.test(name) ? name : null); // coinos.io names that belong to existing coinos users are reserved for // them until the migration gives those users a way to claim their own. -async function takenByCoinosUser(domain, name) { +async function takenByCoinosUser(domain, name, claimantPubkey = null) { if (domain !== 'coinos.io') return false; try { const r = await fetch(`https://coinos.io/api/users/${encodeURIComponent(name)}`); if (r.status !== 200) return false; - // A migrated account has handed its name over: the old site keeps the - // account and its history, but receiving belongs to us now. const u = await r.json().catch(() => null); - return !(u && u.migrated); + if (!u) return false; + // An existing coinos.io account owns its name. The `migrated` flag once + // gated this and proved meaningless (poppy got squatted through it) — + // identity is the proof: only a claim SIGNED by the old account's own + // nostr key may take the name over. + return !(u.npub && claimantPubkey && u.npub === npubEncode(claimantPubkey)); } catch { return true; } // can't verify → refuse rather than squat } @@ -1044,7 +1047,7 @@ Bun.serve({ if (existing && existing.pubkey !== auth.pubkey && existing.manager !== auth.pubkey) { return json({ error: 'name is taken' }, 409); } - if (!existing && await takenByCoinosUser(domain, name)) return json({ error: 'name is taken' }, 409); + if (!existing && await takenByCoinosUser(domain, name, auth.pubkey)) return json({ error: 'name is taken' }, 409); // an npub-shaped name belongs to that identity alone if (npubPrefixOwner(name)) { const managerOk = existing && existing.manager === auth.pubkey; |
