diff --git a/src/backend/drivers/subdomain/SubdomainDriver.edges.test.ts b/src/backend/drivers/subdomain/SubdomainDriver.edges.test.ts index ec75a8bfe..b1d45009b 100644 --- a/src/backend/drivers/subdomain/SubdomainDriver.edges.test.ts +++ b/src/backend/drivers/subdomain/SubdomainDriver.edges.test.ts @@ -573,6 +573,24 @@ describe('SubdomainDriver.update field handling', () => { expect(cleared.associated_app).toBeNull(); }); + it('disconnects the directory when root_dir is null', async () => { + const { actor } = await makeUser(); + const name = uniqueName('unlink'); + await createSubdomain(actor, name); + + // The shape `puter.hosting.update(name, null)` sends. + const updated = (await withActor(actor, () => + driver.update({ + id: { subdomain: name }, + object: { root_dir: null }, + }), + )) as Record; + + expect(updated.root_dir).toBeNull(); + const row = await server.stores.subdomain.getBySubdomain(name); + expect(row?.root_dir_id ?? null).toBeNull(); + }); + it('rejects repointing root_dir at a path that does not exist', async () => { const { actor } = await makeUser(); const created = await createSubdomain(actor, uniqueName('badroot')); diff --git a/src/backend/drivers/subdomain/SubdomainDriver.ts b/src/backend/drivers/subdomain/SubdomainDriver.ts index 9dafced69..82b2ef762 100644 --- a/src/backend/drivers/subdomain/SubdomainDriver.ts +++ b/src/backend/drivers/subdomain/SubdomainDriver.ts @@ -357,7 +357,10 @@ export class SubdomainDriver extends PuterDriver { // Subdomain name is immutable — strip if provided const patch: Record = {}; - if (object.root_dir !== undefined) { + // A null root_dir disconnects the directory; the site stays reserved. + if (object.root_dir === null) { + patch.root_dir_id = null; + } else if (object.root_dir !== undefined) { const rootDirPath = expandTildePath( String(object.root_dir), actor.user.username,