Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
import * as cdk from 'aws-cdk-lib';
|
|
|
|
|
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
|
|
|
import * as rds from 'aws-cdk-lib/aws-rds';
|
|
|
|
|
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
|
|
|
import * as sqs from 'aws-cdk-lib/aws-sqs';
|
|
|
|
|
import * as cognito from 'aws-cdk-lib/aws-cognito';
|
|
|
|
|
import * as logs from 'aws-cdk-lib/aws-logs';
|
|
|
|
|
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
|
2026-05-20 19:07:49 -04:00
|
|
|
import * as sns from 'aws-cdk-lib/aws-sns';
|
|
|
|
|
import * as snsSubscriptions from 'aws-cdk-lib/aws-sns-subscriptions';
|
|
|
|
|
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
|
|
|
|
|
import * as cloudwatchActions from 'aws-cdk-lib/aws-cloudwatch-actions';
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
import { Construct } from 'constructs';
|
2026-06-12 18:04:53 -04:00
|
|
|
import { EnvConfig } from './config';
|
|
|
|
|
|
|
|
|
|
export interface FoundationStackProps extends cdk.StackProps {
|
|
|
|
|
config: EnvConfig;
|
|
|
|
|
}
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
|
|
|
|
|
export class FoundationStack extends cdk.Stack {
|
|
|
|
|
public readonly vpc: ec2.IVpc;
|
|
|
|
|
public readonly lambdaSecurityGroup: ec2.ISecurityGroup;
|
|
|
|
|
public readonly dbSecret: secretsmanager.ISecret;
|
2026-06-12 18:44:42 -04:00
|
|
|
public readonly dbCluster: rds.IDatabaseCluster;
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
public readonly uploadsBucket: s3.IBucket;
|
|
|
|
|
public readonly generatedBucket: s3.IBucket;
|
|
|
|
|
public readonly libraryBucket: s3.IBucket;
|
|
|
|
|
public readonly jobsQueue: sqs.IQueue;
|
|
|
|
|
public readonly userPool: cognito.IUserPool;
|
2026-05-20 19:07:49 -04:00
|
|
|
public readonly alarmTopic: sns.ITopic;
|
2026-05-20 18:51:31 -04:00
|
|
|
public readonly webClientId: string;
|
|
|
|
|
public readonly mobileClientId: string;
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
|
2026-06-12 18:04:53 -04:00
|
|
|
constructor(scope: Construct, id: string, props: FoundationStackProps) {
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
super(scope, id, props);
|
2026-06-12 18:04:53 -04:00
|
|
|
const { config } = props;
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
|
|
|
|
|
// VPC: 2 AZs, public + private subnets, single NAT Gateway
|
|
|
|
|
this.vpc = new ec2.Vpc(this, 'Vpc', {
|
2026-06-12 18:04:53 -04:00
|
|
|
vpcName: `proposal-system-vpc${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
maxAzs: 2,
|
|
|
|
|
natGateways: 1,
|
|
|
|
|
subnetConfiguration: [
|
|
|
|
|
{
|
|
|
|
|
name: 'public',
|
|
|
|
|
subnetType: ec2.SubnetType.PUBLIC,
|
|
|
|
|
cidrMask: 24,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'private',
|
|
|
|
|
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
|
|
|
|
|
cidrMask: 24,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// VPC Endpoints
|
|
|
|
|
this.vpc.addGatewayEndpoint('S3Endpoint', {
|
|
|
|
|
service: ec2.GatewayVpcEndpointAwsService.S3,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.vpc.addInterfaceEndpoint('SecretsManagerEndpoint', {
|
|
|
|
|
service: ec2.InterfaceVpcEndpointAwsService.SECRETS_MANAGER,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Security Groups
|
|
|
|
|
this.lambdaSecurityGroup = new ec2.SecurityGroup(this, 'LambdaSg', {
|
|
|
|
|
vpc: this.vpc,
|
2026-06-12 18:04:53 -04:00
|
|
|
securityGroupName: `proposal-system-lambda-sg${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
description: 'Security group for proposal system Lambda functions',
|
|
|
|
|
allowAllOutbound: true,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const rdsSg = new ec2.SecurityGroup(this, 'RdsSg', {
|
|
|
|
|
vpc: this.vpc,
|
2026-06-12 18:04:53 -04:00
|
|
|
securityGroupName: `proposal-system-rds-sg${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
description: 'Security group for proposal system RDS instance',
|
|
|
|
|
allowAllOutbound: false,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
rdsSg.addIngressRule(
|
|
|
|
|
this.lambdaSecurityGroup,
|
|
|
|
|
ec2.Port.tcp(5432),
|
|
|
|
|
'Allow PostgreSQL from Lambda SG'
|
|
|
|
|
);
|
|
|
|
|
|
2026-06-12 18:44:42 -04:00
|
|
|
// Aurora PostgreSQL Serverless v2 — pgvector store for the Bedrock Knowledge Base.
|
|
|
|
|
// PR3: replaced the RDS instance + OpenSearch Serverless with Aurora + pgvector
|
|
|
|
|
// (kills the AOSS OCU floor; scales toward 0 ACU when idle). Data API is required
|
|
|
|
|
// by Bedrock Knowledge Bases to query the vector table.
|
|
|
|
|
const dbCluster = new rds.DatabaseCluster(this, 'Database', {
|
|
|
|
|
clusterIdentifier: `proposal-system-db${config.stackSuffix}`,
|
|
|
|
|
engine: rds.DatabaseClusterEngine.auroraPostgres({
|
|
|
|
|
version: rds.AuroraPostgresEngineVersion.VER_15_4,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
}),
|
|
|
|
|
vpc: this.vpc,
|
|
|
|
|
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
|
|
|
securityGroups: [rdsSg],
|
2026-06-12 18:44:42 -04:00
|
|
|
writer: rds.ClusterInstance.serverlessV2('writer'),
|
|
|
|
|
serverlessV2MinCapacity: 0.5,
|
|
|
|
|
serverlessV2MaxCapacity: 4,
|
|
|
|
|
enableDataApi: true,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
storageEncrypted: true,
|
2026-06-12 18:44:42 -04:00
|
|
|
backup: { retention: cdk.Duration.days(7) },
|
2026-06-12 18:04:53 -04:00
|
|
|
deletionProtection: config.retainData,
|
|
|
|
|
removalPolicy: config.retainData ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
|
2026-06-12 18:44:42 -04:00
|
|
|
defaultDatabaseName: 'proposals',
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
credentials: rds.Credentials.fromGeneratedSecret('proposalsadmin', {
|
2026-06-12 18:04:53 -04:00
|
|
|
secretName: `proposal-system/db-credentials${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
2026-06-12 18:44:42 -04:00
|
|
|
this.dbSecret = dbCluster.secret!;
|
|
|
|
|
this.dbCluster = dbCluster;
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
|
|
|
|
|
// S3 Buckets
|
2026-05-27 17:45:11 -04:00
|
|
|
// Fix: INF-M5 — enforce HTTPS-only access on all S3 buckets
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
this.uploadsBucket = new s3.Bucket(this, 'UploadsBucket', {
|
2026-06-12 18:04:53 -04:00
|
|
|
bucketName: `proposal-system-uploads-${this.account}${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
encryption: s3.BucketEncryption.S3_MANAGED,
|
audit: fix all Critical and High security/reliability issues across monorepo
6-domain audit (API, web, mobile, lambdas, infra, QA) with fixes:
API security: scope internal API key middleware to allowed paths only,
return 401 on invalid key instead of falling through, remove unvalidated
JWT code path, sanitize error messages, add UpdateProposal validator,
remove status field from UpdateProposalRequest to prevent over-posting,
log swallowed exceptions in ProposalService.
Infrastructure: enforce SSL on all S3 buckets, encrypt SQS queues,
enable optional MFA on Cognito, add API Gateway access logging.
Lambdas: fix _retry_request undefined variable across all 4 Lambdas,
re-raise exceptions in pdf-extract/pdf-generate instead of swallowing,
add idempotency guard to suggestions Lambda.
Web: add ErrorBoundary, add auth loading state to ProtectedRoute,
add mutation error toasts in AdminWorkspace, fix dead Cognito link.
Mobile: add mutex to offline queue processing, distinguish permanent
vs retryable failures, register all screens for both roles, log sync
errors.
Swagger/OpenAPI: add Swashbuckle with JWT bearer security definition,
add ProducesResponseType attributes to key endpoints.
Includes AUDIT-REPORT.md with complete findings and CLAUDE.md project
instructions.
2026-05-27 15:33:27 -04:00
|
|
|
enforceSSL: true,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
versioned: true,
|
|
|
|
|
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
|
|
|
lifecycleRules: [
|
|
|
|
|
{
|
|
|
|
|
transitions: [
|
|
|
|
|
{
|
|
|
|
|
storageClass: s3.StorageClass.INFREQUENT_ACCESS,
|
|
|
|
|
transitionAfter: cdk.Duration.days(90),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
cors: [
|
|
|
|
|
{
|
|
|
|
|
allowedMethods: [s3.HttpMethods.PUT, s3.HttpMethods.POST],
|
2026-06-12 18:04:53 -04:00
|
|
|
allowedOrigins: config.s3CorsOrigins,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
allowedHeaders: ['*'],
|
|
|
|
|
maxAge: 3600,
|
|
|
|
|
},
|
|
|
|
|
],
|
2026-06-12 18:04:53 -04:00
|
|
|
removalPolicy: config.retainData ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
});
|
|
|
|
|
cdk.Tags.of(this.uploadsBucket).add('Purpose', 'Vendor PDFs and dispatcher attachments');
|
|
|
|
|
cdk.Tags.of(this.uploadsBucket).add('ManagedBy', 'proposal-system');
|
|
|
|
|
|
|
|
|
|
this.generatedBucket = new s3.Bucket(this, 'GeneratedBucket', {
|
2026-06-12 18:04:53 -04:00
|
|
|
bucketName: `proposal-system-generated-${this.account}${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
encryption: s3.BucketEncryption.S3_MANAGED,
|
2026-05-27 17:45:11 -04:00
|
|
|
enforceSSL: true, // Fix: INF-M5
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
versioned: true,
|
|
|
|
|
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
2026-06-12 18:04:53 -04:00
|
|
|
removalPolicy: config.retainData ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
});
|
|
|
|
|
cdk.Tags.of(this.generatedBucket).add('Purpose', 'Generated proposal PDFs');
|
|
|
|
|
cdk.Tags.of(this.generatedBucket).add('ManagedBy', 'proposal-system');
|
|
|
|
|
|
|
|
|
|
this.libraryBucket = new s3.Bucket(this, 'LibraryBucket', {
|
2026-06-12 18:04:53 -04:00
|
|
|
bucketName: `proposal-system-library-${this.account}${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
encryption: s3.BucketEncryption.S3_MANAGED,
|
2026-05-27 17:45:11 -04:00
|
|
|
enforceSSL: true, // Fix: INF-M5
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
versioned: true,
|
|
|
|
|
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
2026-06-12 18:04:53 -04:00
|
|
|
removalPolicy: config.retainData ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
});
|
|
|
|
|
cdk.Tags.of(this.libraryBucket).add('Purpose', 'Historical proposal library for RAG');
|
|
|
|
|
cdk.Tags.of(this.libraryBucket).add('ManagedBy', 'proposal-system');
|
|
|
|
|
|
|
|
|
|
// SQS Queue + DLQ
|
|
|
|
|
const dlq = new sqs.Queue(this, 'JobsDlq', {
|
2026-06-12 18:04:53 -04:00
|
|
|
queueName: `proposal-system-jobs-dlq${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
retentionPeriod: cdk.Duration.days(14),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.jobsQueue = new sqs.Queue(this, 'JobsQueue', {
|
2026-06-12 18:04:53 -04:00
|
|
|
queueName: `proposal-system-jobs${config.stackSuffix}`,
|
2026-05-20 18:51:31 -04:00
|
|
|
visibilityTimeout: cdk.Duration.seconds(720),
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
deadLetterQueue: {
|
|
|
|
|
queue: dlq,
|
|
|
|
|
maxReceiveCount: 3,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Cognito User Pool
|
|
|
|
|
const userPool = new cognito.UserPool(this, 'UserPool', {
|
2026-06-12 18:04:53 -04:00
|
|
|
userPoolName: `proposal-system-auth${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
selfSignUpEnabled: false,
|
|
|
|
|
signInAliases: { email: true },
|
|
|
|
|
standardAttributes: {
|
|
|
|
|
email: { required: true, mutable: true },
|
|
|
|
|
fullname: { required: true, mutable: true },
|
|
|
|
|
},
|
|
|
|
|
passwordPolicy: {
|
|
|
|
|
minLength: 12,
|
|
|
|
|
requireUppercase: true,
|
|
|
|
|
requireLowercase: true,
|
|
|
|
|
requireDigits: true,
|
|
|
|
|
requireSymbols: false,
|
|
|
|
|
},
|
|
|
|
|
accountRecovery: cognito.AccountRecovery.EMAIL_ONLY,
|
2026-06-12 18:04:53 -04:00
|
|
|
removalPolicy: config.retainData ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.userPool = userPool;
|
|
|
|
|
|
|
|
|
|
// Cognito Groups
|
|
|
|
|
new cognito.CfnUserPoolGroup(this, 'DispatchersGroup', {
|
|
|
|
|
userPoolId: userPool.userPoolId,
|
|
|
|
|
groupName: 'dispatchers',
|
|
|
|
|
description: 'Dispatchers who submit proposal requests',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
new cognito.CfnUserPoolGroup(this, 'AdminsGroup', {
|
|
|
|
|
userPoolId: userPool.userPoolId,
|
|
|
|
|
groupName: 'admins',
|
|
|
|
|
description: 'Admins who review and approve proposals',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
new cognito.CfnUserPoolGroup(this, 'SysadminsGroup', {
|
|
|
|
|
userPoolId: userPool.userPoolId,
|
|
|
|
|
groupName: 'sysadmins',
|
|
|
|
|
description: 'System administrators',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Cognito Domain
|
|
|
|
|
userPool.addDomain('CognitoDomain', {
|
2026-06-12 18:04:53 -04:00
|
|
|
cognitoDomain: { domainPrefix: config.cognitoDomainPrefix },
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Web App Client (PKCE)
|
2026-05-20 11:36:51 -04:00
|
|
|
const webClient = userPool.addClient('WebClient', {
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
userPoolClientName: 'proposal-system-web',
|
|
|
|
|
generateSecret: false,
|
|
|
|
|
authFlows: {
|
|
|
|
|
userSrp: true,
|
|
|
|
|
},
|
|
|
|
|
oAuth: {
|
|
|
|
|
flows: { authorizationCodeGrant: true },
|
|
|
|
|
scopes: [
|
|
|
|
|
cognito.OAuthScope.OPENID,
|
|
|
|
|
cognito.OAuthScope.EMAIL,
|
|
|
|
|
cognito.OAuthScope.PROFILE,
|
|
|
|
|
],
|
2026-06-12 18:04:53 -04:00
|
|
|
callbackUrls: config.webCallbackUrls,
|
|
|
|
|
logoutUrls: config.webLogoutUrls,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-20 18:51:31 -04:00
|
|
|
this.webClientId = webClient.userPoolClientId;
|
|
|
|
|
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
// Mobile App Client (PKCE)
|
2026-05-20 11:36:51 -04:00
|
|
|
const mobileClient = userPool.addClient('MobileClient', {
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
userPoolClientName: 'proposal-system-mobile',
|
|
|
|
|
generateSecret: false,
|
|
|
|
|
authFlows: {
|
|
|
|
|
userSrp: true,
|
|
|
|
|
},
|
|
|
|
|
oAuth: {
|
|
|
|
|
flows: { authorizationCodeGrant: true },
|
|
|
|
|
scopes: [
|
|
|
|
|
cognito.OAuthScope.OPENID,
|
|
|
|
|
cognito.OAuthScope.EMAIL,
|
|
|
|
|
cognito.OAuthScope.PROFILE,
|
|
|
|
|
],
|
2026-05-20 11:36:51 -04:00
|
|
|
callbackUrls: ['com.seahavenind.proposals://auth/callback'],
|
|
|
|
|
logoutUrls: ['com.seahavenind.proposals://auth/logout'],
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-20 19:09:35 -04:00
|
|
|
this.webClientId = webClient.userPoolClientId;
|
2026-05-20 18:51:31 -04:00
|
|
|
this.mobileClientId = mobileClient.userPoolClientId;
|
|
|
|
|
|
2026-05-20 19:07:49 -04:00
|
|
|
// SNS Alarm Topic
|
|
|
|
|
const alarmTopic = new sns.Topic(this, 'AlarmTopic', {
|
2026-06-12 18:04:53 -04:00
|
|
|
topicName: `proposal-system-alarms${config.stackSuffix}`,
|
2026-05-20 19:07:49 -04:00
|
|
|
displayName: 'Proposal System Alarms',
|
|
|
|
|
});
|
|
|
|
|
alarmTopic.addSubscription(
|
2026-06-12 18:04:53 -04:00
|
|
|
new snsSubscriptions.EmailSubscription(config.alarmsEmail),
|
2026-05-20 19:07:49 -04:00
|
|
|
);
|
|
|
|
|
this.alarmTopic = alarmTopic;
|
|
|
|
|
|
|
|
|
|
const alarmAction = new cloudwatchActions.SnsAction(alarmTopic);
|
|
|
|
|
|
|
|
|
|
// DLQ Alarm: any message landing in DLQ indicates a processing failure
|
|
|
|
|
const dlqAlarm = new cloudwatch.Alarm(this, 'DlqDepthAlarm', {
|
2026-06-12 18:04:53 -04:00
|
|
|
alarmName: `proposal-system-dlq-depth${config.stackSuffix}`,
|
2026-05-20 19:07:49 -04:00
|
|
|
alarmDescription: 'Messages in DLQ — SQS processing failures',
|
|
|
|
|
metric: dlq.metricApproximateNumberOfMessagesVisible({
|
|
|
|
|
period: cdk.Duration.minutes(1),
|
|
|
|
|
}),
|
|
|
|
|
threshold: 0,
|
|
|
|
|
comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
|
|
|
|
|
evaluationPeriods: 1,
|
|
|
|
|
treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
|
|
|
|
|
});
|
|
|
|
|
dlqAlarm.addAlarmAction(alarmAction);
|
|
|
|
|
|
|
|
|
|
// RDS Alarms
|
|
|
|
|
const rdsAlarms = [
|
|
|
|
|
new cloudwatch.Alarm(this, 'RdsCpuAlarm', {
|
2026-06-12 18:04:53 -04:00
|
|
|
alarmName: `proposal-system-rds-cpu${config.stackSuffix}`,
|
2026-05-20 19:07:49 -04:00
|
|
|
alarmDescription: 'RDS CPU utilization above 80%',
|
2026-06-12 18:44:42 -04:00
|
|
|
metric: dbCluster.metricCPUUtilization({ period: cdk.Duration.minutes(5) }),
|
2026-05-20 19:07:49 -04:00
|
|
|
threshold: 80,
|
|
|
|
|
evaluationPeriods: 3,
|
|
|
|
|
treatMissingData: cloudwatch.TreatMissingData.BREACHING,
|
|
|
|
|
}),
|
|
|
|
|
new cloudwatch.Alarm(this, 'RdsConnectionsAlarm', {
|
2026-06-12 18:04:53 -04:00
|
|
|
alarmName: `proposal-system-rds-connections${config.stackSuffix}`,
|
2026-05-20 19:07:49 -04:00
|
|
|
alarmDescription: 'RDS database connections above 80',
|
2026-06-12 18:44:42 -04:00
|
|
|
metric: dbCluster.metricDatabaseConnections({ period: cdk.Duration.minutes(5) }),
|
2026-05-20 19:07:49 -04:00
|
|
|
threshold: 80,
|
|
|
|
|
evaluationPeriods: 2,
|
|
|
|
|
treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
|
|
|
|
|
}),
|
2026-06-12 18:44:42 -04:00
|
|
|
// Aurora storage auto-scales (no FreeStorageSpace); freeable memory is the
|
|
|
|
|
// meaningful health signal for a Serverless v2 cluster.
|
|
|
|
|
new cloudwatch.Alarm(this, 'RdsLowMemoryAlarm', {
|
|
|
|
|
alarmName: `proposal-system-rds-low-memory${config.stackSuffix}`,
|
|
|
|
|
alarmDescription: 'Aurora freeable memory below 256 MB',
|
|
|
|
|
metric: dbCluster.metricFreeableMemory({ period: cdk.Duration.minutes(5) }),
|
|
|
|
|
threshold: 256_000_000,
|
2026-05-20 19:07:49 -04:00
|
|
|
comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
|
2026-06-12 18:44:42 -04:00
|
|
|
evaluationPeriods: 3,
|
|
|
|
|
treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
|
2026-05-20 19:07:49 -04:00
|
|
|
}),
|
|
|
|
|
];
|
|
|
|
|
for (const alarm of rdsAlarms) {
|
|
|
|
|
alarm.addAlarmAction(alarmAction);
|
|
|
|
|
}
|
|
|
|
|
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
// CloudWatch Log Groups
|
|
|
|
|
const logGroupNames = [
|
|
|
|
|
'proposal-system-api',
|
|
|
|
|
'proposal-system-pdf-extract',
|
|
|
|
|
'proposal-system-pdf-generate',
|
|
|
|
|
'proposal-system-library-ingest',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
for (const name of logGroupNames) {
|
|
|
|
|
new logs.LogGroup(this, `LogGroup-${name}`, {
|
2026-06-12 18:04:53 -04:00
|
|
|
logGroupName: `/aws/lambda/${name}${config.stackSuffix}`,
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
retention: logs.RetentionDays.TWO_MONTHS,
|
|
|
|
|
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Outputs
|
|
|
|
|
new cdk.CfnOutput(this, 'VpcId', { value: this.vpc.vpcId });
|
|
|
|
|
new cdk.CfnOutput(this, 'UserPoolId', { value: userPool.userPoolId });
|
|
|
|
|
new cdk.CfnOutput(this, 'UserPoolArn', { value: userPool.userPoolArn });
|
|
|
|
|
new cdk.CfnOutput(this, 'UploadsBucketName', { value: this.uploadsBucket.bucketName });
|
|
|
|
|
new cdk.CfnOutput(this, 'GeneratedBucketName', { value: this.generatedBucket.bucketName });
|
|
|
|
|
new cdk.CfnOutput(this, 'LibraryBucketName', { value: this.libraryBucket.bucketName });
|
|
|
|
|
new cdk.CfnOutput(this, 'JobsQueueUrl', { value: this.jobsQueue.queueUrl });
|
|
|
|
|
new cdk.CfnOutput(this, 'DbSecretArn', { value: this.dbSecret.secretArn });
|
2026-05-20 11:36:51 -04:00
|
|
|
new cdk.CfnOutput(this, 'WebClientId', { value: webClient.userPoolClientId });
|
|
|
|
|
new cdk.CfnOutput(this, 'MobileClientId', { value: mobileClient.userPoolClientId });
|
2026-05-20 19:07:49 -04:00
|
|
|
new cdk.CfnOutput(this, 'AlarmTopicArn', { value: alarmTopic.topicArn });
|
Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model
Phase 0 of proposal-system: complete project setup including:
- CDK infrastructure (3 stacks: foundation, compute, frontend)
- .NET 8 solution with Clean Architecture (Domain, Application, Infrastructure, Api)
- EF Core data model (PostgreSQL) with all entities
- Python Lambda placeholders (pdf-extract, pdf-generate, library-ingest)
- React 19 web frontend scaffold (Vite + MUI)
- React Native mobile placeholder
- Shared TypeScript API contracts
- GitHub Actions CI/CD (ci.yaml + deploy.yaml)
- OIDC deploy role (githubdeploy-proposal-system)
- Dependabot configuration
- Cognito User Pool with Google OAuth, PKCE clients, groups
2026-05-16 18:40:46 -04:00
|
|
|
}
|
|
|
|
|
}
|