import { describe, test, expect, beforeAll, afterAll } from 'bun:test'; import { setupFileRig, type FileTestRig } from '../integration/helpers/rig.js'; import { FingerprintRequiredError, NotFoundError, type FileEntry } from '../../src/index.js'; describe('Fingerprint gate', () => { let rig: FileTestRig; const verifiedSet = new Set(); beforeAll(async () => { verifiedSet.clear(); rig = await setupFileRig({ requireFingerprintVerifiedFor: (ctx) => { // Mutations require verification; reads are optional. const op = ctx.op; if (op === 'mkdir' || op === 'delete' || op === 'move' || op === 'write') return 'required'; if (op === 'list') return 'optional'; return 'optional'; }, isFingerprintVerified: (sender) => verifiedSet.has(sender), stat: async (ctx) => { const e: FileEntry = { name: ctx.path.split('/').filter(Boolean).pop() ?? '', kind: 'file', size: 1, mtime: 0, metadata: {}, }; return e; }, mkdir: async (ctx) => { const e: FileEntry = { name: ctx.path.split('/').filter(Boolean).pop() ?? '', kind: 'dir', size: 0, mtime: 0, metadata: {}, }; return { entry: e }; }, delete: async () => ({ deletedCount: 1 }), list: async () => ({ entries: [], hasMore: false }), }); }); afterAll(async () => { await rig.teardown(); }); test('mutation without verification → FingerprintRequiredError', async () => { verifiedSet.delete('alice'); await expect(rig.fs.mkdir('/locked')).rejects.toBeInstanceOf(FingerprintRequiredError); await expect(rig.fs.delete('/locked')).rejects.toBeInstanceOf(FingerprintRequiredError); }); test('mutation after marking peer verified → succeeds', async () => { verifiedSet.add('alice'); const result = await rig.fs.mkdir('/verified-dir'); expect(result.entry.name).toBe('verified-dir'); }); test('optional ops (stat, list) work without verification', async () => { verifiedSet.delete('alice'); const stat = await rig.fs.stat('/anything'); expect(stat.name).toBe('anything'); const list = await rig.fs.list('/anything'); expect(list.entries).toEqual([]); }); }); describe('Fingerprint gate with reject policy', () => { let rig: FileTestRig; beforeAll(async () => { rig = await setupFileRig({ requireFingerprintVerifiedFor: () => 'reject', stat: async (ctx) => { const e: FileEntry = { name: 'x', kind: 'file', size: 1, mtime: 0, metadata: {}, }; return e; }, }); }); afterAll(async () => { await rig.teardown(); }); test('all ops rejected outright', async () => { await expect(rig.fs.stat('/x')).rejects.toBeInstanceOf(FingerprintRequiredError); }); });