@@ -116,11 +116,34 @@ describe('searchableJson postgres integration', () => {
116116 await verifyRow ( rows [ 0 ] , plaintext )
117117 } , 30000 )
118118
119- // stack intentionally drops null handling from its Encrypted type
120- // (see "feat(stack): remove null from Encrypted type"), so unlike
121- // protect, encrypt(null) returns a real SteVec rather than null.
122- // The null pass-through scenario therefore doesn't apply to stack.
123- it . skip ( 'round-trips null values' , async ( ) => { } )
119+ it ( 'round-trips null values' , async ( ) => {
120+ // stack's encrypt() public signature still excludes null from its
121+ // JsPlaintext input; the runtime guard restored in #493 handles
122+ // null as defense in depth, so the cast bypasses only the type
123+ // narrowing — the runtime behavior under test is the same as
124+ // protect's.
125+ const encrypted = await protectClient . encrypt ( null as any , {
126+ column : table . metadata ,
127+ table : table ,
128+ } )
129+
130+ if ( encrypted . failure ) throw new Error ( encrypted . failure . message )
131+ expect ( encrypted . data ) . toBeNull ( )
132+
133+ const [ inserted ] = await sql `
134+ INSERT INTO "protect-ci-jsonb-stack" (metadata, test_run_id)
135+ VALUES (NULL, ${ TEST_RUN_ID } )
136+ RETURNING id
137+ `
138+
139+ const rows = await sql `
140+ SELECT id, (metadata).data as metadata FROM "protect-ci-jsonb-stack"
141+ WHERE id = ${ inserted . id }
142+ `
143+
144+ expect ( rows ) . toHaveLength ( 1 )
145+ expect ( rows [ 0 ] . metadata ) . toBeNull ( )
146+ } , 30000 )
124147 } )
125148
126149 // ─── jsonb_path_query: path-based selector queries ─────────────────
0 commit comments