Staging 96adbce3 added refuseWhenAccountDeletionPending to the open route; the
domain test's call counter saw its service RPC. The freeze has its own suite,
so the test mocks it as not frozen; the invalid-source assertion is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
110 lines
7.9 KiB
TypeScript
110 lines
7.9 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { spawnSync } from "node:child_process";
|
|
import { fileURLToPath } from "node:url";
|
|
import test from "node:test";
|
|
import { parseOpenRectificationCaseRequest } from "../src/lib/rectification-agentic/v9/open-request.ts";
|
|
import { openRectificationRequestBody } from "../src/lib/rectification-entry.ts";
|
|
|
|
const sourceId = "11111111-1111-4111-8111-111111111111";
|
|
const requestId = "22222222-2222-4222-8222-222222222222";
|
|
|
|
test("handoff accepts only a source reference, never a browser domain or birth facts", () => {
|
|
const body = openRectificationRequestBody("homepage", null, sourceId);
|
|
assert.equal(body.sourceSessionId, sourceId);
|
|
assert.ok(parseOpenRectificationCaseRequest(body));
|
|
for (const patch of [{ domain: "career" }, { productDomain: "marriage" }, { birth_date: "2000-06-14" }, { scores: [] }, { sourceSessionId: "not-a-uuid" }]) {
|
|
assert.equal(parseOpenRectificationCaseRequest({ ...body, ...patch }), null);
|
|
}
|
|
assert.equal(parseOpenRectificationCaseRequest({ intent: "session", requestId, sessionId: sourceId, sourceSessionId: sourceId }), null);
|
|
assert.equal(parseOpenRectificationCaseRequest({ intent: "new", requestId, sourceSessionId: sourceId }), null);
|
|
assert.equal(openRectificationRequestBody("session", sourceId, sourceId).sourceSessionId, undefined);
|
|
});
|
|
|
|
// Fictional owned-session/RPC controls exercising the actual POST and case service,
|
|
// not a PostgreSQL or engine calibration claim.
|
|
test("production open route reads owned consultation themes and fixes new-case targets without changing exact-session opens", () => {
|
|
const script = String.raw`
|
|
import assert from 'node:assert/strict';
|
|
import { mock } from 'node:test';
|
|
import { pathToFileURL } from 'node:url';
|
|
import { resolveActiveSkillPackage } from './src/lib/skill-package-registry.ts';
|
|
import { targetChartsForDomain } from './src/lib/rectification-agentic/core/segment-summary.ts';
|
|
const userId='11111111-1111-4111-8111-111111111111';
|
|
const sourceId='22222222-2222-4222-8222-222222222222';
|
|
const sessionId='33333333-3333-4333-8333-333333333333';
|
|
const caseId='44444444-4444-4444-8444-444444444444';
|
|
const skill=resolveActiveSkillPackage('jyotish-birth-time-rectification');
|
|
let source={id:sourceId,user_id:userId,session_type:'consultation',theme:'marriage'};
|
|
let persistedDomain=null; let sourceError=null; let queries=[]; let calls=[];
|
|
const response=()=>({case_id:caseId,session_id:sessionId,status:'draft',disposition:'created',should_start_opening:false,skill_version:skill.version});
|
|
const accounting={
|
|
from(table){assert.equal(table,'profiles'); return {select(){return this},eq(){return this},single:async()=>({error:null,data:{
|
|
birth_date:'2000-06-14',birth_place_label:'Synthetic Test City',reported_birth_time:'09:10',birth_time_source:'family_exact',
|
|
latitude:40,longitude:-74,timezone_id:'America/New_York',timezone_offset:-4,ayanamsa:'raman'
|
|
}})}},
|
|
rpc:async(fn,args)=>{
|
|
calls.push({fn,args});
|
|
if(fn==='get_agentic_rectification_skill_identity')return {error:null,data:{skill_name:skill.name,skill_version:skill.version,skill_sha256:skill.sha256,skill_source_commit:skill.sourceCommit}};
|
|
if(fn==='open_agentic_rectification_case')return {error:null,data:response()};
|
|
if(fn==='open_agentic_rectification_case_v2'){
|
|
if(args.p_intent==='session')assert.ok(!Object.hasOwn(args,'p_product_domain'));
|
|
else if(persistedDomain===null)persistedDomain=args.p_product_domain;
|
|
return {error:null,data:response()};
|
|
}
|
|
throw new Error('unexpected RPC '+fn);
|
|
}
|
|
};
|
|
mock.module('server-only',{namedExports:{}});
|
|
mock.module('@/lib/supabase/server',{namedExports:{createServerSupabaseClient:async()=>({
|
|
auth:{getUser:async()=>({data:{user:{id:userId}},error:null})},
|
|
from(table){assert.equal(table,'chat_sessions'); const filters={}; return {
|
|
select(columns){assert.equal(columns,'id,user_id,session_type,theme'); return this},
|
|
eq(key,value){filters[key]=value; return this},
|
|
maybeSingle:async()=>{queries.push(filters); assert.equal(filters.id,sourceId); assert.equal(filters.user_id,userId);
|
|
return {data:source,error:sourceError}}
|
|
}}
|
|
})}});
|
|
mock.module('@/lib/supabase/admin',{namedExports:{createAdminSupabaseClient:()=>accounting}});
|
|
mock.module('@/lib/product-access',{namedExports:{isProductEnabled:async()=>true}});
|
|
// Account-deletion freeze (staging 96adbce3) has its own suite; here the account is not frozen.
|
|
mock.module('@/lib/account-deletion-server',{namedExports:{refuseWhenAccountDeletionPending:async()=>null}});
|
|
const {POST}=await import(pathToFileURL(process.cwd()+'/src/app/api/rectification/cases/open/route.ts').href);
|
|
const post=async(body)=>POST(new Request('https://example.invalid/api/rectification/cases/open',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(body)}));
|
|
const body={intent:'homepage',requestId:'55555555-5555-4555-8555-555555555555',sourceSessionId:sourceId};
|
|
for(const [theme,domain,targets] of [
|
|
['marriage','marriage',['D1','D9']],['career','career',['D1','D10']],['general','general',['D1','D9','D10']],
|
|
['wealth','finance',['D1','D9','D10']],['migration','relocation',['D1','D9','D10']],['annual','general',['D1','D9','D10']],
|
|
['health','health',['D1','D9','D10']],['education','education',['D1','D9','D10']],['family','family',['D1','D9','D10']],['timing','general',['D1','D9','D10']]
|
|
]){
|
|
source.theme=theme; persistedDomain=null; calls=[];
|
|
const result=await post(body); assert.equal(result.status,200,await result.text());
|
|
assert.equal(persistedDomain,domain); assert.deepEqual(targetChartsForDomain(persistedDomain),targets);
|
|
assert.equal(calls.filter(c=>c.fn==='open_agentic_rectification_case_v2').length,1);
|
|
assert.ok(!calls.some(c=>/initialize_agentic_rectification_domain|focus|billing/.test(c.fn)));
|
|
}
|
|
source.theme='marriage'; persistedDomain=null; assert.equal((await post(body)).status,200);
|
|
source.theme='career'; assert.equal((await post(body)).status,200); assert.equal(persistedDomain,'marriage','new source theme cannot rewrite persisted case domain');
|
|
for(const [replacement,status,code] of [
|
|
[null,404,'source_session_not_found'],
|
|
[{...source,user_id:'66666666-6666-4666-8666-666666666666'},404,'source_session_not_found'],
|
|
[{...source,session_type:'birth_time_rectification'},400,'source_session_not_consultation'],
|
|
[{...source,theme:'relationship'},400,'source_session_invalid_theme'],
|
|
[{...source,theme:'D1'},400,'source_session_invalid_theme']
|
|
]){
|
|
source=replacement; calls=[]; const result=await post(body); assert.equal(result.status,status); assert.equal((await result.json()).code,code);
|
|
assert.equal(calls.length,0,'invalid source must not read profile or open a case');
|
|
}
|
|
sourceError={message:'synthetic unavailable'}; const unavailable=await post(body); assert.equal(unavailable.status,503); sourceError=null;
|
|
calls=[]; queries=[]; persistedDomain=null;
|
|
const general=await post({intent:'homepage',requestId:body.requestId}); assert.equal(general.status,200); assert.equal(persistedDomain,'general'); assert.equal(queries.length,0);
|
|
calls=[]; queries=[];
|
|
const exact=await post({intent:'session',sessionId,requestId:body.requestId}); assert.equal(exact.status,200);
|
|
assert.equal(queries.length,0); assert.ok(!Object.hasOwn(calls.find(c=>c.fn==='open_agentic_rectification_case_v2').args,'p_product_domain'));
|
|
assert.equal((await post({...body,domain:'career'})).status,400);
|
|
`;
|
|
const result = spawnSync(process.execPath, ["--experimental-test-module-mocks", "--import", "tsx", "--input-type=module", "--eval", script], {
|
|
cwd: fileURLToPath(new URL("../", import.meta.url)), encoding: "utf8", timeout: 60_000,
|
|
});
|
|
assert.equal(result.status, 0, result.stderr + result.stdout);
|
|
});
|