07fbeea09b
Ersätter den tidigare webappen på denna branch med ett fokuserat monorepo: - apps/mobile: Expo/React Native med tre vyer (Welcome, Chat, Paywall), Cognito hosted UI-inloggning (Apple/Google/e-post) och In-App Purchase/Play Billing via en gemensam purchases-modul. - services/api: en enda Lambda-backend — OpenAI Responses API med Markdown-kunskapsbas som systeminstruktioner, free tier-gräns i PostgreSQL (HTTP 402 -> paywall) och kvittoverifiering bakom ett delat PaymentProvider-interface (Apple/Google, Stripe kan läggas till för webb senare). - infra: AWS CDK-stack med API Gateway (JWT-authorizer), Lambda, Cognito, Aurora Serverless v2 och Secrets Manager. - db/migrations: minimal datamodell (users + usage), inga konversationer sparas. - GitHub Actions: CI (lint, typecheck, test) och deploy från main. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0118DaxZR36RpnY524vRqx3z
21 lines
753 B
TypeScript
21 lines
753 B
TypeScript
import { GetSecretValueCommand, SecretsManagerClient } from '@aws-sdk/client-secrets-manager';
|
|
|
|
const client = new SecretsManagerClient({});
|
|
const cache = new Map<string, Record<string, string>>();
|
|
|
|
/**
|
|
* Fetches a JSON secret from AWS Secrets Manager and caches it for the
|
|
* lifetime of the Lambda container.
|
|
*/
|
|
export async function getSecret(arn: string): Promise<Record<string, string>> {
|
|
const cached = cache.get(arn);
|
|
if (cached) return cached;
|
|
const result = await client.send(new GetSecretValueCommand({ SecretId: arn }));
|
|
if (!result.SecretString) {
|
|
throw new Error(`Secret ${arn} has no string value`);
|
|
}
|
|
const parsed = JSON.parse(result.SecretString) as Record<string, string>;
|
|
cache.set(arn, parsed);
|
|
return parsed;
|
|
}
|