import test from 'brittle' import b4a from 'b4a' import Hyperdrive from 'hyperdrive' import Corestore from 'corestore' import { mkdirSync, rmSync } from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' import { createVfs } from './lib/vfs.js' import { createBareOsIpc } from './lib/bare-os-ipc.js' import { bareOsWwwInitdEnabled, bareOsWwwResolveStaticPath, BARE_OS_WWW_DEFAULT_INDEX, ensureBareOsWwwHomeDefaults, maybeRegisterBareOsWwwInitd, maybeRestartBareOsWwwAfterIdentity } from './lib/bare-os-www-initd.js' import { findBareServiceDefinition } from './lib/bare-initd.js' import { bareHolesailManagedStartService, bareHolesailManagedStopService, bareHolesailManagedPersistentSeedLooksValid, bareHolesailManagedReadState, bareHolesailManagedWriteState } from './lib/bare-holesail-managed.js' import { bareOsWwwHolesailConnectionId, ensureBareOsWwwHolesailTunnel } from './lib/bare-os-www-holesail.js' const __dirname = path.dirname(fileURLToPath(import.meta.url)) function testCorestoreDir(name) { const dir = path.join( __dirname, '.test-data', name + '-' + process.pid + '-' + Math.random().toString(36).slice(2) ) mkdirSync(path.dirname(dir), { recursive: true }) return dir } function testCtx(drive, personal, env = {}) { const shellEnv = { HOME: '/home/user', PATH: '/bin', USER: 'user', UID: '1000', GID: '1000', PWD: '/home/user', BARE_OS_EXIT_STATUS: '0', BARE_OS_SSH_LISTEN_PORT: '0', ...env } const bareOsIpc = createBareOsIpc() const vfs = createVfs(drive, personal, shellEnv, null, { bareOsIpc }) return { drive, personalDrive: personal, vfs, bareOsIpc, env: shellEnv, console, b4a, bareOsRegisterSuspendHook: () => {}, bareOsRegisterResumeHook: () => {} } } test('bareOsWwwInitdEnabled respects BARE_OS_WWW_INITD', (t) => { t.ok(bareOsWwwInitdEnabled({})) t.absent(bareOsWwwInitdEnabled({ BARE_OS_WWW_INITD: '0' })) t.absent(bareOsWwwInitdEnabled({ BARE_OS_WWW_INITD: 'false' })) }) test('bareOsWwwResolveStaticPath', (t) => { const d = '/home/user/.www' t.is(bareOsWwwResolveStaticPath(d, '/'), `${d}/index.html`) t.is(bareOsWwwResolveStaticPath(d, '/index.html'), `${d}/index.html`) t.is(bareOsWwwResolveStaticPath(d, '/a/b.css'), `${d}/a/b.css`) t.is(bareOsWwwResolveStaticPath(d, '/docs/'), `${d}/docs/index.html`) t.absent(bareOsWwwResolveStaticPath(d, '/../x')) }) test('vfs routes HOME/.www to HDMS www mount when present', async (t) => { const dir = testCorestoreDir('vfswww') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvwww')) const wwwDrive = new Hyperdrive(store.namespace('wwwalias')) await sys.ready() await personal.ready() await wwwDrive.ready() await wwwDrive.put('/hello.txt', b4a.from('from-www-drive')) const shellEnv = { HOME: '/home/user', USER: 'user', PATH: '/bin', PWD: '/home/user' } const mntRef = { getMounts: () => new Map([['www', { drive: wwwDrive, writable: true }]]) } const vfs = createVfs(sys, personal, shellEnv, mntRef, { bareOsIpc: createBareOsIpc() }) const r = vfs.route('/home/user/.www/hello.txt') t.is(r.drive, wwwDrive) t.is(r.path, '/hello.txt') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('bare-os-www service definition is registerable for configured port', async (t) => { const dir = testCorestoreDir('wwwsrv') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pwww')) await sys.ready() await personal.ready() const port = 19000 + Math.floor(Math.random() * 1000) const ctx = testCtx(sys, personal, { BARE_OS_WWW_PORT: String(port), BARE_OS_WWW_HOLESAIL: '0' }) maybeRegisterBareOsWwwInitd(ctx.env) const svc = findBareServiceDefinition('bare-os-www') t.ok(svc && typeof svc.start === 'function') t.ok(typeof /** @type {{ stop?: unknown }} */ (svc).stop === 'function') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('bare-os-www directory defaults can be prepared for redirectable subdir paths', async (t) => { const dir = testCorestoreDir('wwwsubdir') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('psub')) await sys.ready() await personal.ready() const port = 18000 + Math.floor(Math.random() * 500) const ctx = testCtx(sys, personal, { BARE_OS_WWW_PORT: String(port), BARE_OS_WWW_HOLESAIL: '0' }) await ctx.vfs.mkdir(ctx.vfs.resolveLogical('~/.www/test'), { recursive: true }) await ctx.vfs.writeFile( ctx.vfs.resolveLogical('~/.www/test/index.html'), b4a.from('SUBDIR_INDEX_BODY', 'utf8') ) maybeRegisterBareOsWwwInitd(ctx.env) const svc = findBareServiceDefinition('bare-os-www') t.ok(svc && typeof svc.start === 'function') const bodySlash = b4a.toString( await ctx.vfs.readFile(ctx.vfs.resolveLogical('~/.www/test/index.html')), 'utf8' ) t.is(String(bodySlash), 'SUBDIR_INDEX_BODY') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ensureBareOsWwwHolesailTunnel persists managed server entry', async (t) => { const dir = testCorestoreDir('wwwhs') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pwwhs')) await sys.ready() await personal.ready() const ctx = testCtx(sys, personal, { USER: 'guest', HOME: '/home/guest', UID: '65534', GID: '65534', PWD: '/home/guest' }) const p = 18188 const id = bareOsWwwHolesailConnectionId(p) const empty = { version: 1, connections: {} } await bareHolesailManagedWriteState( ctx, /** @type {Record} */ (ctx.env), empty ) await ensureBareOsWwwHolesailTunnel(ctx, ctx.env, p) const { state } = await bareHolesailManagedReadState( ctx, /** @type {Record} */ (ctx.env) ) const row = state.connections[id] t.ok(row && /** @type {{ server?: boolean }} */ (row).server === true) t.is(/** @type {{ port?: number }} */ (row).port, p) t.is(/** @type {{ host?: string }} */ (row).host, '127.0.0.1') const seedStr = /** @type {{ seed?: string }} */ (row).seed t.ok(seedStr && bareHolesailManagedPersistentSeedLooksValid(seedStr)) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ensureBareOsWwwHolesailTunnel preserves existing hs key when normalizing row', async (t) => { const dir = testCorestoreDir('wwwhskey') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pwwhsk')) await sys.ready() await personal.ready() const ctx = testCtx(sys, personal, { USER: 'guest', HOME: '/home/guest', UID: '65534', GID: '65534', PWD: '/home/guest' }) const p = 18189 const id = bareOsWwwHolesailConnectionId(p) const keepKey = 'hs://0000keepthiskey000000000000000000000000000000000000000000' await bareHolesailManagedWriteState( ctx, /** @type {Record} */ (ctx.env), { version: 1, connections: { [id]: { server: true, port: 19999, host: '0.0.0.0', enabled: true, key: keepKey } } } ) await ensureBareOsWwwHolesailTunnel(ctx, ctx.env, p) const { state } = await bareHolesailManagedReadState( ctx, /** @type {Record} */ (ctx.env) ) const row = /** @type {{ port?: number, host?: string, key?: string }} */ ( state.connections[id] ) t.is(row.port, p) t.is(row.host, '127.0.0.1') t.is(row.key, keepKey) const migratedSeed = /** @type {{ seed?: string }} */ (row).seed t.ok(migratedSeed && bareHolesailManagedPersistentSeedLooksValid(migratedSeed)) t.is( migratedSeed, 'keepthiskey000000000000000000000000000000000000000000'.toLowerCase() ) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ensureBareOsWwwHolesailTunnel reuses existing identity and prunes duplicate prefixed entries', async (t) => { const dir = testCorestoreDir('wwwhsdedupe') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pwwwdedupe')) await sys.ready() await personal.ready() const ctx = testCtx(sys, personal, { USER: 'guest', HOME: '/home/guest', UID: '65534', GID: '65534', PWD: '/home/guest' }) const keepId = bareOsWwwHolesailConnectionId(8088) const dropId = bareOsWwwHolesailConnectionId(18080) const keepKey = 'hs://0000keepidentity000000000000000000000000000000000000000000' await bareHolesailManagedWriteState( ctx, /** @type {Record} */ (ctx.env), { version: 1, connections: { [keepId]: { server: true, port: 8088, host: '127.0.0.1', enabled: true, key: keepKey }, [dropId]: { server: true, port: 18080, host: '127.0.0.1', enabled: true, seed: 'b'.repeat(64) } } } ) await ensureBareOsWwwHolesailTunnel(ctx, ctx.env, 19090) const { state } = await bareHolesailManagedReadState( ctx, /** @type {Record} */ (ctx.env) ) const rows = Object.values(state.connections || {}) const rowSafe = /** @type {{ port?: number, key?: string, seed?: string }} */ ( rows.find((r) => r && /** @type {{ key?: string }} */ (r).key === keepKey) || rows[0] || {} ) t.ok(rows.length >= 1) t.is(rowSafe.port, 19090) t.ok(rowSafe.seed && bareHolesailManagedPersistentSeedLooksValid(rowSafe.seed)) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ensureBareOsWwwHolesailTunnel restarts managed runtime when www port changes', async (t) => { const dir = testCorestoreDir('wwwhssync') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pwwwsync')) await sys.ready() await personal.ready() const ctx = testCtx(sys, personal, { USER: 'guest', HOME: '/home/guest', UID: '65534', GID: '65534', PWD: '/home/guest', BARE_OS_HOLESAIL_INITD: '1', BARE_OS_HOLESAIL_MANAGED: '1' }) const id = bareOsWwwHolesailConnectionId(8088) await bareHolesailManagedWriteState( ctx, /** @type {Record} */ (ctx.env), { version: 1, connections: { [id]: { server: true, port: 8088, host: '127.0.0.1', enabled: true, seed: 'd'.repeat(64) } } } ) await bareHolesailManagedStartService(ctx, ctx.env) await ensureBareOsWwwHolesailTunnel(ctx, ctx.env, 19090) const { state } = await bareHolesailManagedReadState( ctx, /** @type {Record} */ (ctx.env) ) const row = /** @type {{ port?: number }} */ (state.connections[id]) t.is(row.port, 19090) await bareHolesailManagedStopService(ctx) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('BARE_OS_WWW_DEFAULT_INDEX is non-trivial HTML', (t) => { t.ok(BARE_OS_WWW_DEFAULT_INDEX.includes('')) t.ok(BARE_OS_WWW_DEFAULT_INDEX.includes('Bare OS')) }) test('ensureBareOsWwwHomeDefaults creates ~/.www/index.html', async (t) => { const dir = testCorestoreDir('wwwdefaults') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pdef')) await sys.ready() await personal.ready() const ctx = testCtx(sys, personal) await ensureBareOsWwwHomeDefaults(ctx) const idx = ctx.vfs.resolveLogical('~/.www/index.html') const buf = await ctx.vfs.readFile(idx) t.ok(buf && buf.byteLength > 50) t.ok(b4a.toString(buf, 'utf8').includes('Bare OS')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('maybeRestartBareOsWwwAfterIdentity updates home-scoped defaults', async (t) => { const dir = testCorestoreDir('wwwrebind') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('prebind')) await sys.ready() await personal.ready() const port = 19500 + Math.floor(Math.random() * 800) const shellEnv = { HOME: '/home/alice', PATH: '/bin', USER: 'alice', UID: '1000', GID: '1000', PWD: '/home/alice', BARE_OS_EXIT_STATUS: '0', BARE_OS_SSH_LISTEN_PORT: '0', BARE_OS_WWW_PORT: String(port), BARE_OS_WWW_HOLESAIL: '0' } const bareOsIpc = createBareOsIpc() const vfs = createVfs(sys, personal, shellEnv, null, { bareOsIpc }) const ctx = { drive: sys, personalDrive: personal, vfs, bareOsIpc, env: shellEnv, console, b4a } await vfs.mkdir(vfs.resolveLogical('~/.www'), { recursive: true }) await vfs.writeFile( vfs.resolveLogical('~/.www/index.html'), b4a.from('ALICE', 'utf8') ) shellEnv.HOME = '/home/bob' shellEnv.USER = 'bob' shellEnv.PWD = '/home/bob' await vfs.mkdir(vfs.resolveLogical('~/.www'), { recursive: true }) await vfs.writeFile( vfs.resolveLogical('~/.www/index.html'), b4a.from('BOB', 'utf8') ) shellEnv.HOME = '/home/alice' shellEnv.USER = 'alice' shellEnv.PWD = '/home/alice' maybeRegisterBareOsWwwInitd(ctx.env) const svc = findBareServiceDefinition('bare-os-www') t.ok(svc && typeof svc.start === 'function') shellEnv.HOME = '/home/bob' shellEnv.USER = 'bob' shellEnv.PWD = '/home/bob' await maybeRestartBareOsWwwAfterIdentity(ctx) const bobText = b4a.toString( await vfs.readFile(vfs.resolveLogical('~/.www/index.html')), 'utf8' ) t.is(bobText, 'BOB') await store.close() rmSync(dir, { recursive: true, force: true }) })