This repository has been archived on 2026-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
seahaven-slack-bot/lib/constructs/socket-mode.ts
Adam Moussa 006dbf7c6b feat: Alex rollout — persona, Socket Mode, payments, channels, App Home, unanswered questions
- Rename bot to Alex with friendly/professional persona (Bedrock Agent instruction rewrite)
- Replace HTTP webhook Lambda with ECS Fargate Socket Mode service (persistent WebSocket)
- Add payment/invoice lookup via PaymentsDashboard table (vendor, invoice, check search)
- Switch from manual SiteAssignments to auto-populated verified-sites table
- Add channel support via app_mention events (threaded replies)
- Add App Home tab with Block Kit capabilities view
- Add unanswered questions logging to seahaven-unanswered-questions DynamoDB table
- Fix pre-existing compliance: add arm64 + 60-day log retention to all Lambdas
- Remove webhook Lambda and seed-sites script (both obsolete)
2026-04-30 16:38:54 -04:00

67 lines
2.1 KiB
TypeScript

import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as logs from 'aws-cdk-lib/aws-logs';
import * as path from 'path';
export interface SocketModeProps {
vpc: ec2.IVpc;
processorLambda: lambda.IFunction;
appHomeLambda: lambda.IFunction;
}
export class SocketModeConstruct extends Construct {
constructor(scope: Construct, id: string, props: SocketModeProps) {
super(scope, id);
const appTokenSecret = secretsmanager.Secret.fromSecretNameV2(
this, 'AppTokenSecret', 'seahaven/slack/app-level-token',
);
const cluster = new ecs.Cluster(this, 'Cluster', {
clusterName: 'seahaven-socket-mode',
vpc: props.vpc,
});
const taskDef = new ecs.FargateTaskDefinition(this, 'TaskDef', {
memoryLimitMiB: 512,
cpu: 256,
runtimePlatform: {
cpuArchitecture: ecs.CpuArchitecture.ARM64,
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
},
});
taskDef.addContainer('socket-mode', {
image: ecs.ContainerImage.fromAsset(
path.join(__dirname, '../../services/socket-mode'),
),
environment: {
APP_TOKEN_SECRET_ARN: appTokenSecret.secretArn,
PROCESSOR_FUNCTION_NAME: props.processorLambda.functionName,
APP_HOME_FUNCTION_NAME: props.appHomeLambda.functionName,
},
logging: ecs.LogDrivers.awsLogs({
streamPrefix: 'socket-mode',
logRetention: logs.RetentionDays.TWO_MONTHS,
}),
});
appTokenSecret.grantRead(taskDef.taskRole);
props.processorLambda.grantInvoke(taskDef.taskRole);
props.appHomeLambda.grantInvoke(taskDef.taskRole);
new ecs.FargateService(this, 'Service', {
serviceName: 'seahaven-socket-mode',
cluster,
taskDefinition: taskDef,
desiredCount: 1,
minHealthyPercent: 100,
maxHealthyPercent: 200,
assignPublicIp: false,
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
});
}
}