// Row 285 amendment 1 (#1790, mos-1580, sage-4059): a chief references gitea // exactly when this business declares a library. The Case 1 source stays unchanged. import { test } from 'node:test'; import assert from 'node:assert/strict'; import { mkdtempSync, readFileSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { BusinessError, validateBusinessDocument } from '../src/index.mjs'; import { mappingEntry } from '../../library/tests/helpers.mjs'; const ROLES = fileURLToPath(new URL('../../../roles/', import.meta.url)); const CASE1 = new URL('../../../docs/guides/case1-business.mosaic-stack.json', import.meta.url); const GITEA = { gitea: { store: true, rotateBy: '2099-01-01' } }; function fixture(t) { const root = mkdtempSync(join(tmpdir(), 'chief-library-')); t.after(() => rmSync(root, { recursive: true, force: true })); const doc = JSON.parse(readFileSync(CASE1, 'utf8')); const validate = () => validateBusinessDocument(doc, join(root, 'businesses/mosaic-stack.json'), { rolesDir: ROLES }); return { doc, validate }; } // Removing the library condition makes this successful Case 1 load fail. test('row 285 amendment 1: no library loads with empty chief credentials', t => { const { doc, validate } = fixture(t); doc.roles.chief.credentials = {}; const business = validate(); assert.deepEqual(business.roles.chief.credentials, {}); assert.deepEqual(business.roles.assistant.credentials, {}); }); // Dropping the required-reference refusal makes the missing-reference assertion fail. test('row 285 amendment 1: a library without chief gitea refuses by name', t => { const { doc, validate } = fixture(t); doc.projects.books = mappingEntry(); assert.throws(validate, error => error instanceof BusinessError && error.exitCode === 2 && /chief-library-gitea-required: .*roles\.chief\.credentials/.test(error.message)); doc.roles.chief.credentials = structuredClone(GITEA); assert.deepEqual(Object.keys(validate().roles.chief.credentials), ['gitea']); }); // Letting the chief keep unused gitea, or weakening exact-match globally, breaks this refusal. test('row 285 amendment 1: no library with chief gitea refuses the extra reference', t => { const { doc, validate } = fixture(t); doc.roles.chief.credentials = structuredClone(GITEA); assert.throws(validate, error => error instanceof BusinessError && error.exitCode === 2 && /roles\.chief\.credentials must reference exactly the services its role definition needs \(none; got gitea\)/.test(error.message)); delete doc.roles.chief.credentials; doc.roles.assistant.credentials = structuredClone(GITEA); assert.throws(validate, error => error instanceof BusinessError && error.exitCode === 2 && /roles\.assistant\.credentials must reference exactly the services its role definition needs \(none; got gitea\)/.test(error.message)); });