import { test } from 'node:test'; import assert from 'node:assert/strict'; import { mkdtempSync, rmSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { consoleReads } from '../src/reads.mjs'; import { recordBootRefused, recordBootOk } from '../../cli/src/boot-status.mjs'; import { createOrg, templateRender, showOrg, archiveOrg } from '../../organization/src/org-service.mjs'; import { busStopForDelete } from '../../cli/src/org-bus.mjs'; import { listOrgs, resolveOrg } from '../../organization/src/org-registry.mjs'; import { organizationConsole } from '../src/organizations.mjs'; test('admission errors are visible while a healthy organization remains usable', async t => { const root = mkdtempSync(join(tmpdir(), 'org-admission-')); t.after(() => rmSync(root, { recursive: true, force: true })); const configDir = join(root, 'config'), dataRoot = join(root, 'data'); mkdirSync(configDir, { mode: 0o700 }); mkdirSync(dataRoot, { mode: 0o700 }); const principal = { provider: 'local-dev', iss: 'local-dev', sub: 'local-dev-owner' }; const ctx = { configDir, dataRoot, instance: 'readtest', principal }; for (const id of ['alpha', 'beta']) await createOrg(ctx, id, await templateRender(id)); const file = join(configDir, 'org-runtime.json'), registry = JSON.parse(readFileSync(file, 'utf8')); registry.orgs.alpha.digest = '0'.repeat(64); writeFileSync(file, JSON.stringify(registry)); const console = organizationConsole({ ctx, listOrgs, showOrg, resolveOrg, orgPaths: () => ({}), busStatus: async () => ({ healthy: true }), options: ({ id }) => ({ id }) }); const rows = await console.list(principal); assert.equal(rows.find(row => row.id === 'alpha')?.invalid, true); assert.match(rows.find(row => row.id === 'alpha')?.reason, /document and registry disagree/); assert.equal((await console.resolve('beta', principal)).id, 'beta'); }); test('an owner whose only organization is archived gets an empty list, not an error', async t => { const root = mkdtempSync(join(tmpdir(), 'org-archived-')); t.after(() => rmSync(root, { recursive: true, force: true })); const configDir = join(root, 'config'), dataRoot = join(root, 'data'); mkdirSync(configDir, { mode: 0o700 }); mkdirSync(dataRoot, { mode: 0o700 }); const principal = { provider: 'local-dev', iss: 'local-dev', sub: 'local-dev-owner' }; const ctx = { configDir, dataRoot, instance: 'readtest', principal }; await createOrg(ctx, 'alpha', await templateRender('alpha')); const { revision } = await showOrg(ctx, 'alpha'); await archiveOrg(ctx, 'alpha', { ifRevision: revision, busStop: busStopForDelete }); const console = organizationConsole({ ctx, listOrgs, showOrg, resolveOrg, orgPaths: () => ({}), busStatus: async () => ({ healthy: true }), options: ({ id }) => ({ id }) }); assert.deepEqual(await console.list(principal), []); }); test('offline boot status comes from the selected organization root', async t => { const root = mkdtempSync(join(tmpdir(), 'org-reads-')); t.after(() => rmSync(root, { recursive: true, force: true })); const alpha = join(root, 'alpha'), beta = join(root, 'beta'); recordBootOk(alpha, { business: 'alpha', file: 'alpha.json' }); recordBootRefused(beta, { business: 'beta', file: 'beta.json', reason: 'bad config' }); const reads = orgRoot => consoleReads({ root, system: { dataRoot: root }, orgRoot, business: 'alpha' }); assert.equal((await reads(alpha).busStatus()).boot.business, 'alpha'); assert.equal((await reads(beta).busStatus()).boot.business, 'beta'); }); test('settings reads the notifier choice created under the selected organization root', async t => { const root = mkdtempSync(join(tmpdir(), 'org-reads-')); t.after(() => rmSync(root, { recursive: true, force: true })); const configDir = join(root, 'config'), dataRoot = join(root, 'data'); mkdirSync(configDir, { mode: 0o700 }); mkdirSync(dataRoot, { mode: 0o700 }); const ctx = { configDir, dataRoot, instance: 'readtest', principal: { provider: 'local-dev', iss: 'local-dev', sub: 'local-dev-owner' } }; const created = await createOrg(ctx, 'alpha', await templateRender('alpha')); const reads = consoleReads({ root, configDir, system: { dataRoot }, orgRoot: created.root, business: 'alpha' }); assert.deepEqual((await reads.settings()).notifier, { binding: null }); });