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/conversation-log.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

40 lines
1.7 KiB
TypeScript

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
export class ConversationLogConstruct extends Construct {
public readonly table: dynamodb.Table;
public readonly unansweredTable: dynamodb.Table;
constructor(scope: Construct, id: string) {
super(scope, id);
this.table = new dynamodb.Table(this, 'Table', {
tableName: 'seahaven-conversations',
// PK: Slack user ID (e.g. U0123456789)
partitionKey: { name: 'userId', type: dynamodb.AttributeType.STRING },
// SK: ISO-8601 timestamp — enables range queries for session lookup
sortKey: { name: 'timestamp', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
removalPolicy: cdk.RemovalPolicy.RETAIN,
pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: true },
// TTL attribute — records are automatically expired after 90 days
timeToLiveAttribute: 'ttl',
});
// GSI for looking up all turns in a given Bedrock session (for context retrieval)
this.table.addGlobalSecondaryIndex({
indexName: 'sessionId-index',
partitionKey: { name: 'sessionId', type: dynamodb.AttributeType.STRING },
sortKey: { name: 'timestamp', type: dynamodb.AttributeType.STRING },
});
this.unansweredTable = new dynamodb.Table(this, 'UnansweredTable', {
tableName: 'seahaven-unanswered-questions',
partitionKey: { name: 'questionId', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
removalPolicy: cdk.RemovalPolicy.RETAIN,
timeToLiveAttribute: 'ttl',
});
}
}