diff --git a/apps/desktop/extensions/ai-sidebar/moshpit.js b/apps/desktop/extensions/ai-sidebar/moshpit.js index fda93cf..4dc3401 100644 --- a/apps/desktop/extensions/ai-sidebar/moshpit.js +++ b/apps/desktop/extensions/ai-sidebar/moshpit.js @@ -18,13 +18,23 @@ export const DEFAULT_CONSOLE_BASE = 'https://app.moshcode.sh'; // `mosh.eggs` and own the page people use to check who holds `.eggs`. export const CONSOLE_LABEL = 'mosh'; -// Where a name with no destination yet is parked. A name inside the namespace -// should never dead-end on ERR_NAME_NOT_RESOLVED. -export const DEFAULT_PARKING_BASE = 'https://moshcoding.com'; +// Where a name with no destination yet is parked. +// +// The registry's own /n/, which is also where a *pointed* name is +// fetched — one route handles both, because "what is behind this name" and +// "there is nothing behind this name yet" are the same question with different +// answers. It shows what else lives under that ending and which endings are +// related, so an unclaimed name is a way into the namespace instead of a dead +// end. +// +// It was moshcoding.com/parking, which has never existed — that is the Next.js +// site, not the registry, and it has no such route. Every unpointed name +// 404'd, which is indistinguishable from the namespace not working. +export const DEFAULT_PARKING_BASE = 'https://pit.moshcode.sh'; /** The parking page for a name with no destination yet. */ export function parkingUrlFor(name, parkingBase = DEFAULT_PARKING_BASE) { - return `${parkingBase.replace(/\/+$/, '')}/parking?name=${encodeURIComponent(name)}`; + return `${parkingBase.replace(/\/+$/, '')}/n/${encodeURIComponent(name)}`; } /** diff --git a/apps/desktop/extensions/ai-sidebar/moshpit.test.js b/apps/desktop/extensions/ai-sidebar/moshpit.test.js index 1aa3c09..3481b7c 100644 --- a/apps/desktop/extensions/ai-sidebar/moshpit.test.js +++ b/apps/desktop/extensions/ai-sidebar/moshpit.test.js @@ -138,7 +138,7 @@ describe('destinationFor — parking', () => { globalThis.chrome = { storage: { local: { get: async () => ({ moshpitConfig: { mode: 'clearnet' } }) } } }; globalThis.fetch = async () => ({ ok: true, json: async () => ({ name_registered: false, target: null }) }); expect(await js.destinationFor('california.oranges', false)).toBe( - 'https://moshcoding.com/parking?name=california.oranges', + 'https://pit.moshcode.sh/n/california.oranges', ); }); @@ -168,7 +168,7 @@ describe('lookupMoshpit — the registry payload as it really is', () => { prefer: 'fallback', }); expect(await js.destinationFor('california.oranges', false)).toBe( - 'https://moshcoding.com/parking?name=california.oranges', + 'https://pit.moshcode.sh/n/california.oranges', ); }); @@ -232,3 +232,31 @@ describe('the lookup budget', () => { expect(js.DEFAULT_LOOKUP_TIMEOUT_MS).toBeLessThanOrEqual(10000); }); }); + +describe('parking sends a name somewhere that exists', () => { + it('parks at the registry, not at a route nobody ever built', () => { + // moshcoding.com/parking has never existed — that is the Next.js site, not + // the registry. Every unpointed name 404'd, which from a browser is + // indistinguishable from the namespace not working at all. + expect(js.parkingUrlFor('scrambled.eggs')).toBe('https://pit.moshcode.sh/n/scrambled.eggs'); + expect(js.DEFAULT_PARKING_BASE).toBe('https://pit.moshcode.sh'); + }); + + it('agrees with the TS source of truth', () => { + expect(js.parkingUrlFor('scrambled.eggs')).toBe(ts.parkingUrlFor('scrambled.eggs')); + expect(js.DEFAULT_PARKING_BASE).toBe(ts.DEFAULT_PARKING_BASE); + }); + + it('parks and fetches at the same route, because it is the same question', () => { + // /n/ serves a pointed name and shows the directory for an unpointed one. + expect(js.parkingUrlFor('a.eggs')).toBe(js.gatewayUrlFor('a.eggs')); + }); + + it('still honours a self-hosted parking base', () => { + expect(js.parkingUrlFor('a.eggs', 'https://my.pit/')).toBe('https://my.pit/n/a.eggs'); + }); + + it('escapes the name rather than pasting it into a URL', () => { + expect(js.parkingUrlFor('a b.eggs')).toBe('https://pit.moshcode.sh/n/a%20b.eggs'); + }); +}); diff --git a/apps/desktop/src/moshpit-resolve.test.ts b/apps/desktop/src/moshpit-resolve.test.ts index 51365f5..8177e96 100644 --- a/apps/desktop/src/moshpit-resolve.test.ts +++ b/apps/desktop/src/moshpit-resolve.test.ts @@ -261,7 +261,7 @@ describe('decideResolution — parking unpointed names', () => { moshpit: unregistered, }); expect(d.use).toBe('park'); - expect(d.url).toBe('https://moshcoding.com/parking?name=california.oranges'); + expect(d.url).toBe('https://pit.moshcode.sh/n/california.oranges'); }); it('parks a claimed name that is not pointed at an address yet', () => { @@ -304,6 +304,6 @@ describe('decideResolution — parking unpointed names', () => { moshpit: unregistered, parkingBase: 'https://my.park/', }); - expect(d.url).toBe('https://my.park/parking?name=california.oranges'); + expect(d.url).toBe('https://my.park/n/california.oranges'); }); }); diff --git a/apps/desktop/src/moshpit-resolve.ts b/apps/desktop/src/moshpit-resolve.ts index 6768994..9041097 100644 --- a/apps/desktop/src/moshpit-resolve.ts +++ b/apps/desktop/src/moshpit-resolve.ts @@ -66,14 +66,14 @@ export const CONSOLE_LABEL = 'mosh'; * at an IP, and "this name is unclaimed / unpointed, here's how to take it" is * a far more useful answer than ERR_NAME_NOT_RESOLVED. */ -export const DEFAULT_PARKING_BASE = 'https://moshcoding.com'; +export const DEFAULT_PARKING_BASE = 'https://pit.moshcode.sh'; /** The parking page for a name with no destination yet. */ export function parkingUrlFor( name: string, parkingBase: string = DEFAULT_PARKING_BASE, ): string { - return `${parkingBase.replace(/\/+$/, '')}/parking?name=${encodeURIComponent(name)}`; + return `${parkingBase.replace(/\/+$/, '')}/n/${encodeURIComponent(name)}`; } export interface MoshpitLookup {