feat(mbe): use generated client for type safety#32
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR replaces manual HTTP/TLS logic with a generated, type-safe API client and centralizes health response types.
- Introduce shared
PingResponseTypeandVersionResponseTypefor health endpoints - Remove legacy certificate utilities and inline health route setup
- Swap raw
superagentcalls forbuildApiClient-based requests and add version route
Reviewed Changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/types/health.ts | Add shared io-ts types for ping and version responses |
| src/shared/appUtils.ts | Remove readCertificates and setupHealthCheckRoutes |
| src/routes/enclaved.ts | Update mounting of keygen router (drop /api prefix) |
| src/masterBitgoExpress/routers/index.ts | Include EnclavedExpressApiSpec in combined spec |
| src/masterBitgoExpress/routers/healthCheck.ts | Use imported health types and simplify router creation |
| src/masterBitgoExpress/routers/enclavedExpressHealth.ts | Replace raw HTTPS logic with generated client and add version route |
| src/masterBitgoExpress/enclavedExpressClient.ts | Build and use a type-safe API client for all enclaved calls |
| src/enclavedBitgoExpress/routers/enclavedApiSpec.ts | Prefix key/multisig routes with /api |
| src/enclavedBitgoExpress/routers/index.ts | Export consolidated EnclavedApiSpec |
| src/tests/masterBitgoExpress/sendMany.test.ts | Update error assertion for missing enclave config |
| src/tests/masterBitgoExpress/generateWallet.test.ts | Update error assertion for missing enclave config |
| masterBitgoExpress.json | Extend OpenAPI with shared health schemas and version endpoint |
Comments suppressed due to low confidence (5)
src/enclavedBitgoExpress/routers/index.ts:1
- [nitpick] The constant name
EnclavedAPiSpecuses inconsistent casing (APivsApi). Rename it toEnclavedApiSpecfor clarity and consistency.
import { EnclavedAPiSpec as ApiSpec } from './enclavedApiSpec';
src/masterBitgoExpress/routers/enclavedExpressHealth.ts:88
- The new version endpoint (
/version/enclavedExpress) lacks corresponding tests. Consider adding unit or integration tests to verify its behavior.
router.get('v1.enclaved.version', [
src/routes/enclaved.ts:18
- Removing the
/apiprefix here may break existing routes. Consider mounting the keygen router with a base path, e.g.,app.use('/api', createKeyGenRouter(config));.
app.use(createKeyGenRouter(config));
src/masterBitgoExpress/enclavedExpressClient.ts:153
- The client is referencing
v1.health.pingbut the generated spec definesv1.enclaved.ping. Update the key to matchthis.apiClient['v1.enclaved.ping'].
let request = this.apiClient['v1.health.ping'].post({});
src/masterBitgoExpress/enclavedExpressClient.ts:176
- The client is referencing
v1.health.versionbut the spec definesv1.enclaved.version. Update this tothis.apiClient['v1.enclaved.version'].
let request = this.apiClient['v1.health.version'].get({});
d8bed21 to
225d143
Compare
225d143 to
3cb0dc2
Compare
| expressApp(invalidConfig as MasterExpressConfig); | ||
| assert(false, 'Expected error to be thrown when enclaved express client is not configured'); | ||
| } catch (e) { | ||
| (e as Error).message.should.equal('enclavedExpressUrl and enclavedExpressCert are required'); |
There was a problem hiding this comment.
wait im v confused. why is this removing the calls to the actual API?
There was a problem hiding this comment.
because the client is constructed when the routes are configured, so it'll fail here: https://github.com/BitGo/enclaved-bitgo-express/blob/3cb0dc2f3cee8eee5b5644abbc9360f9847379e5/src/masterBitgoExpress/enclavedExpressClient.ts#L62
There was a problem hiding this comment.
what i mean is, how is this test defining the client to make calls to generate wallet?
There was a problem hiding this comment.
for this case (when the config is invalid), the app won't startup. I can modify it so that the client is only created during the request, so it would fail then.
| coin: coin, | ||
| type: 'independent', |
There was a problem hiding this comment.
because it's not used in the actual request. Look at the Api spec for Enclaved Express.
There was a problem hiding this comment.
'v1.key.independent': {
post: httpRoute({
method: 'POST',
path: '/api/{coin}/key/independent',
request: httpRequest({
params: {
coin: t.string,
},
body: IndependentKeyRequest,
}),
response: IndependentKeyResponse,
description: 'Generate an independent key',
}),
},
| try { | ||
| expressApp(invalidConfig as MasterExpressConfig); | ||
| assert(false, 'Expected error to be thrown when enclaved express client is not configured'); | ||
| } catch (error) { | ||
| (error as Error).message.should.equal( | ||
| 'enclavedExpressUrl and enclavedExpressCert are required', | ||
| ); | ||
| } |
There was a problem hiding this comment.
?? why is this just calling the app?
There was a problem hiding this comment.
see above.
| let response; | ||
| if (cfg.tlsMode === TlsMode.MTLS) { | ||
| // Use Master Express's own certificate as client cert when connecting to Enclaved Express | ||
| const httpsAgent = new https.Agent({ | ||
| rejectUnauthorized: !cfg.allowSelfSigned, | ||
| ca: cfg.enclavedExpressCert, | ||
| // Provide client certificate for mTLS | ||
| key: cfg.tlsKey, | ||
| cert: cfg.tlsCert, | ||
| }); |
There was a problem hiding this comment.
where are the cert's being passed with the api client?
There was a problem hiding this comment.
| export async function readCertificates( | ||
| keyPath: string, | ||
| crtPath: string, | ||
| ): Promise<{ key: string; cert: string }> { | ||
| const privateKeyPromise = fs.promises.readFile(keyPath, 'utf8'); | ||
| const certificatePromise = fs.promises.readFile(crtPath, 'utf8'); | ||
| const [key, cert] = await Promise.all([privateKeyPromise, certificatePromise]); | ||
| return { key, cert }; | ||
| } |
There was a problem hiding this comment.
where are the cert's being read now..?
There was a problem hiding this comment.
I did test if this works with certificates loaded.
Ticket: WP-000000