From e4ad27e6eeabc9b2521f96dd6cfc965752cbcea0 Mon Sep 17 00:00:00 2001 From: Sota Date: Tue, 1 Sep 2026 18:02:10 -0700 Subject: [PATCH] fix(deploy): retire the removed RoomDO namespace Keep hosted deployment history explicit while allowing fresh self-hosted relays to omit namespaces they never provisioned. Closes #454. Co-authored-by: Cursor --- apps/relay/test/self-host-config.test.ts | 13 ++++++++++++- apps/relay/wrangler.jsonc | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/relay/test/self-host-config.test.ts b/apps/relay/test/self-host-config.test.ts index 70599546..5629c52b 100644 --- a/apps/relay/test/self-host-config.test.ts +++ b/apps/relay/test/self-host-config.test.ts @@ -5,6 +5,12 @@ const readJsonc = (raw: string) => JSON.parse( raw.replace(/^\s*\/\/.*$/gm, ""), ); +function liveExports(exports: Record): Record { + return Object.fromEntries( + Object.entries(exports).filter(([, value]) => value.state !== "deleted"), + ); +} + function normalizedRuntimeConfig(input: any): any { const config = structuredClone(input); // The official hosted relay also serves the AgentCall product site. A @@ -21,6 +27,9 @@ function normalizedRuntimeConfig(input: any): any { } for (const dataset of config.analytics_engine_datasets ?? []) dataset.dataset = ""; for (const rateLimit of config.ratelimits ?? []) rateLimit.namespace_id = ""; + // Hosted deletion tombstones retire namespaces provisioned by earlier + // releases. A fresh self-hosted account never owned those namespaces. + if (config.exports) config.exports = liveExports(config.exports); return config; } @@ -38,9 +47,11 @@ describe("self-host Wrangler distribution", () => { d1_databases: [{ binding: "DB", migrations_dir: "migrations" }], analytics_engine_datasets: [{ binding: "STATUS_READS" }], durable_objects: hosted.durable_objects, - exports: hosted.exports, + exports: liveExports(hosted.exports), routes: [{ pattern: "relay.example.com", custom_domain: true }], }); + expect(hosted.exports.RoomDO).toEqual({ type: "durable-object", state: "deleted" }); + expect(selfHosted.exports).not.toHaveProperty("RoomDO"); expect(hosted.assets).toEqual({ directory: "../landing", binding: "ASSETS", diff --git a/apps/relay/wrangler.jsonc b/apps/relay/wrangler.jsonc index 6a864215..3bc67238 100644 --- a/apps/relay/wrangler.jsonc +++ b/apps/relay/wrangler.jsonc @@ -44,6 +44,7 @@ ] }, "exports": { "HandleDO": { "type": "durable-object", "storage": "sqlite" }, + "RoomDO": { "type": "durable-object", "state": "deleted" }, "RateLimiterDO": { "type": "durable-object", "storage": "sqlite" } }, // Must stay in step with HOSTED_RELAY_HOST (packages/shared/src/protocol.ts),