front-integrations/README.md
Adam Moussa 4506e3cbf7
Some checks failed
Deploy / deploy (push) Has been cancelled
Document SAM template as IaC component in README (#23)
The README described the deployed AWS resources but never mentioned
template.yaml itself, the SAM project layout, the global function
defaults, the full parameter set, or the stack outputs. Add a
Project Structure section and an Infrastructure section so the
template.yaml infrastructure-as-code component is documented
accurately.
2026-07-10 16:07:12 -04:00

250 lines
10 KiB
Markdown

# front-integrations
![Python](https://img.shields.io/badge/Python-3776AB?logo=python&logoColor=white)
![AWS SAM](https://img.shields.io/badge/AWS-SAM-FF9900?logo=amazonaws&logoColor=white)
![Slack](https://img.shields.io/badge/Slack-integration-4A154B?logo=slack&logoColor=white)
![CI](https://github.com/Sea-Haven-Industries/front-integrations/actions/workflows/ci.yaml/badge.svg)
Front platform integrations for Sea Haven Industries. Two scheduled Lambdas:
1. **SLA Monitor** — checks Front conversations for SLA breaches and sends tiered Slack alerts
2. **User Sync** — pulls Google Workspace user profiles and syncs job title + phone to Front teammate custom fields
## Architecture
```
EventBridge (every 15 min, 8 AM-5 PM ET, Mon-Fri)
|
v
front-sla-monitor (Python 3.12, arm64)
|
+-- Secrets Manager --> front-integrations/front-api-token
+-- Secrets Manager --> front-integrations/slack-bot-token
|
+-- GET Front API /inboxes --> filter to configured inboxes
+-- GET Front API /inboxes/{id}/conversations --> open conversations
|
+-- DynamoDB (front-sla-alerts) --> dedup + first-run-of-day detection
|
+-- Morning (first run) --> summary to #front-sla-alerts
+-- Tier 1 (1 hr) --> Slack DM assignee or #front-sla-alerts
+-- Tier 2 (1 day) --> Slack DM Adam
EventBridge (weekdays 6:00 AM ET)
|
v
front-user-sync (Python 3.12, arm64)
|
+-- Secrets Manager --> front-integrations/google-service-account
+-- Secrets Manager --> front-integrations/front-api-token
|
+-- GET Google Admin Directory API --> list users in target OUs
+-- PATCH Front API /teammates/alt:email:{email} --> update custom_fields
```
## SLA Rules
| Tier | Threshold | Action |
|---|---|---|
| 1 | 1 business hour without reply | Slack DM the assignee, or post to #front-sla-alerts if unassigned |
| 2 | 1 business day without reply | Slack DM Adam |
Business time counts weekday hours only (Mon-Fri, Eastern time). Alerts are only sent during business hours (8 AM-5 PM ET). Overnight breaches produce a single morning summary.
## Project Structure
```
front-integrations/
├── template.yaml # AWS SAM template — all infrastructure (see below)
├── samconfig.toml.example # Deploy config template (copy to samconfig.toml, gitignored)
├── slack-app-manifest.yaml # Slack app manifest for the SLA Monitor bot
└── src/
├── sla_monitor/ # front-sla-monitor Lambda
│ ├── app.py # handler: app.handler
│ └── requirements.txt
└── user_sync/ # front-user-sync Lambda
├── app.py # handler: app.handler
└── requirements.txt
```
## AWS Resources
- **Stack:** `front-integrations` (SAM, us-east-1)
- **Lambda:** `front-sla-monitor` — Python 3.12, arm64, 256 MB, 300s timeout, 60-day log retention
- **Lambda:** `front-user-sync` — Python 3.12, arm64, 256 MB, 300s timeout, 60-day log retention
- **DynamoDB:** `front-sla-alerts` — alert history per conversation + monitor state, 7-day TTL
- **EventBridge:** SLA check every 15 min during business hours; user sync daily at 6 AM ET weekdays
## Infrastructure (`template.yaml`)
All of the resources above are declared as code in a single AWS SAM template,
[`template.yaml`](template.yaml) at the repository root (`Transform: AWS::Serverless-2016-10-31`).
It is the only source of infrastructure truth — there are no console-created or
CDK resources in this stack. `sam build` / `sam deploy` render it to a
CloudFormation stack named `front-integrations` in `us-east-1`.
### Global defaults
`Globals.Function` applies to every Lambda unless overridden per-function:
- Runtime `python3.12`, architecture `arm64`
- 256 MB memory, 300s timeout
- Permissions boundary `arn:aws:iam::328440206208:policy/seahaven-lambda-execution-boundary`
### Resources declared
| Logical ID | Type | Notes |
|---|---|---|
| `SlaMonitorFunction` | `AWS::Serverless::Function` | `front-sla-monitor`; `Schedule` event `cron(0/15 12-22 ? * MON-FRI *)` (UTC) |
| `UserSyncFunction` | `AWS::Serverless::Function` | `front-user-sync`; `Schedule` event `cron(0 11 ? * MON-FRI *)` (UTC) |
| `AlertsTable` | `AWS::DynamoDB::Table` | `front-sla-alerts`; PAY_PER_REQUEST, `conversationId` hash key, `ttl` TTL attribute |
| `SlaMonitorLogGroup`, `UserSyncLogGroup` | `AWS::Logs::LogGroup` | 60-day retention; each function `DependsOn` its group |
| 8 alarms | `AWS::CloudWatch::Alarm` | 3 per Lambda + 2 on the table — see [Monitoring](#monitoring) |
Each function carries a least-privilege inline IAM policy: `secretsmanager:GetSecretValue`
scoped to only the secret ARNs it reads. `SlaMonitorFunction` additionally gets a
`DynamoDBCrudPolicy` scoped to `AlertsTable`.
### Parameters
Secret ARNs and the alert channel are passed in at deploy time (via `parameter_overrides`
in `samconfig.toml` — see [`samconfig.toml.example`](samconfig.toml.example) — or the
`SAM_PARAMETER_OVERRIDES` Actions secret). They have no defaults and must be supplied:
| Parameter | Description |
|---|---|
| `FrontApiTokenSecretArn` | ARN of the Front API token secret |
| `SlackBotTokenSecretArn` | ARN of the Slack bot token secret |
| `GoogleServiceAccountSecretArn` | ARN of the Google service account key secret |
| `SlackAlertChannel` | Slack channel ID for `#front-sla-alerts` |
The remaining parameters (`AckSlaMinutes`, `ActionSlaMinutes`, `MonitorInboxes`,
`GoogleOrgUnits`, etc.) tune behavior and ship with sensible defaults — see
[Configuration](#configuration).
### Outputs
| Output | Value |
|---|---|
| `SlaMonitorFunctionArn` | `front-sla-monitor` Lambda ARN |
| `UserSyncFunctionArn` | `front-user-sync` Lambda ARN |
| `AlertsTableName` | `front-sla-alerts` table name |
## Monitoring
CloudWatch alarms publish to the shared `site-alerts` SNS topic (`arn:aws:sns:us-east-1:328440206208:site-alerts`). All alarms are ALARM-only (no OK/recovery notification) and treat missing data as `notBreaching`.
| Alarm | Metric | Trigger |
|---|---|---|
| `front-sla-monitor-errors` | Lambda `Errors` (Sum) | Any invocation error in a 5-min window |
| `front-sla-monitor-throttles` | Lambda `Throttles` (Sum) | Any throttled invocation in a 5-min window |
| `front-sla-monitor-duration` | Lambda `Duration` (Max) | Run exceeds 270s (90% of the 300s timeout) |
| `front-user-sync-errors` | Lambda `Errors` (Sum) | Any invocation error in a 5-min window |
| `front-user-sync-throttles` | Lambda `Throttles` (Sum) | Any throttled invocation in a 5-min window |
| `front-user-sync-duration` | Lambda `Duration` (Max) | Run exceeds 270s (90% of the 300s timeout) |
| `front-sla-alerts-read-throttle` | DynamoDB `ReadThrottleEvents` (Sum) | Any read throttle on the table |
| `front-sla-alerts-write-throttle` | DynamoDB `WriteThrottleEvents` (Sum) | Any write throttle on the table |
## Secrets (Secrets Manager)
| Secret | Purpose |
|---|---|
| `front-integrations/front-api-token` | Front API token (shared by both Lambdas) |
| `front-integrations/slack-bot-token` | Slack Bot User OAuth Token for SLA alerts |
| `front-integrations/google-service-account` | Google Cloud service account JSON key |
## Documentation
The canonical map of Sea Haven's AWS infrastructure lives in Confluence. This project's `front-integrations` stack is represented there as a Mermaid subgraph.
- **[AWS Architecture Map](https://seahaven.atlassian.net/wiki/spaces/IT/pages/1540098)** (Confluence, IT space, page 1540098)
## Setup
### 1. Create the Slack App
1. Go to https://api.slack.com/apps and create **Front SLA Monitor** (see `slack-app-manifest.yaml`)
2. Add Bot Token Scopes: `chat:write`, `users:read`, `users:read.email`
3. Install to workspace, copy Bot User OAuth Token
4. Create `#front-sla-alerts` channel and invite the bot
### 2. Create a Front API Token
1. Front > Settings > Developers > API tokens
2. Create a token with conversation read + teammate read/write scope
### 3. Set Up Google Workspace Service Account
1. Enable **Admin SDK API** in Google Cloud Console
2. Create service account `front-directory-sync`, create JSON key
3. Enable Domain-Wide Delegation, copy Client ID
4. In Google Workspace Admin: Security > API Controls > Domain-Wide Delegation
5. Add Client ID with scope: `https://www.googleapis.com/auth/admin.directory.user.readonly`
### 4. Create Custom Fields in Front
1. Settings > Custom Fields > Teammates tab
2. Create: **Job Title** (String) and **Phone** (String)
### 5. Store Secrets in AWS
```bash
aws secretsmanager create-secret \
--name "front-integrations/front-api-token" \
--secret-string "YOUR_FRONT_API_TOKEN" \
--region us-east-1
aws secretsmanager create-secret \
--name "front-integrations/slack-bot-token" \
--secret-string "xoxb-YOUR-SLACK-BOT-TOKEN" \
--region us-east-1
aws secretsmanager create-secret \
--name "front-integrations/google-service-account" \
--secret-string file://path-to-service-account-key.json \
--region us-east-1
```
### 6. Deploy
```bash
sam build
sam deploy --guided
```
Or push to `main` to trigger the GitHub Actions deploy workflow.
### 7. GitHub Actions Secrets
| Secret | Value |
|---|---|
| `AWS_DEPLOY_ROLE_ARN` | Org-wide OIDC deploy role (set after OIDC role is added) |
| `SAM_PARAMETER_OVERRIDES` | `FrontApiTokenSecretArn=arn:... SlackBotTokenSecretArn=arn:... GoogleServiceAccountSecretArn=arn:... SlackAlertChannel=CXXXXXXXXXX` |
## Manual Testing
```bash
aws lambda invoke --function-name front-sla-monitor --payload '{}' /dev/stdout --region us-east-1
aws lambda invoke --function-name front-user-sync --payload '{}' /dev/stdout --region us-east-1
```
## Configuration
### SLA Monitor
| Parameter | Default | Description |
|---|---|---|
| `AckSlaMinutes` | 60 | Business minutes before Tier 1 alert |
| `ActionSlaMinutes` | 1440 | Business minutes before Tier 2 alert |
| `AdamEmail` | adam@seahavenind.com | Tier 2 escalation recipient |
| `SlackAlertChannel` | — | Channel ID for broadcast alerts |
| `MonitorInboxes` | Triage,California,... | Inbox names to monitor (empty = all shared) |
| `SlaMonitorStartDate` | 2026-05-14 | Date monitoring begins |
### User Sync
| Parameter | Default | Description |
|---|---|---|
| `GoogleAdminEmail` | adam@seahavenind.com | Google Workspace admin to impersonate |
| `GoogleOrgUnits` | /Office/Scheduling,/Office/Operations | Org unit paths to sync |