102 lines
17 KiB
TypeScript
102 lines
17 KiB
TypeScript
import assert from "node:assert/strict"
|
|
import { createHmac,randomUUID } from "node:crypto"
|
|
import { PARTITION_SPECS } from "../db/partitions.js"
|
|
import { createServerPollProductionDependencies,createServerPollProductionExecution,type ServerPollProductionInput,type ServerPollProductionIo } from "./server-poll-production.js"
|
|
import { ServerPollProblem } from "./server-poll-execution-model.js"
|
|
import { ServerPollExecutionError,type ServerPollReceipt } from "./server-poll-execution.js"
|
|
|
|
// Pure query/native/lock doubles. No real pool, SQL, DNS, sockets or collectors.
|
|
type Row=Record<string,unknown>
|
|
const time="2026-10-25T12:00:00.000Z",epoch="11111111-2222-3333-4444-555555555555"
|
|
const server=(id:number):Row=>({id,name:id===1?"before":"foreign",host:`192.0.2.${id}`,port:443,username:"fixture-admin",password:"NEVER_POLL_PASSWORD_"+id,use_ssl:true,verify_ssl:true,enabled:true,routing_endpoint_epoch:epoch,updated_at:"2026-10-24T12:00:00+00:00",opaque:"NEVER_POLL_SERVER"})
|
|
const canonical=(value:unknown):unknown=>Array.isArray(value)?value.map(canonical):value&&typeof value==="object"?Object.fromEntries(Object.entries(value).sort(([a],[b])=>a.localeCompare(b)).map(([key,item])=>[key,canonical(item)])):value
|
|
const proof=async(value:unknown)=>createHmac("sha256","inert-production-adapter-fixture-only").update(JSON.stringify(canonical(value))).digest("hex")
|
|
let servers:Row[],snapshots:Row[],partitions:Row[],allowed:number[],revoked:boolean,sql:string[],native:string[],locks:string[],events:string[],cache:number,mode:string,afterQuery:(()=>void)|undefined,claim:{proof:string;receipt?:ServerPollReceipt}|undefined,unsafeReleases:number
|
|
const initialPartition=():Row=>({parent:"server_snapshots",name:"server_snapshots_w_20000103",namespace:"public",bound:"FOR VALUES FROM ('2000-01-03T00:00:00.000Z') TO ('2000-01-10T00:00:00.000Z')",reloptions:[],catalog_json:JSON.stringify({oid:"100",relname:"server_snapshots_w_20000103",opaque:"NEVER_PARTITION"})})
|
|
function reset(){servers=[server(1),server(2)];snapshots=[{id:1,server_id:1,polled_at:"2026-10-24T12:00:00+00:00",status:"online",raw_interfaces:[{name:"old",opaque:"NEVER_RAW"}],raw_ip_addresses:[],opaque:"NEVER_HISTORY"}];partitions=[initialPartition()];allowed=[1,2];revoked=false;sql=[];native=[];locks=[];events=[];cache=0;mode="normal";afterQuery=undefined;claim=undefined;unsafeReleases=0}
|
|
const isBundle=(text:string)=>text.includes("/* poll-context:bundle */")
|
|
function contextBundle():Row[]{
|
|
const tagged=(source:string,rows:Row[])=>rows.map((row,index)=>({source,row_order:String(index+1),raw_json:JSON.stringify(row)}))
|
|
const parents=PARTITION_SPECS.map((spec,index)=>({name:spec.parent,namespace:"public",relkind:mode==="bad-parent"&&index===0?"r":"p",oid:String(500+index),owner:"1",partition_key:"RANGE ("+(["flow_buckets","flow_minute_stats","flow_minute_dims","flow_hour_facts"].includes(spec.parent)?"bucket_at":["flow_daily_dims","flow_daily_facts"].includes(spec.parent)?"day":spec.parent==="server_snapshots"?"polled_at":"sampled_at")+")"}))
|
|
const history=mode==="snapshot-overflow"?Array.from({length:2001},(_,index)=>({...snapshots[0],id:index+1})):snapshots.map(row=>mode==="snapshot-oversize"?{...row,raw_interfaces:[{opaque:"x".repeat(1048577)}]}:row)
|
|
const settings={id:1,retention_days:14,opaque:"NEVER_SETTINGS",updated_at:time}
|
|
const rows:Row[]=[...tagged("servers",servers),...tagged("traffic",[settings]),...tagged("uptime",[settings]),...tagged("internetPath",[settings]),...tagged("parents",parents),...tagged("partitions",partitions),...tagged("snapshots",history),...tagged("protections",[{id:"guard",object_ref:{kind:"server",id:"1",serverId:1,protection:"approval"},created_by:"fixture-owner"}])]
|
|
if(mode==="oversize")rows[0].raw_json=null
|
|
if(mode==="unknown-source")rows[0].source="unexpected"
|
|
if(mode==="duplicate-ordinal")rows[1].row_order=rows[0].row_order
|
|
if(mode==="ordinal-gap")rows[1].row_order="3"
|
|
if(mode==="numeric-ordinal")rows[0].row_order=1
|
|
if(mode==="non-string-payload")rows[0].raw_json={id:1}
|
|
if(mode==="partition-null-sentinel")rows.find(row=>row.source==="partitions")!.raw_json=null
|
|
if(mode==="parent-null-key")rows.find(row=>row.source==="parents")!.raw_json=JSON.stringify({...parents[0],partition_key:null})
|
|
if(mode==="settings-overflow")rows.push({...rows.find(row=>row.source==="traffic")!,row_order:"2"})
|
|
return mode==="shuffled"?rows.reverse():rows
|
|
}
|
|
reset()
|
|
const io:ServerPollProductionIo={
|
|
connect:async options=>{options.signal?.throwIfAborted();return {release:unsafe=>{if(unsafe)unsafeReleases++},query:async(text,values,options)=>{
|
|
options.signal?.throwIfAborted();assert.ok(options.timeoutMs>0&&options.timeoutMs<=10000);sql.push(text);events.push(isBundle(text)?"bundle":text)
|
|
let rows:Row[]=[]
|
|
if(isBundle(text)){assert.deepEqual(values,[[1,2],PARTITION_SPECS.map(spec=>spec.parent),1]);rows=contextBundle();if(mode==="revoke-after-bundle")revoked=true}
|
|
else if(text==="SELECT id FROM servers ORDER BY id LIMIT 1001"){rows=servers.map(row=>({id:row.id}));if(mode==="revoke-after-metadata")revoked=true}
|
|
else if(text.includes("FROM servers s WHERE"))rows=servers.map(row=>({raw_json:mode==="oversize"?null:JSON.stringify(row)}))
|
|
else if(/FROM (traffic_settings|uptime_settings|internet_path_settings) s/.test(text))rows=[{raw_json:JSON.stringify({id:1,retention_days:14,opaque:"NEVER_SETTINGS",updated_at:time})}]
|
|
else if(text.includes("pg_get_partkeydef"))rows=PARTITION_SPECS.map((spec,index)=>({name:spec.parent,namespace:"public",relkind:mode==="bad-parent"&&index===0?"r":"p",oid:String(500+index),owner:"1",partition_key:"RANGE ("+(["flow_buckets","flow_minute_stats","flow_minute_dims","flow_hour_facts"].includes(spec.parent)?"bucket_at":["flow_daily_dims","flow_daily_facts"].includes(spec.parent)?"day":spec.parent==="server_snapshots"?"polled_at":"sampled_at")+")"}))
|
|
else if(text.includes("FROM pg_inherits"))rows=partitions.filter(row=>values[1]===undefined||row.name===values[1])
|
|
else if(text.includes("FROM server_snapshots s WHERE"))rows=mode==="snapshot-overflow"?Array.from({length:2001},(_,index)=>({raw_json:JSON.stringify({...snapshots[0],id:index+1})})):snapshots.map(row=>({raw_json:JSON.stringify(mode==="snapshot-oversize"?{...row,raw_interfaces:[{opaque:"x".repeat(1048577)}]}:row)}))
|
|
else if(text.includes("FROM mcp_protections s"))rows=[{raw_json:JSON.stringify({id:"guard",object_ref:{kind:"server",id:"1",serverId:1,protection:"approval"},created_by:"fixture-owner"})}]
|
|
else if(text.startsWith("UPDATE servers s SET")){const row=servers.find(row=>row.id===values[0])!;row.name=values[1];row.updated_at=values[2];rows=[{raw_json:JSON.stringify(row)}]}
|
|
else if(text.startsWith("INSERT INTO server_snapshots")){const columns=text.match(/\(([^)]+)\) VALUES/)![1].split(",");const row:Row={id:2};for(let index=0;index<columns.length;index++)row[columns[index]]=columns[index].startsWith("raw_")?JSON.parse(String(values[index])):values[index];snapshots.push(row);rows=[{raw_json:JSON.stringify(row)}]}
|
|
else if(text.startsWith("UPDATE server_snapshots SET")){for(const row of snapshots)if((values[2]as unknown[]).includes(row.id)){row.raw_interfaces=null;row.raw_ip_addresses=null;rows.push({id:String(row.id),server_id:row.server_id,polled_at:row.polled_at,raw_interfaces:null,raw_ip_addresses:null})}}
|
|
else if(text.startsWith("DROP TABLE")){const name=text.match(/"public"\."([^"]+)"/)![1];partitions=partitions.filter(row=>row.name!==name)}
|
|
else if(text.startsWith("CREATE TABLE")){const match=text.match(/"public"\."([^"]+)" PARTITION OF "public"\."([^"]+)" FOR VALUES FROM \('([^']+)'\) TO \('([^']+)'\)/)!;if(!partitions.some(row=>row.name===match[1]))partitions.push({parent:match[2],name:match[1],namespace:"public",bound:`FOR VALUES FROM ('${match[3]}') TO ('${match[4]}')`,reloptions:[],catalog_json:JSON.stringify({oid:String(1000+partitions.length),relname:match[1],opaque:"NEVER_NEW_PARTITION"})})}
|
|
else if(text.startsWith("ALTER TABLE")){const name=text.match(/"public"\."([^"]+)"/)![1],row=partitions.find(row=>row.name===name)!;row.reloptions=["fillfactor=70","autovacuum_vacuum_scale_factor=0.05","autovacuum_vacuum_cost_limit=2000"]}
|
|
else if(!["BEGIN","BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY","COMMIT","SET LOCAL TIME ZONE 'UTC'"].includes(text)&&!text.startsWith("SET LOCAL statement_timeout="))throw Error("Unexpected inert SQL")
|
|
if(afterQuery){const hook=afterQuery;afterQuery=undefined;hook()}
|
|
if(mode==="lost-commit"&&text==="COMMIT"&&servers[0].name==="after")throw Error("NEVER_COMMIT_ACK")
|
|
return {rows,rowCount:rows.length}
|
|
}}},
|
|
applicationLock:async work=>{locks.push("global");return work()},serverLocks:async(ids,work)=>{assert.deepEqual(ids,[1,2]);locks.push("servers");return work()},
|
|
native:async(read,_server,options)=>{await options.beforeDispatch();native.push(read);if(read==="identity")return{name:"after"};if(read==="resource")return{"cpu-load":"5","free-memory":"1024","total-memory":"2048",version:"7","board-name":"CHR",uptime:"1d"};if(read==="interfaces")return[{".id":"*1",name:"ether1",opaque:"NEVER_NATIVE"}];return[{".id":"*2",interface:"ether1",address:"192.0.2.1/24"}]},
|
|
invalidateCache:async()=>{cache++},
|
|
}
|
|
const request=()=>({serverId:1,receiptId:randomUUID()})
|
|
const input=(bound=request()):ServerPollProductionInput=>({request:bound,io,now:()=>Date.parse(time),proof,authorize:async(_request,_ids,signal)=>{events.push("fresh");signal?.throwIfAborted();if(revoked)throw new ServerPollProblem("PERMISSION_DENIED","inert revoke");return{global:true,serverIds:allowed,authorityProof:"a".repeat(64)}},maintenanceLease:async(work,options)=>{assert.deepEqual(options.serverIds,[1,2]);locks.push("writers-drained");return work()},journal:{intent:async()=>{},acknowledge:async()=>{},claim:async(_request,bindingProof)=>{if(claim)return claim.receipt?{state:"known",bindingProof:claim.proof,receipt:claim.receipt}:{state:"unresolved",bindingProof:claim.proof};claim={proof:bindingProof};return{state:"new"}},complete:async(receipt)=>{claim!.receipt=structuredClone(receipt)}}})
|
|
let configured=input(),deps=createServerPollProductionDependencies(configured),checks=0
|
|
const context=await deps.readContext(configured.request,async()=>{checks++},[1,2],{deadlineAt:Date.parse(time)+45000})
|
|
assert.equal(context.settings.traffic!.retentionDays,14);assert.equal(context.servers[0].routingEndpointEpoch,epoch);assert.equal(context.snapshots[0].polledAt,"2026-10-24T12:00:00.000Z");assert.equal(context.partitions[0].from,"2000-01-03T00:00:00.000Z");assert.ok(checks>sql.length,"Every SQL await has before/after authorization")
|
|
assert.equal(sql.filter(isBundle).length,1,"One bounded bundle reads every private context source")
|
|
assert.deepEqual(sql.filter(text=>text.startsWith("SELECT id FROM servers")||isBundle(text)).map(text=>isBundle(text)?"bundle":"metadata"),["metadata","bundle"])
|
|
for(const text of sql){const event=isBundle(text)?"bundle":text,index=events.indexOf(event);assert.deepEqual(events.slice(index-1,index+2),["fresh",event,"fresh"],"Every physical SQL keeps fresh authority immediately on both sides")}
|
|
assert.equal(context.servers[0].opaque,"NEVER_POLL_SERVER");assert.equal(context.settings.traffic!.opaque,"NEVER_SETTINGS");assert.equal(context.snapshots[0].opaque,"NEVER_HISTORY");assert.equal((context.partitions[0].catalog as Row).opaque,"NEVER_PARTITION")
|
|
reset();mode="shuffled";configured=input();deps=createServerPollProductionDependencies(configured)
|
|
assert.deepEqual(await deps.readContext(configured.request,async()=>{},[1,2],{deadlineAt:Date.parse(time)+45000}),context,"Tagged ordinals conserve the complete context despite shuffled transport rows")
|
|
reset();allowed=[1];configured=input();deps=createServerPollProductionDependencies(configured);await assert.rejects(deps.readContext(configured.request,async()=>{},[1],{deadlineAt:Date.parse(time)+45000}));assert.ok(!sql.some(isBundle),"Metadata denies before credentials/settings bundle")
|
|
reset();configured=input();deps=createServerPollProductionDependencies(configured);afterQuery=()=>{revoked=true};await assert.rejects(deps.readContext(configured.request,async()=>{},[1,2],{deadlineAt:Date.parse(time)+45000}));assert.ok(!sql.some(isBundle))
|
|
for(const fault of ["oversize","bad-parent","snapshot-oversize","snapshot-overflow","unknown-source","duplicate-ordinal","ordinal-gap","numeric-ordinal","non-string-payload","partition-null-sentinel","parent-null-key","settings-overflow"]){reset();mode=fault;configured=input();deps=createServerPollProductionDependencies(configured);await assert.rejects(deps.readContext(configured.request,async()=>{},[1,2],{deadlineAt:Date.parse(time)+45000}),ServerPollProblem,fault);assert.equal(native.length,0);assert.ok(!sql.includes("COMMIT"),fault+" refuses the whole context")}
|
|
for(const fault of ["revoke-after-metadata","revoke-after-bundle"]){reset();mode=fault;configured=input();deps=createServerPollProductionDependencies(configured);await assert.rejects(deps.readContext(configured.request,async()=>{},[1,2],{deadlineAt:Date.parse(time)+45000}));assert.equal(sql.filter(isBundle).length,fault==="revoke-after-bundle"?1:0);assert.ok(!sql.includes("COMMIT"));assert.ok(unsafeReleases>0)}
|
|
reset();configured=input();const executor=createServerPollProductionExecution(configured),plan=await executor.prepare(configured.request);assert.equal(native.length,0)
|
|
const receipt=await executor.execute(plan)
|
|
assert.equal(receipt.complete,true);assert.equal(receipt.maintenanceComplete,true);assert.deepEqual(native.sort(),["addresses","identity","interfaces","resource"]);assert.deepEqual(locks,["global","servers","writers-drained"]);assert.equal(cache,1);assert.equal(snapshots[0].raw_interfaces,null);assert.equal(servers[1].name,"foreign");assert.ok(sql.some(text=>text.startsWith("DROP TABLE")));assert.ok(sql.some(text=>text.startsWith("CREATE TABLE")));assert.ok(sql.some(text=>text.startsWith("ALTER TABLE")));assert.ok(!JSON.stringify(receipt).includes("NEVER_"))
|
|
const writes=sql.filter(text=>/^(UPDATE|INSERT|CREATE|DROP|ALTER)/.test(text)).length;await executor.execute(plan);assert.equal(sql.filter(text=>/^(UPDATE|INSERT|CREATE|DROP|ALTER)/.test(text)).length,writes,"Known receipt never replays SQL/DDL")
|
|
reset();configured=input();const failed=createServerPollProductionExecution(configured),pending=await failed.prepare(configured.request);mode="lost-commit";await assert.rejects(failed.execute(pending),ServerPollExecutionError);assert.equal(servers[0].name,"after");assert.equal(cache,0);assert.ok(unsafeReleases>0);const count=sql.filter(text=>text.startsWith("UPDATE servers")).length;await assert.rejects(failed.execute(pending));assert.equal(sql.filter(text=>text.startsWith("UPDATE servers")).length,count)
|
|
reset();configured=input();deps=createServerPollProductionDependencies(configured);await assert.rejects(deps.effect({kind:"flow-cache.invalidate",serverId:1},{receiptId:configured.request.receiptId,stage:0,deadlineAt:Date.parse(time)+45000,beforeDispatch:async()=>{}}));assert.equal(cache,0,"No publication outside owned global/server/writer lease")
|
|
assert.throws(()=>createServerPollProductionDependencies({...input(),maintenanceLease:undefined as never}))
|
|
assert.throws(()=>createServerPollProductionDependencies({...input(),journal:{} as never}))
|
|
reset();configured=input();deps=createServerPollProductionDependencies(configured);await assert.rejects(deps.readContext({...configured.request,receiptId:randomUUID()},async()=>{},[1,2],{deadlineAt:Date.parse(time)+45000}));assert.equal(sql.length,0,"Bound adapter refuses another operation before SQL")
|
|
reset();configured=input();const late=createServerPollProductionExecution({...configured,journal:{...configured.journal,intent:async value=>{if(value.stage==="publish.0")revoked=true}}}),latePlan=await late.prepare(configured.request);await assert.rejects(late.execute(latePlan));assert.ok(!sql.some(text=>text.startsWith("UPDATE servers")),"Revocation after durable intent prevents SQL dispatch")
|
|
reset();configured=input();deps=createServerPollProductionDependencies({...configured,io:{...io,connect:async()=>{throw Error("NEVER_SQL_CREDENTIAL")}}});await assert.rejects(deps.readContext(configured.request,async()=>{},[1,2],{deadlineAt:Date.parse(time)+45000}),(error:unknown)=>error instanceof ServerPollProblem&&!error.message.includes("NEVER_"))
|
|
reset();configured=input();let delegated=0
|
|
const sameBackendIo:ServerPollProductionIo={...io,
|
|
connect:async()=>{throw Error("Adapter must use supplied same-backend transaction")},
|
|
transaction:async(readOnly,fence,options,work)=>{
|
|
delegated++;assert.equal(readOnly,true);await fence()
|
|
const connection=await io.connect(options)
|
|
try{return await work(async(text,values=[])=>{await fence();const result=await connection.query(text,values,{signal:options.signal,timeoutMs:1000});await fence();return result})}finally{connection.release(false)}
|
|
},
|
|
}
|
|
deps=createServerPollProductionDependencies({...configured,io:sameBackendIo})
|
|
assert.equal((await deps.readContext(configured.request,async()=>{},[1,2],{deadlineAt:Date.parse(time)+45000})).servers.length,2)
|
|
assert.equal(delegated,1,"Context must share the maintenance transaction backend, including nested reads")
|
|
console.log("Server poll production adapter inert tests: actual schema mapping, metadata-before-secrets, full raw context, source fences, global/server/writer locks, same-backend transaction delegation, all publications/DDL, lost commit no replay passed; no SQL/network executed")
|