@@ -69,13 +69,24 @@ function freshRows(): { secrets: Row[]; settings: Row[] } {
6969interface Harness {
7070 secrets : Row [ ] ;
7171 writes : Array < { where : Row ; data : Row } > ;
72+ /** Every table a driver read was issued for, in order. */
73+ reads : string [ ] ;
7274}
7375
74- /** Wire the mocked boot to a fake engine over `rows`. */
75- function wireBoot ( rows : { secrets : Row [ ] ; settings : Row [ ] } , opts : { conditionalWrite ?: boolean } = { } ) : Harness {
76- const harness : Harness = { secrets : rows . secrets , writes : [ ] } ;
76+ /**
77+ * Wire the mocked boot to a fake engine over `rows`.
78+ *
79+ * `absent` names the tables the boot MEASURED absent, which is what the stack's
80+ * `tableAbsent` answers (`SchemaStack.tableAbsent`). The default is none: every
81+ * table exists, as on a plain `--apply` boot, where nothing is deferred.
82+ */
83+ function wireBoot (
84+ rows : { secrets : Row [ ] ; settings : Row [ ] } ,
85+ opts : { conditionalWrite ?: boolean ; absent ?: readonly string [ ] } = { } ,
86+ ) : Harness {
87+ const harness : Harness = { secrets : rows . secrets , writes : [ ] , reads : [ ] } ;
7788 const secretDriver : Record < string , unknown > = {
78- async find ( ) { return harness . secrets . map ( ( r ) => ( { ...r } ) ) ; } ,
89+ async find ( ) { harness . reads . push ( 'sys_secret' ) ; return harness . secrets . map ( ( r ) => ( { ...r } ) ) ; } ,
7990 } ;
8091 if ( opts . conditionalWrite !== false ) {
8192 secretDriver . updateMany = async ( _object : string , query : { where : Row } , data : Row ) => {
@@ -94,13 +105,17 @@ function wireBoot(rows: { secrets: Row[]; settings: Row[] }, opts: { conditional
94105 listDatasourceDefs : ( ) => [ ] ,
95106 getDriverForObject : ( object : string ) => {
96107 if ( object === 'sys_secret' ) return secretDriver ;
97- if ( object === 'sys_setting' ) return { async find ( ) { return rows . settings . map ( ( r ) => ( { ...r } ) ) ; } } ;
98- if ( object === 'sys_metadata' ) return { async find ( ) { return [ ] ; } } ;
108+ if ( object === 'sys_setting' ) {
109+ return { async find ( ) { harness . reads . push ( 'sys_setting' ) ; return rows . settings . map ( ( r ) => ( { ...r } ) ) ; } } ;
110+ }
111+ if ( object === 'sys_metadata' ) return { async find ( ) { harness . reads . push ( 'sys_metadata' ) ; return [ ] ; } } ;
99112 return undefined ;
100113 } ,
101114 } ;
115+ const absent = new Set ( opts . absent ?? [ ] ) ;
102116 vi . mocked ( bootSchemaStack ) . mockResolvedValue ( {
103117 kernel : { getService : ( name : string ) => ( name === 'objectql' ? engine : undefined ) } ,
118+ tableAbsent : ( objectName : string ) => absent . has ( objectName ) ,
104119 shutdown : async ( ) => { } ,
105120 } as never ) ;
106121 return harness ;
@@ -231,6 +246,29 @@ describe('os secret rewrap — guards that stop a run before any row is opened o
231246 expect ( text ) . not . toContain ( KEY_HEX ) ;
232247 } , 60_000 ) ;
233248
249+ it ( 'a dry run over tables the boot measured absent reads none of them, and reports empty work' , async ( ) => {
250+ const h = wireBoot ( freshRows ( ) , { absent : [ 'sys_secret' , 'sys_setting' , 'sys_metadata' ] } ) ;
251+ const { payload, exitCode } = await run ( [ '--no-declared-datasources' ] ) ;
252+
253+ // "Not asked": a table that does not exist holds nothing, so no read is issued.
254+ expect ( h . reads ) . toEqual ( [ ] ) ;
255+ expect ( payload . mode ) . toBe ( 'dry-run' ) ;
256+ expect ( payload . report . counts ) . toEqual ( { total : 0 , rewrap : 0 , done : 0 , left : 0 , refused : 0 , notWritten : 0 } ) ;
257+ // The union is enumerated, not gapped: an absent table holds no reference.
258+ for ( const family of Object . values ( payload . report . families ) as Array < { status : string } > ) {
259+ expect ( family . status ) . toBe ( 'enumerated' ) ;
260+ }
261+ expect ( payload . report . refusal ) . toBeNull ( ) ;
262+ expect ( exitCode ) . toBe ( 0 ) ;
263+ expect ( h . writes ) . toEqual ( [ ] ) ;
264+
265+ // POSITIVE CONTROL: the same rows, tables present — they are read, and the row is planned.
266+ const present = wireBoot ( freshRows ( ) ) ;
267+ const ok = await run ( [ '--no-declared-datasources' ] ) ;
268+ expect ( present . reads ) . toContain ( 'sys_secret' ) ;
269+ expect ( ok . payload . report . counts . total ) . toBe ( 1 ) ;
270+ } , 60_000 ) ;
271+
234272 it ( 'an unreadable --declared-datasources file is refused before the boot, never read as []' , async ( ) => {
235273 const dir = mkdtempSync ( join ( tmpdir ( ) , 'os-rewrap-ds-' ) ) ;
236274 try {
0 commit comments