import fs from 'node:fs/promises'; import assert from 'node:assert/strict'; import { randomUUID } from 'node:crypto'; const fixturePath = 'C:/laragon/data/sgf-tempo/secrets/browser-fixture.json'; const fixture = JSON.parse(await fs.readFile(fixturePath, 'utf8')); const base = 'http://127.0.0.1:8001'; function client() { const cookies = new Map(); let csrf = ''; let token = ''; return { async request(path, method = 'GET', body, context = token) { const response = await fetch(base + path, { method, headers: { Accept: 'application/json', 'Content-Type': 'application/json', Cookie: [...cookies].map(([k,v]) => `${k}=${v}`).join('; '), 'X-CSRF-TOKEN': csrf, 'X-SGF-Context': context, 'Idempotency-Key': randomUUID() }, ...(body === undefined ? {} : { body: JSON.stringify(body) }) }); for (const cookie of response.headers.getSetCookie()) { const pair = cookie.split(';', 1)[0], split = pair.indexOf('='); cookies.set(pair.slice(0, split), pair.slice(split + 1)); } const data = await response.json().catch(() => ({})); if (data.csrf) csrf = data.csrf; if (data.context?.token) token = data.context.token; return { status: response.status, data }; }, async login(email) { await this.request('/api/session'); assert.equal((await this.request('/api/login', 'POST', { email, password: fixture.password })).status, 200); return this.select(); }, async select(unit = fixture.unit, company = fixture.company) { const response = await this.request('/api/context', 'POST', { tenant_id: fixture.tenant, company_id: company, unit_id: unit }); assert.equal(response.status, 200); return response.data.context.token; } }; } const manager = client(), reader = client(); await manager.login('gestor@example.test'); await reader.login('consulta@example.test'); async function create(area, data) { const result = await manager.request('/api/a/' + area, 'POST', data); assert.equal(result.status, 201); return result.data.id; } async function save(kind, id, data) { const result = await manager.request(`/api/document-preparation/${kind}/${id}`, 'PATCH', data); assert.equal(result.status, 200); return result.data; } const customer = await create('clients', { name: 'Cliente documental de demonstração' }); const service = await create('services', { name: 'Serviço documental de demonstração' }); const source = await create('service_drafts', { client_id: customer, lines: [{ service_id: service, quantity: '1.25', unit_price: '0.00000001' }] }); const oldDraft = await create('billing_drafts', { source_id: source, name: 'B1 anterior à preparação documental' }); assert.equal((await manager.request(`/api/b1/billing-drafts/${oldDraft}/confirm-internal`, 'POST', { version: 1 })).status, 200); const oldBefore = (await manager.request(`/api/a/billing_drafts/${oldDraft}`)).data.confirmation; assert.equal(oldBefore.snapshot.schema_version, undefined); const profile = { version: 0, nuit: 'IDENTIFICAÇÃO SINTÉTICA', address: 'Morada sintética', locality: 'Localidade de teste', country: 'País de teste' }; await save('issuer', fixture.company, profile); await save('client', customer, profile); const privateMarker = 'SYNTHETIC-' + randomUUID(); const paymentData = { version: 0, label: 'Instruções de demonstração — sem operação bancária', bank: 'Banco fictício de teste', holder: 'Titular sintético', account_number: privateMarker, instructions: 'Apenas instruções sintéticas; não efectuar pagamentos.', currency: null }; const instruction = (await save('payment', 0, paymentData)).id; const preparation = { version: 0, draft_version: 1, currency: null, service_date: '2026-11-01', period_start: '2026-11-01', period_end: '2026-11-30', payment_terms: 'Prazo a conferir com vencimento; sem regra aprovada', proposed_due_date: '2026-11-15', price_mode: 'undefined', units: ['hora'], payment_instruction_ids: [instruction] }; await save('service_drafts', source, preparation); const newDraft = await create('billing_drafts', { source_id: source, name: 'Documento interno com preparação versão 2' }); const reused = (await manager.request(`/api/document-preparation/billing_drafts/${newDraft}`)).data; assert.equal(reused.data.units[0], 'hora'); assert.equal(reused.data.payment_instruction_ids[0], instruction); assert.equal(reused.currency, null); assert.equal((await manager.request(`/api/b1/billing-drafts/${newDraft}/confirm-internal`, 'POST', { version: 1 })).status, 200); const snapshot = (await manager.request(`/api/a/billing_drafts/${newDraft}`)).data.confirmation; assert.equal(snapshot.snapshot.schema_version, 2); assert.equal(snapshot.snapshot.document_preparation.payment_instructions[0].data.account_number, privateMarker); await save('payment', instruction, { ...paymentData, version: 1, instructions: 'Instruções sintéticas revistas após confirmação.' }); assert.deepEqual((await manager.request(`/api/a/billing_drafts/${oldDraft}`)).data.confirmation, oldBefore); assert.deepEqual((await manager.request(`/api/a/billing_drafts/${newDraft}`)).data.confirmation, snapshot); assert.equal((await reader.request(`/api/document-preparation/payment/${instruction}`)).status, 200); assert.equal((await reader.request(`/api/document-preparation/payment/${instruction}`, 'PATCH', { ...paymentData, version: 2 })).status, 403); assert.equal((await manager.request(`/api/document-preparation/payment/${instruction}`, 'PATCH', { ...paymentData, version: 1 })).status, 409); const oldContext = await manager.select(); await manager.select(null); assert.equal((await manager.request(`/api/document-preparation/issuer/${fixture.company}`, 'PATCH', { ...profile, version: 1 }, oldContext)).status, 409); await manager.select(null, fixture.sibling); assert.equal((await manager.request(`/api/document-preparation/payment/${instruction}`)).status, 403); await manager.select(); const editableDraft = await create('billing_drafts', { source_id: source, name: 'Percurso visual — preparação documental' }); fixture.document_client_id = customer; fixture.document_source_id = source; fixture.document_draft_id = editableDraft; await fs.writeFile(fixturePath, JSON.stringify(fixture)); await manager.request('/api/logout', 'POST'); await reader.request('/api/logout', 'POST'); await fs.writeFile('docs/proofs/document-http-results.json', JSON.stringify({ database: 'sgf_tempo_test', real_synthetic_login: true, results: ['Client created with name only; company/client profiles reused.', 'Source preparation and selected issuer instruction reused in billing draft.', 'Existing B1 v1 and future v2 snapshots unchanged after configuration updates.', 'Reader can consult instructions; editing denied 403.', 'Old version/context denied 409; other company denied 403.', 'Currency unknown, exact prices unchanged; no receipt, issue or accounting operation.'], instruction_values: 'omitted' }, null, 2)); console.log('Isolated document preparation HTTP proof passed. Instruction values omitted.');