wulf-pulse/lib/services/route53-factory.ts
lorentz 210f84d343 feat(24-01): implement Route 53 credential factory
- lib/services/route53-factory.ts: isRoute53Configured() / getRoute53Client()
  / resetRoute53Client(), following the veeam-factory.ts singleton shape
- No explicit credentials option passed to Route53Client — relies on the AWS
  SDK's default credential chain reading AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY
  from process.env, exactly how BWS injects them at the container entrypoint
- CLAUDE.md: document the AWS_* env-prefix exception in the integration table
- All 7 route53-factory.test.ts assertions pass; npx tsc --noEmit clean
2026-08-05 19:25:36 -04:00

47 lines
1.6 KiB
TypeScript

import { Route53Client } from '@aws-sdk/client-route-53';
let route53ClientInstance: Route53Client | null = null;
/**
* Check if AWS Route 53 credentials are configured.
*/
export function isRoute53Configured(): boolean {
return !!(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY);
}
/**
* Get or create the Route 53 client singleton instance.
*
* Intentionally does NOT pass an explicit `credentials` option — omitting it
* lets @aws-sdk/credential-provider-node's default credential chain read
* AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN from
* process.env automatically (fromEnv() is first in the chain). This is
* exactly how Bitwarden Secrets Manager (`bws run`) injects credentials at
* the docker-entrypoint.sh layer. Do NOT "fix" this by adding an explicit
* credentials object — see 24-RESEARCH.md Pitfall 1.
*/
export function getRoute53Client(): Route53Client {
if (!route53ClientInstance) {
if (!isRoute53Configured()) {
throw new Error(
'AWS credentials missing. Please set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (and AWS_REGION) environment variables.'
);
}
// Route 53 is a global service but the SDK still requires a signing
// region; us-east-1 is the conventional default AWS's own CLI/console use.
route53ClientInstance = new Route53Client({
region: process.env.AWS_REGION || 'us-east-1',
});
console.log('Route 53 client initialized');
}
return route53ClientInstance;
}
/**
* Reset the singleton instance (useful for testing).
*/
export function resetRoute53Client(): void {
route53ClientInstance = null;
}