From 2d1d14ff696441546d9fb7eefd7909e327a9d93e Mon Sep 17 00:00:00 2001 From: "nekomimi.pet" Date: Sat, 3 Oct 2026 11:55:45 -0400 Subject: [PATCH] fix: restore the agreed preview.wisp.place hostname --- .../src/lib/preview-host.test.ts | 36 +++++++++---------- .../src/server-preview.test.ts | 12 +++---- apps/preview-bot/src/comment.test.ts | 10 +++--- apps/preview-bot/src/config.test.ts | 13 ++++--- apps/preview-bot/src/handler.test.ts | 8 ++--- apps/preview-bot/src/verify.test.ts | 6 ++-- cli-rs/crates/wispctl/src/commands/deploy.rs | 4 +-- .../content/docs/guides/preview-deploys.md | 4 +-- 8 files changed, 50 insertions(+), 43 deletions(-) diff --git a/apps/hosting-service/src/lib/preview-host.test.ts b/apps/hosting-service/src/lib/preview-host.test.ts index 0a22987..d9eccc3 100644 --- a/apps/hosting-service/src/lib/preview-host.test.ts +++ b/apps/hosting-service/src/lib/preview-host.test.ts @@ -1,37 +1,37 @@ import { describe, expect, test } from 'bun:test' import { isPreviewHostname, parsePreviewHostname } from './preview-host' -const PREVIEW = 'wispsites.dev' +const PREVIEW = 'preview.wisp.place' describe('parsePreviewHostname', () => { test('splits the rkey and the owner claim', () => { - expect(parsePreviewHostname('pr-ab12cd3-yummers.wispsites.dev', PREVIEW)).toEqual({ + expect(parsePreviewHostname('pr-ab12cd3-yummers.preview.wisp.place', PREVIEW)).toEqual({ rkey: 'pr-ab12cd3', claim: 'yummers', }) }) test('keeps hyphenated claims intact', () => { - expect(parsePreviewHostname('pr-ab12cd3-my-site.wispsites.dev', PREVIEW)).toEqual({ + expect(parsePreviewHostname('pr-ab12cd3-my-site.preview.wisp.place', PREVIEW)).toEqual({ rkey: 'pr-ab12cd3', claim: 'my-site', }) }) test.each([ - ['apex', 'wispsites.dev'], + ['apex', 'preview.wisp.place'], ['other domain', 'pr-ab12cd3-yummers.example.com'], - ['lookalike suffix', 'pr-ab12cd3-yummers.evilwispsites.dev'], - ['nested host', 'x.pr-ab12cd3-yummers.wispsites.dev'], - ['no pr prefix', 'ab12cd3-yummers.wispsites.dev'], - ['no claim', 'pr-ab12cd3.wispsites.dev'], - ['empty claim', 'pr-ab12cd3-.wispsites.dev'], - ['short sha', 'pr-ab12cd-yummers.wispsites.dev'], - ['long sha', 'pr-ab12cd3e-yummers.wispsites.dev'], - ['non-hex sha', 'pr-ab12cdg-yummers.wispsites.dev'], - ['uppercase sha', 'pr-AB12CD3-yummers.wispsites.dev'], - ['double hyphen before claim', 'pr-ab12cd3--yummers.wispsites.dev'], - ['label over 63 chars', `pr-ab12cd3-${'a'.repeat(60)}.wispsites.dev`], + ['lookalike suffix', 'pr-ab12cd3-yummers.evilpreview.wisp.place'], + ['nested host', 'x.pr-ab12cd3-yummers.preview.wisp.place'], + ['no pr prefix', 'ab12cd3-yummers.preview.wisp.place'], + ['no claim', 'pr-ab12cd3.preview.wisp.place'], + ['empty claim', 'pr-ab12cd3-.preview.wisp.place'], + ['short sha', 'pr-ab12cd-yummers.preview.wisp.place'], + ['long sha', 'pr-ab12cd3e-yummers.preview.wisp.place'], + ['non-hex sha', 'pr-ab12cdg-yummers.preview.wisp.place'], + ['uppercase sha', 'pr-AB12CD3-yummers.preview.wisp.place'], + ['double hyphen before claim', 'pr-ab12cd3--yummers.preview.wisp.place'], + ['label over 63 chars', `pr-ab12cd3-${'a'.repeat(60)}.preview.wisp.place`], ])('rejects %s', (_name, host) => { expect(parsePreviewHostname(host, PREVIEW)).toBeNull() }) @@ -39,9 +39,9 @@ describe('parsePreviewHostname', () => { describe('isPreviewHostname', () => { test('covers the apex and everything beneath it only', () => { - expect(isPreviewHostname('wispsites.dev', PREVIEW)).toBe(true) - expect(isPreviewHostname('anything.wispsites.dev', PREVIEW)).toBe(true) - expect(isPreviewHostname('evilwispsites.dev', PREVIEW)).toBe(false) + expect(isPreviewHostname('preview.wisp.place', PREVIEW)).toBe(true) + expect(isPreviewHostname('anything.preview.wisp.place', PREVIEW)).toBe(true) + expect(isPreviewHostname('evilpreview.wisp.place', PREVIEW)).toBe(false) expect(isPreviewHostname('wisp.place', PREVIEW)).toBe(false) }) }) diff --git a/apps/hosting-service/src/server-preview.test.ts b/apps/hosting-service/src/server-preview.test.ts index a105f66..fbba7ae 100644 --- a/apps/hosting-service/src/server-preview.test.ts +++ b/apps/hosting-service/src/server-preview.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, mock, test } from 'bun:test' process.env.BASE_HOST = 'wisp.place' -process.env.PREVIEW_HOST = 'wispsites.dev' +process.env.PREVIEW_HOST = 'preview.wisp.place' const OWNER_DID = 'did:plc:alice' const domainLookups: string[] = [] @@ -35,7 +35,7 @@ describe('preview host routing', () => { }) test("serves the pr site from the claim owner, ignoring the claim's mapped site", async () => { - const response = await app.request('https://pr-ab12cd3-alice.wispsites.dev/docs/index.html') + const response = await app.request('https://pr-ab12cd3-alice.preview.wisp.place/docs/index.html') expect(response.status).toBe(200) expect(await response.text()).toBe('preview body') @@ -44,16 +44,16 @@ describe('preview host routing', () => { }) test('404s an unregistered claim', async () => { - const response = await app.request('https://pr-ab12cd3-nobody.wispsites.dev/') + const response = await app.request('https://pr-ab12cd3-nobody.preview.wisp.place/') expect(response.status).toBe(404) expect(served).toEqual([]) }) test.each([ - 'https://wispsites.dev/', - 'https://main-alice.wispsites.dev/', - 'https://x.pr-ab12cd3-alice.wispsites.dev/', + 'https://preview.wisp.place/', + 'https://main-alice.preview.wisp.place/', + 'https://x.pr-ab12cd3-alice.preview.wisp.place/', ])('404s %s without a database lookup', async (url) => { const response = await app.request(url) diff --git a/apps/preview-bot/src/comment.test.ts b/apps/preview-bot/src/comment.test.ts index 7e763a7..5296946 100644 --- a/apps/preview-bot/src/comment.test.ts +++ b/apps/preview-bot/src/comment.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from 'bun:test' import { MAX_PREVIEW_ROWS, parsePreviewRows, renderComment } from './comment' -const row = (sha7: string, host = 'wispsites.dev') => ({ sha7, url: `https://pr-${sha7}-alice.${host}/` }) +const row = (sha7: string, host = 'preview.wisp.place') => ({ sha7, url: `https://pr-${sha7}-alice.${host}/` }) describe('renderComment', () => { test('lists the newest preview first and links it', () => { @@ -9,7 +9,9 @@ describe('renderComment', () => { const lines = body.split('\n') expect(lines.findIndex((l) => l.includes('aaaaaaa'))).toBeLessThan(lines.findIndex((l) => l.includes('bbbbbbb'))) - expect(body).toContain('[https://pr-aaaaaaa-alice.wispsites.dev/](https://pr-aaaaaaa-alice.wispsites.dev/)') + expect(body).toContain( + '[https://pr-aaaaaaa-alice.preview.wisp.place/](https://pr-aaaaaaa-alice.preview.wisp.place/)', + ) expect(body).toContain('`aaaaaaa`') }) @@ -36,10 +38,10 @@ describe('parsePreviewRows', () => { 'someone edited this', '| `abc` | [x](javascript:alert(1)) |', '| `ddddddd` | [https://evil.example/](https://evil.example/) |', - '| `eeeeeee` | [https://pr-eeeeeee-alice.wispsites.dev/](https://pr-eeeeeee-alice.wispsites.dev/) |', + '| `eeeeeee` | [https://pr-eeeeeee-alice.preview.wisp.place/](https://pr-eeeeeee-alice.preview.wisp.place/) |', ].join('\n') - expect(parsePreviewRows(body, 'wispsites.dev')).toEqual([row('eeeeeee')]) + expect(parsePreviewRows(body, 'preview.wisp.place')).toEqual([row('eeeeeee')]) }) test('treats an empty or foreign body as no rows', () => { diff --git a/apps/preview-bot/src/config.test.ts b/apps/preview-bot/src/config.test.ts index a85c7b8..bd9b8c8 100644 --- a/apps/preview-bot/src/config.test.ts +++ b/apps/preview-bot/src/config.test.ts @@ -5,7 +5,7 @@ const valid = { BOT_HANDLE: 'wisp.place', BOT_PASSWORD: 'app-password-secret', DATABASE_URL: 'postgres://postgres:postgres@localhost:5432/wisp', - PREVIEW_HOST: 'wispsites.dev', + PREVIEW_HOST: 'preview.wisp.place', } describe('resolveConfig', () => { @@ -15,15 +15,20 @@ describe('resolveConfig', () => { expect(config.botHandle).toBe('wisp.place') expect(config.botPassword).toBe('app-password-secret') expect(config.databaseUrl).toBe('postgres://postgres:postgres@localhost:5432/wisp') - expect(config.previewHost).toBe('wispsites.dev') + expect(config.previewHost).toBe('preview.wisp.place') expect(config.baseHost).toBe('wisp.place') expect(config.port).toBe(3004) }) test('lowercases hosts and trims port', () => { - const config = resolveConfig({ ...valid, PREVIEW_HOST: 'WispSites.Dev', BASE_HOST: 'Wisp.Place', PORT: ' 8080 ' }) + const config = resolveConfig({ + ...valid, + PREVIEW_HOST: 'Preview.Wisp.Place', + BASE_HOST: 'Wisp.Place', + PORT: ' 8080 ', + }) - expect(config.previewHost).toBe('wispsites.dev') + expect(config.previewHost).toBe('preview.wisp.place') expect(config.baseHost).toBe('wisp.place') expect(config.port).toBe(8080) }) diff --git a/apps/preview-bot/src/handler.test.ts b/apps/preview-bot/src/handler.test.ts index c9cad94..e51329f 100644 --- a/apps/preview-bot/src/handler.test.ts +++ b/apps/preview-bot/src/handler.test.ts @@ -61,7 +61,7 @@ function world(overrides: Partial = {}): World { function handlerFor(w: World, limits = { capacity: 100 }) { return createHandler({ ports: w.ports, - config: { previewHost: 'wispsites.dev' }, + config: { previewHost: 'preview.wisp.place' }, clientKey: () => 'client', perClient: createRateLimiter({ capacity: limits.capacity, refillPerSecond: 0.0001 }), perOwner: createRateLimiter({ capacity: limits.capacity, refillPerSecond: 0.0001 }), @@ -84,10 +84,10 @@ describe('POST /v1/preview', () => { const response = await handlerFor(w)(post(body)) expect(response.status).toBe(200) - expect(await response.json()).toEqual({ status: 'created', url: 'https://pr-ab12cd3-alice.wispsites.dev/' }) + expect(await response.json()).toEqual({ status: 'created', url: 'https://pr-ab12cd3-alice.preview.wisp.place/' }) expect(w.creates).toHaveLength(1) expect(w.creates[0]).toMatchObject({ pull: { uri: PULL_URI, cid: 'bafypull' }, roundIdx: 0 }) - expect(w.creates[0]?.body).toContain('https://pr-ab12cd3-alice.wispsites.dev/') + expect(w.creates[0]?.body).toContain('https://pr-ab12cd3-alice.preview.wisp.place/') }) test('a new commit updates the same comment and keeps the earlier previews', async () => { @@ -211,7 +211,7 @@ describe('rate limits', () => { const w = world() const handle = createHandler({ ports: w.ports, - config: { previewHost: 'wispsites.dev' }, + config: { previewHost: 'preview.wisp.place' }, clientKey: (() => { let n = 0 return () => `client-${n++}` diff --git a/apps/preview-bot/src/verify.test.ts b/apps/preview-bot/src/verify.test.ts index 6cfdf24..315fdda 100644 --- a/apps/preview-bot/src/verify.test.ts +++ b/apps/preview-bot/src/verify.test.ts @@ -47,7 +47,7 @@ function fakePorts(overrides: Partial = {}): { ports: Ports; calls: Calls return { ports, calls } } -const config = { previewHost: 'wispsites.dev' } +const config = { previewHost: 'preview.wisp.place' } describe('verifyPreview', () => { test('accepts a preview whose every link is anchored in an authority the owner controls', async () => { @@ -57,13 +57,13 @@ describe('verifyPreview', () => { expect(result).toEqual({ ok: true, - url: 'https://pr-ab12cd3-alice.wispsites.dev/', + url: 'https://pr-ab12cd3-alice.preview.wisp.place/', sha7: 'ab12cd3', pull: { uri: PULL_URI, cid: 'bafypull' }, roundIdx: 2, }) expect(calls.pipelines).toEqual([['spindle.example', '3kpipeline']]) - expect(calls.probes).toEqual(['https://pr-ab12cd3-alice.wispsites.dev/']) + expect(calls.probes).toEqual(['https://pr-ab12cd3-alice.preview.wisp.place/']) }) test("asks the spindle named in the owner's repo record, never one the request names", async () => { diff --git a/cli-rs/crates/wispctl/src/commands/deploy.rs b/cli-rs/crates/wispctl/src/commands/deploy.rs index 3a66f34..32025c8 100644 --- a/cli-rs/crates/wispctl/src/commands/deploy.rs +++ b/cli-rs/crates/wispctl/src/commands/deploy.rs @@ -597,8 +597,8 @@ mod preview_tests { #[test] fn preview_urls_validate_and_normalize() { assert_eq!( - build_preview_url("pr-abcdef0", "alice", "WispSites.Dev").unwrap(), - "https://pr-abcdef0-alice.wispsites.dev/" + build_preview_url("pr-abcdef0", "alice", "Preview.Wisp.Place").unwrap(), + "https://pr-abcdef0-alice.preview.wisp.place/" ); assert_eq!( build_preview_url("pr-ABCDEF0", "alice", "example.com") diff --git a/docs/src/content/docs/guides/preview-deploys.md b/docs/src/content/docs/guides/preview-deploys.md index cb1675c..9970615 100644 --- a/docs/src/content/docs/guides/preview-deploys.md +++ b/docs/src/content/docs/guides/preview-deploys.md @@ -9,7 +9,7 @@ A preview deploy publishes a pull request's build as a site in **your own PDS**, - Each pull request round deploys a site named `pr-`, where `` is the first seven characters of the pull request's head commit. - The hosting service serves it at `https://pr--./`. `` is a wisp subdomain you already claimed (the `alice` in `alice.wisp.place`). Without the claim, nothing in the host would say whose site it is, and anyone could write the same site name into their own repo and answer for someone else's commit. -- The preview host is a separate registrable domain from the one that serves production sites, so a preview's JavaScript cannot read the cookies or storage of any production site. Operators enable it by setting `PREVIEW_HOST` on the hosting service. It has no default, and unset means previews are off. +- Preview URLs use `pr--.preview.wisp.place`. Operators enable this routing with `PREVIEW_HOST=preview.wisp.place` on the hosting service and DNS/TLS for `*.preview.wisp.place`. The environment variable has no default; unset means previews are off. These are separate origins, not a separate registrable domain: cookies scoped to `.wisp.place` can also reach preview hosts. - Every preview carries `X-Robots-Tag: noindex`, set through the site's settings record. Because each round is a new commit, each round gets its own URL. Earlier rounds stay up, so you can compare them, until they are pruned. @@ -40,7 +40,7 @@ dependencies: environment: WISP_HANDLE: "alice.example.com" - PREVIEW_HOST: "your-preview-host.example" + PREVIEW_HOST: "preview.wisp.place" PREVIEW_CLAIM: "alice" steps: -- 2.54.0