@@ -18,7 +18,6 @@ describe('/diagnostics endpoint', function () {
1818 it ( 'responds 200 with the documented top-level shape' , async function ( ) {
1919 const response = await supertest ( app ) . get ( '/diagnostics' ) . expect ( 200 ) ;
2020 expect ( response . body ) . to . have . property ( 'timestamp' ) . that . is . a ( 'string' ) ;
21- expect ( response . body ) . to . have . property ( 'readOnly' ) ;
2221 expect ( response . body ) . to . have . property ( 'cadt' ) . that . is . an ( 'object' ) ;
2322 expect ( response . body ) . to . have . property ( 'network' ) . that . is . an ( 'object' ) ;
2423 expect ( response . body ) . to . have . property ( 'chia' ) . that . is . an ( 'object' ) ;
@@ -164,89 +163,30 @@ describe('/diagnostics endpoint', function () {
164163 } ) ;
165164 } ) ;
166165
167- describe ( 'read-only stripping' , function ( ) {
168- // The exact contract is documented in src/routes/diagnostics.js and
169- // mirrors the wallet-health.js convention: when READ_ONLY is true the
170- // response retains only non-sensitive metadata. Balances, transaction
171- // details, peer details, subscription IDs, and home-org IDs MUST be
172- // absent. We also intentionally short-circuit BEFORE the wallet/datalayer
173- // RPC fan-out, so the entire `chia.wallet` and `chia.datalayer` sections
174- // are omitted in read-only mode.
175- it ( 'omits operational details when READ_ONLY is enabled' , async function ( ) {
176- await withConfigOverride ( async ( ) => {
177- const response = await supertest ( app ) . get ( '/diagnostics' ) . expect ( 200 ) ;
178- expect ( response . body ) . to . have . property ( 'readOnly' , true ) ;
179- expect ( response . body ) . to . have . property ( 'message' ) . that . is . a ( 'string' ) ;
180-
181- expect ( response . body . chia ) . to . not . have . property ( 'wallet' ) ;
182- expect ( response . body . chia ) . to . not . have . property ( 'datalayer' ) ;
183- expect ( response . body . chia ) . to . not . have . property ( 'fullNode' ) ;
184- expect ( response . body . chia ) . to . not . have . property ( 'services' ) ;
185-
186- expect ( response . body . cadt . v1 ) . to . not . have . property ( 'homeOrgId' ) ;
187- expect ( response . body . cadt . v2 ) . to . not . have . property ( 'homeOrgId' ) ;
188-
189- expect ( response . body . cadt ) . to . have . property ( 'version' ) ;
190- expect ( response . body . network ) . to . have . property ( 'cadt' ) ;
191- expect ( response . body . chia ) . to . have . property ( 'chiaTools' ) ;
192- expect ( response . body ) . to . have . property ( 'system' ) ;
193- } , { APP : { READ_ONLY : true } } ) ;
194- } ) ;
195-
196- it ( 'keeps full detail by default (READ_ONLY off)' , async function ( ) {
197- const response = await supertest ( app ) . get ( '/diagnostics' ) . expect ( 200 ) ;
198- expect ( response . body . readOnly ) . to . equal ( false ) ;
199- expect ( response . body . chia . wallet ) . to . have . property ( 'pendingTransactions' ) ;
200- expect ( response . body . chia . wallet ) . to . have . property ( 'trustedFullNodePeers' ) ;
201- expect ( response . body . chia . datalayer ) . to . have . property ( 'subscriptions' ) ;
202- } ) ;
203-
204- // The four scenarios below exhaustively cover the (READ_ONLY × API key
205- // configured × key provided) matrix for READ_ONLY=true. They confirm both
206- // (a) a public observer node with no API key gets the reduced response
207- // without authentication, and (b) when an API key IS configured the
208- // endpoint still enforces it, returning the reduced response only to
209- // authenticated callers.
210- it ( 'public observer node (READ_ONLY=true, no API key): returns 200 with reduced fields without auth' , async function ( ) {
211- await withConfigOverride ( async ( ) => {
212- const response = await supertest ( app ) . get ( '/diagnostics' ) ;
213- expect ( response . status ) . to . equal ( 200 ) ;
214- expect ( response . body . readOnly ) . to . equal ( true ) ;
215- expect ( response . body . chia ) . to . not . have . property ( 'wallet' ) ;
216- expect ( response . body . chia ) . to . not . have . property ( 'datalayer' ) ;
217- expect ( response . body . chia ) . to . not . have . property ( 'fullNode' ) ;
218- expect ( response . body . cadt ) . to . have . property ( 'version' ) ;
219- expect ( response . body . network ) . to . have . property ( 'cadt' ) ;
220- expect ( response . body ) . to . have . property ( 'system' ) ;
221- } , { APP : { READ_ONLY : true , CADT_API_KEY : '' } } ) ;
222- } ) ;
223-
224- it ( 'READ_ONLY=true + API key configured + no key provided: rejects with 403' , async function ( ) {
166+ describe ( 'read-only mode' , function ( ) {
167+ it ( 'returns 403 when READ_ONLY is enabled' , async function ( ) {
225168 await withConfigOverride ( async ( ) => {
226169 const response = await supertest ( app ) . get ( '/diagnostics' ) ;
227170 expect ( response . status ) . to . equal ( 403 ) ;
228- } , { APP : { READ_ONLY : true , CADT_API_KEY : 'protected-observer-key' } } ) ;
171+ expect ( response . body ) . to . have . property ( 'error' ) . that . is . a ( 'string' ) ;
172+ } , { APP : { READ_ONLY : true } } ) ;
229173 } ) ;
230174
231- it ( 'READ_ONLY=true + API key configured + correct key: returns 200 with reduced fields ' , async function ( ) {
175+ it ( 'returns 403 regardless of API key when READ_ONLY is enabled ' , async function ( ) {
232176 await withConfigOverride ( async ( ) => {
233177 const response = await supertest ( app )
234178 . get ( '/diagnostics' )
235179 . set ( 'x-api-key' , 'protected-observer-key' ) ;
236- expect ( response . status ) . to . equal ( 200 ) ;
237- expect ( response . body . readOnly ) . to . equal ( true ) ;
238- expect ( response . body . chia ) . to . not . have . property ( 'wallet' ) ;
239- expect ( response . body . chia ) . to . not . have . property ( 'datalayer' ) ;
180+ expect ( response . status ) . to . equal ( 403 ) ;
181+ expect ( response . body ) . to . have . property ( 'error' ) . that . is . a ( 'string' ) ;
240182 } , { APP : { READ_ONLY : true , CADT_API_KEY : 'protected-observer-key' } } ) ;
241183 } ) ;
242184
243- it ( 'READ_ONLY=true + API key configured + wrong key: rejects with 403' , async function ( ) {
244- await withConfigOverride ( async ( ) => {
245- const response = await supertest ( app )
246- . get ( '/diagnostics' )
247- . set ( 'x-api-key' , 'X' . repeat ( 'protected-observer-key' . length ) ) ;
248- expect ( response . status ) . to . equal ( 403 ) ;
249- } , { APP : { READ_ONLY : true , CADT_API_KEY : 'protected-observer-key' } } ) ;
185+ it ( 'returns full detail by default (READ_ONLY off)' , async function ( ) {
186+ const response = await supertest ( app ) . get ( '/diagnostics' ) . expect ( 200 ) ;
187+ expect ( response . body . chia . wallet ) . to . have . property ( 'pendingTransactions' ) ;
188+ expect ( response . body . chia . wallet ) . to . have . property ( 'trustedFullNodePeers' ) ;
189+ expect ( response . body . chia . datalayer ) . to . have . property ( 'subscriptions' ) ;
250190 } ) ;
251191 } ) ;
252192
@@ -262,7 +202,7 @@ describe('/diagnostics endpoint', function () {
262202 it ( 'always returns 200 with the documented top-level keys' , async function ( ) {
263203 const response = await supertest ( app ) . get ( '/diagnostics' ) . expect ( 200 ) ;
264204 expect ( response . body ) . to . have . all . keys (
265- 'timestamp' , 'readOnly' , ' cadt', 'network' , 'chia' , 'system' ,
205+ 'timestamp' , 'cadt' , 'network' , 'chia' , 'system' ,
266206 ) ;
267207 expect ( response . body . system ) . to . have . property ( 'cpu' ) ;
268208 expect ( response . body . system ) . to . have . property ( 'memory' ) ;
0 commit comments