// Generated, do not edit. sha256:f2303f8f896c78080d5d688ce3e2df97456f8a2894444e19e5c3457a31b7283d import { describe, it, before, beforeEach, mock } from 'node:test'; import assert from 'node:assert/strict'; import { createDbHarness } from '../helpers/db-node.mjs'; import { CONFIG, ENUMS } from '../../shared/config.js'; const harness = createDbHarness({ seedPreferences: true }); mock.module('../../server/db.js', { namedExports: harness.exports }); let licentieStand = { level: 'full', enforced: true, why: 'licensed' }; const echteLicentie = await import('../../server/license.mjs'); mock.module('../../server/license.mjs', { namedExports: { ...echteLicentie, hasFeature: (naam) => echteLicentie.hasFeature(naam, licentieStand) }, }); const { assertScope, mayScope, isAiEnabled, isAiWriteAllowed, isAiControlAllowed, isAiActive, AI_INACTIVE, AI_DISABLED, AI_WRITE_DENIED, AI_CONTROL_DENIED, AI_UNLICENSED, AI_REFUSALS } = await import('../../server/ai/gate.js'); const { setPref } = await import('../../server/data/preferences.js'); const zet = async (enabled, allowWrite, allowControl = false) => { await setPref('ai', 'allow_read', enabled ? 1 : 0); await setPref('ai', 'allow_write', allowWrite ? 1 : 0); await setPref('ai', 'allow_control', allowControl ? 1 : 0); }; before(() => { harness.recreate(); }); beforeEach(async () => { await zet(true, false, false); }); describe('scope-poort: de schuif "Actief" gaat vóór alles', () => { it('weigert ELKE scope, ook none, als de koppeling niet actief is', async () => { await setPref('ai', 'enabled', 0); try { for (const scope of ['none', 'read', 'write', 'control']) { assert.throws(() => assertScope(scope), e => e.code === AI_INACTIVE, `scope ${scope} hoort geweigerd te worden met de koppeling uit`); } assert.equal(isAiActive(), false); assert.equal(mayScope('none'), false); } finally { await setPref('ai', 'enabled', 1); } }); it('zegt iets ANDERS dan de leesschuif, want dat is een andere schuif', async () => { await setPref('ai', 'enabled', 0); let koppeling; try { assertScope('read'); } catch (e) { koppeling = e; } await setPref('ai', 'enabled', 1); await setPref('ai', 'allow_read', 0); let lezen; try { assertScope('read'); } catch (e) { lezen = e; } assert.notEqual(koppeling.code, lezen.code); assert.match(koppeling.message, /Actief/); assert.match(lezen.message, /niet lezen/i); }); }); describe('scope-poort: de standen', () => { it('laat scope none door zolang de koppeling actief is, ook met de drie rechten uit', async () => { await zet(false, false); assert.doesNotThrow(() => assertScope('none')); }); it('laat scope read door als de koppeling aan staat', () => { assert.doesNotThrow(() => assertScope('read')); }); it('weigert scope read als de koppeling uit staat', async () => { await zet(false, false); assert.throws(() => assertScope('read'), e => e.code === AI_DISABLED); }); it('weigert scope write standaard, ook al staat de koppeling aan', () => { assert.throws(() => assertScope('write'), e => e.code === AI_WRITE_DENIED); }); it('laat scope write door als het schrijfrecht aan staat', async () => { await zet(true, true); assert.doesNotThrow(() => assertScope('write')); }); it('laat scope write door terwijl LEZEN uit staat, want elke schuif gaat over zichzelf', async () => { await zet(false, true); assert.doesNotThrow(() => assertScope('write')); assert.throws(() => assertScope('read'), e => e.code === AI_DISABLED); }); it('weigert scope control standaard, ook al staat de koppeling aan', () => { assert.throws(() => assertScope('control'), e => e.code === AI_CONTROL_DENIED); }); it('laat scope control door als het besturen aan staat', async () => { await zet(true, false, true); assert.doesNotThrow(() => assertScope('control')); assert.equal(isAiControlAllowed(), true); }); it('laat scope control door terwijl lezen uit staat, om dezelfde reden als bij schrijven', async () => { await zet(false, false, true); assert.doesNotThrow(() => assertScope('control')); assert.throws(() => assertScope('read'), e => e.code === AI_DISABLED); }); it('houdt besturen en schrijven uit elkaar', () => { assert.equal(isAiWriteAllowed(), false); assert.equal(isAiControlAllowed(), false); }); it('weigert een onbekende scope', () => { for (const raar of ['lezen', 'READ', '', null, undefined, 'admin']) { assert.throws(() => assertScope(raar), e => AI_REFUSALS.includes(e.code), `scope ${JSON.stringify(raar)} werd doorgelaten`); } }); }); describe('scope-poort: de melding die het model leest', () => { it('zegt bij een geweigerde schrijfactie iets anders dan bij een uitgezette koppeling', async () => { let schrijf; try { assertScope('write'); } catch (e) { schrijf = e; } await zet(false, false); let lees; try { assertScope('read'); } catch (e) { lees = e; } assert.notEqual(schrijf.code, lees.code); assert.notEqual(schrijf.message, lees.message); assert.match(schrijf.message, /niets gewijzigd/i); }); it('telt elke weigering als "bewust niet uitgevoerd"', () => { assert.deepEqual([...AI_REFUSALS].sort(), [AI_UNLICENSED, AI_INACTIVE, AI_DISABLED, AI_WRITE_DENIED, AI_CONTROL_DENIED].sort()); }); }); describe('scope-poort: bij twijfel dicht', () => { it('zegt nee als de voorkeur onleesbaar is', async () => { const origineel = harness.exports.all; harness.exports.all = () => { throw new Error('database weg'); }; try { assert.equal(isAiEnabled(), false); assert.equal(isAiWriteAllowed(), false); } finally { harness.exports.all = origineel; } }); }); describe('scope-poort: de SSOT', () => { it('kent precies de scopes uit de enum', () => { for (const scope of ENUMS.AI_SCOPE) { assert.doesNotThrow(() => { try { assertScope(scope); } catch (e) { if (!AI_REFUSALS.includes(e.code)) throw e; } }, `${scope} wordt niet herkend`); } }); }); describe('scope-poort: mayScope stelt dezelfde vraag zonder te gooien', () => { const standen = []; for (const enabled of [true, false]) { for (const write of [true, false]) { for (const control of [true, false]) standen.push([enabled, write, control]); } } it('geeft voor elke scope in elke stand hetzelfde oordeel als assertScope', async () => { for (const [enabled, write, control] of standen) { await zet(enabled, write, control); for (const scope of ENUMS.AI_SCOPE) { let gooide = false; try { assertScope(scope); } catch { gooide = true; } assert.equal(mayScope(scope), !gooide, `scope '${scope}' bij enabled=${enabled} write=${write} control=${control}`); } } }); it('weigert een onbekende scope, net als assertScope', () => { assert.equal(mayScope('admin'), false); assert.equal(mayScope(''), false); assert.equal(mayScope(undefined), false); }); it('laat none door, ook met alles uit', async () => { await zet(false, false, false); assert.equal(mayScope('none'), true); }); it('zegt nee tegen read zodra de koppeling uit staat', async () => { await zet(false, false, false); assert.equal(mayScope('read'), false); }); }); describe('scope-poort: de licentie gaat vóór de schuiven', () => { it('laat de koppeling toe in de gratis stand, want AI hoort daar sinds 27-10-2026 bij', () => { assert.equal(CONFIG.LICENSE.FREE.HAS.ai, true); licentieStand = { level: 'free', enforced: true, why: 'none' }; for (const scope of ['none', 'read']) { assert.doesNotThrow(() => assertScope(scope), `scope ${scope} hoort door de licentie te komen`); } licentieStand = { level: 'full', enforced: true, why: 'licensed' }; }); });