@@ -135,15 +135,26 @@ admin.get('/stats', async (c) => {
135135
136136// ── GET /status — deep health check for all integrations ───────────────────────
137137
138- type CheckResult = { ok : boolean ; latency_ms : number ; error ?: string ; [ k : string ] : unknown }
139- type CheckInput = { ok : boolean ; error ?: string ; [ k : string ] : unknown }
138+ type CheckResult = {
139+ ok : boolean
140+ latency_ms : number
141+ error ?: string
142+ severity ?: 'critical' | 'warning'
143+ [ k : string ] : unknown
144+ }
145+ type CheckInput = {
146+ ok : boolean
147+ error ?: string
148+ severity ?: 'critical' | 'warning'
149+ [ k : string ] : unknown
150+ }
140151
141152async function timed ( fn : ( ) => Promise < CheckInput > ) : Promise < CheckResult > {
142153 const t0 = Date . now ( )
143154 try {
144155 return { ...await fn ( ) , latency_ms : Date . now ( ) - t0 }
145156 } catch ( err : any ) {
146- return { ok : false , error : err ?. message ?? 'unknown' , latency_ms : Date . now ( ) - t0 }
157+ return { ok : false , error : err ?. message ?? 'unknown' , severity : 'critical' , latency_ms : Date . now ( ) - t0 }
147158 }
148159}
149160
@@ -153,51 +164,56 @@ admin.get('/status', async (c) => {
153164 const [ d1 , kv , resend , stripe , ses ] = await Promise . all ( [
154165 timed ( async ( ) => {
155166 await env . DB . prepare ( 'SELECT 1' ) . first ( )
156- return { ok : true }
167+ return { ok : true , severity : 'critical' }
157168 } ) ,
158169 timed ( async ( ) => {
159170 await env . WIDGET_KV . get ( '__healthcheck' )
160- return { ok : true }
171+ return { ok : true , severity : 'critical' }
161172 } ) ,
162173 timed ( async ( ) => {
163- if ( ! env . RESEND_API_KEY ) return { ok : false , error : 'RESEND_API_KEY not set' }
174+ if ( ! env . RESEND_API_KEY ) return { ok : false , error : 'RESEND_API_KEY not set' , severity : 'critical' }
164175 const res = await fetch ( 'https://api.resend.com/domains' , {
165176 headers : { Authorization : `Bearer ${ env . RESEND_API_KEY } ` } ,
166177 } )
167- if ( ! res . ok ) return { ok : false , error : `HTTP ${ res . status } ` }
168- return { ok : true }
178+ if ( ! res . ok ) return { ok : false , error : `HTTP ${ res . status } ` , severity : 'critical' }
179+ return { ok : true , severity : 'critical' }
169180 } ) ,
170181 timed ( async ( ) => {
171- if ( ! env . STRIPE_SECRET_KEY ) return { ok : false , error : 'STRIPE_SECRET_KEY not set' }
182+ if ( ! env . STRIPE_SECRET_KEY ) return { ok : false , error : 'STRIPE_SECRET_KEY not set' , severity : 'warning' }
172183 const res = await fetch ( 'https://api.stripe.com/v1/balance' , {
173184 headers : { Authorization : `Bearer ${ env . STRIPE_SECRET_KEY } ` } ,
174185 } )
175- if ( ! res . ok ) return { ok : false , error : `HTTP ${ res . status } ` }
176- return { ok : true }
186+ if ( ! res . ok ) return { ok : false , error : `HTTP ${ res . status } ` , severity : 'warning' }
187+ return { ok : true , severity : 'warning' }
177188 } ) ,
178189 timed ( async ( ) => {
179190 if ( ! env . SES_AWS_ACCESS_KEY_ID || ! env . SES_AWS_SECRET_ACCESS_KEY ) {
180- return { ok : false , error : 'SES credentials not set' }
191+ return { ok : false , error : 'SES credentials not set' , severity : 'warning' }
181192 }
182193 const result = await sesCheckCredentials (
183194 env . SES_AWS_ACCESS_KEY_ID ,
184195 env . SES_AWS_SECRET_ACCESS_KEY ,
185196 env . SES_REGION ?? 'us-east-1' ,
186197 )
187- if ( ! result . ok ) return { ok : false , error : result . detail }
198+ if ( ! result . ok ) return { ok : false , error : result . detail , severity : 'warning' }
188199 return {
189200 ok : true ,
201+ severity : 'warning' ,
190202 region : env . SES_REGION ?? 'us-east-1' ,
191203 from : env . SES_FROM_EMAIL ?? '(not set)' ,
192204 }
193205 } ) ,
194206 ] )
195207
196208 const checks : Record < string , CheckResult > = { d1, kv, resend, stripe, ses }
197- const allOk = Object . values ( checks ) . every ( ( ch ) => ch . ok )
209+ const criticalChecks = Object . values ( checks ) . filter ( ( ch ) => ( ch . severity ?? 'critical' ) === 'critical' )
210+ const warningChecks = Object . values ( checks ) . filter ( ( ch ) => ch . severity === 'warning' )
211+ const allOk = criticalChecks . every ( ( ch ) => ch . ok )
212+ const hasWarnings = warningChecks . some ( ( ch ) => ! ch . ok )
198213
199214 return c . json ( {
200215 ok : allOk ,
216+ has_warnings : hasWarnings ,
201217 checks,
202218 env : env . ENVIRONMENT ?? 'unknown' ,
203219 ts : new Date ( ) . toISOString ( ) ,
0 commit comments