@@ -629,6 +629,67 @@ describe('Project expand/backfill/contract against PostgreSQL', () => {
629629 } )
630630 } )
631631
632+ it ( 'keeps operator discovery, assignment and verification on public under a shadow URL search path' , async ( ) => {
633+ await database ( async ( sql , url ) => {
634+ const directory = await mkdtemp ( join ( tmpdir ( ) , 'project-operator-shadow-' ) )
635+ const manifest = join ( directory , 'manifest.json' )
636+ const report = join ( directory , 'report.json' )
637+ const scopedUrl = new URL ( url )
638+ scopedUrl . searchParams . set ( 'search_path' , 'shadow,public' )
639+ const run = ( command : string ) =>
640+ promisify ( execFile ) (
641+ 'bun' ,
642+ [
643+ '--no-env-file' ,
644+ 'scripts/backfill-projects.ts' ,
645+ command ,
646+ '--manifest' ,
647+ manifest ,
648+ ...( command === 'plan'
649+ ? [ ]
650+ : [ '--report' , report , '--ack-release-drained' , '--pause-ms' , '1' ] ) ,
651+ ] ,
652+ {
653+ cwd : new URL ( '../../../apps/sim/' , import . meta. url ) ,
654+ env : { ...process . env , MIGRATION_DATABASE_URL : scopedUrl . toString ( ) } ,
655+ timeout : 30000 ,
656+ }
657+ )
658+ try {
659+ await sql `INSERT INTO workspace (id,name,owner_id) VALUES ('public-env','Public','owner')`
660+ await sql `CREATE SCHEMA shadow`
661+ for ( const name of [
662+ 'workspace' ,
663+ 'project' ,
664+ 'workflow' ,
665+ 'user' ,
666+ 'organization' ,
667+ 'project_workspace' ,
668+ ] ) {
669+ await sql `CREATE TABLE ${ sql ( `shadow.${ name } ` ) } (LIKE ${ sql ( `public.${ name } ` ) } INCLUDING ALL)`
670+ }
671+ await sql `INSERT INTO shadow.workspace (id,name,owner_id) VALUES ('shadow-env','Untouched','owner')`
672+ await run ( 'plan' )
673+ const plan = JSON . parse ( await readFile ( manifest , 'utf8' ) )
674+ expect ( plan . families . map ( ( family : { rootId : string } ) => family . rootId ) ) . toEqual ( [
675+ 'public-env' ,
676+ ] )
677+ await run ( 'apply' )
678+ expect ( await sql `SELECT id,project_id FROM public.workspace` ) . toEqual ( [
679+ { id : 'public-env' , project_id : expect . any ( String ) } ,
680+ ] )
681+ expect ( await sql `SELECT count(*)::int AS count FROM public.project` ) . toEqual ( [ { count : 1 } ] )
682+ await run ( 'verify' )
683+ expect ( await sql `SELECT id,project_id FROM shadow.workspace` ) . toEqual ( [
684+ { id : 'shadow-env' , project_id : null } ,
685+ ] )
686+ expect ( await sql `SELECT count(*)::int AS count FROM shadow.project` ) . toEqual ( [ { count : 0 } ] )
687+ } finally {
688+ await rm ( directory , { recursive : true , force : true } )
689+ }
690+ } )
691+ } )
692+
632693 it ( 'runs the real operator CLI read-only, resumes bounded batches and survives a lost checkpoint' , async ( ) => {
633694 await database ( async ( sql , url ) => {
634695 const directory = await mkdtemp ( join ( tmpdir ( ) , 'project-operator-test-' ) )
0 commit comments