import assert from 'node:assert/strict'; import { mkdtemp, rm } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { randomBytes } from 'node:crypto'; import { getStore } from '../release/netlify-sdk/node_modules/@netlify/blobs/dist/main.js'; import { BlobsServer } from '../release/netlify-sdk/node_modules/@netlify/blobs/dist/server.js'; import { createNetlifyHandler } from '../release/netlify-preview/lib/context-api.mjs'; const directory = await mkdtemp(join(tmpdir(),'marmar-blobs-smoke-')); const token = randomBytes(32).toString('hex'); const server = new BlobsServer({directory,token,logger:()=>{}}); try { const address=await server.start(); const rawStore = () => getStore({name:'context-smoke',siteID:'synthetic-local',edgeURL:`http://127.0.0.1:${address.port}`,uncachedEdgeURL:`http://127.0.0.1:${address.port}`,token,consistency:'strong'}); // Netlify's filesystem test server omits ETags on GET in 11.1.4. // Its list operation returns them. This test-only shim restores that header // contract; production uses the real service ETag and fails closed if absent. const store = () => { const raw=rawStore(); return { get:raw.get.bind(raw), setJSON:raw.setJSON.bind(raw), delete:raw.delete.bind(raw), list:raw.list.bind(raw), getWithMetadata:async(key,opts)=> { const row=await raw.getWithMetadata(key,opts); if (!row) return row; const listing=await raw.list({prefix:key}); return {...row,etag:listing.blobs.find(b=>b.key===key)?.etag}; } }; }; const request=(path,body,cookie)=>new Request('https://context.marmar.life/api/'+path,{method:body===undefined?'GET':'POST',headers:{Origin:'https://context.marmar.life',...(body===undefined?{}:{'Content-Type':'application/json'}),...(cookie?{Cookie:cookie}:{})},...(body===undefined?{}:{body:JSON.stringify(body)})}); // ACC-2 and ACC-11: the hosted demo needs no password; each browser gets its own demo id. process.env.CONTEXT_AUTH_MODE='demo'; let response = await createNetlifyHandler(store)(request('status')); assert.equal(response.status,200); assert.equal((await response.json()).modelConfigured,false); const cookie=response.headers.get('set-cookie').split(';')[0]; let result=await createNetlifyHandler(store)(request('cases',undefined,cookie)); const cases=await result.json(); result=await createNetlifyHandler(store)(request('extract',{sources:cases[0].sources,syntheticOnly:true,useModel:false},cookie)); const draft=await result.json(); assert.equal(result.status,200,JSON.stringify(draft)); const review=Object.fromEntries(draft.facts.map(f=>[f.id,'include'])); result=await createNetlifyHandler(store)(request('assess',{sources:cases[0].sources,syntheticOnly:true,draftId:draft.id,review,fingerprint:draft.fingerprint,acknowledgeUnparsed:true},cookie)); const assessment=await result.json(); assert.equal(result.status,200,JSON.stringify(assessment)); result=await createNetlifyHandler(store)(request('reports/'+assessment.reportId,undefined,cookie)); const report=await result.json(); assert.equal(result.status,200,JSON.stringify(report)); assert.deepEqual(report.sources,cases[0].sources); const other=await createNetlifyHandler(store)(request('status')); const otherCookie=other.headers.get('set-cookie').split(';')[0]; result=await createNetlifyHandler(store)(request('reports/'+assessment.reportId,undefined,otherCookie)); assert.equal(result.status,400); const first=await store().setJSON('conditional',{n:1},{onlyIfNew:true});assert.equal(first.modified,true); assert.equal((await store().setJSON('conditional',{n:2},{onlyIfNew:true})).modified,false); const saved=await store().getWithMetadata('conditional',{type:'json'}); assert.equal((await store().setJSON('conditional',{n:3},{onlyIfMatch:saved.etag})).modified,true); assert.equal((await store().setJSON('conditional',{n:4},{onlyIfMatch:saved.etag})).modified,false); const foreign=await createNetlifyHandler(store)(new Request('https://context.marmar.life/api/status',{headers:{Origin:'https://evil.example'}}));assert.equal(foreign.status,403); const pasted=await createNetlifyHandler(store)(request('extract',{sources:[{...cases[0].sources[0],text:'Patient: someone real'}],syntheticOnly:true,useModel:false},cookie));assert.equal(pasted.status,403); console.log(JSON.stringify({passed:true,scope:'Actual Netlify Blobs SDK with local filesystem server, no cloud/model call',checks:['demo id cookie','cold-handler extraction/assessment/export','browser-session isolation','conditional writes','foreign-origin rejection','fictional records only']})); } finally { await server.stop(); await rm(directory,{recursive:true,force:true}); }