- Switch runtime to nodejs22.x and architecture to arm64
- Add explicit CloudWatch log groups with 60-day retention for all Lambdas
- Rename SQS queue from payments-contractor-batch to payments-payroll-batch
(now handles both employee and contractor batching)
- Remove stale comment
SES receives Gusto payroll emails at payroll@int.seahaven.com, stores
to S3, Lambda parses and posts a combined Slack notification (employee
payroll + contractor payments in one message) after a 10-minute SQS
batching window.
Removes Aurora Serverless, notifyPayroll Lambda, and @aws-sdk/client-rds-data.
Adds mailparser, SQS delay queue, and processPayrollEmail Lambda.
Queries Aurora for new payroll runs and contractor payments, sends
formatted Slack message with gross pay breakdown and total bank
withdrawal amount. Runs weekdays at 2pm ET, tracks notified payrolls
in DynamoDB to avoid duplicates.
Adds public subnet in second AZ, Aurora security group, DB subnet group,
and Serverless v2 cluster with Data API enabled and Secrets Manager credentials.
Capture response headers, body, and transactionId on every check-issue
API call; persist as boa_txn#<ts>#<action> records with 90-day TTL.
Add "Recent BoA Submissions" section to App Home showing the last 10
with click-to-copy transactionId.
Motivation: BoA support asked for a transactionId from a past
successful call and we had no way to recover it from CloudWatch
summary logs alone.
Also adds simulate-csv.cjs (dry-run preview) and stampli-uploader.sh
(launchd-invoked S3 uploader), and gitignores debug artifacts.
- Fix transaction code mapping (475=Cleared, 255=Returned) in fetchBoaTransactions
- Match on customerReference instead of bankReference for check number matching
- Add bank-confirmed protection: CSV cannot override status once bank confirms Cleared
- Add status progression guard: CSV cannot regress status backward in lifecycle
- Cleared status is permanent — cannot be voided, cancelled, or changed
- Enable daily fetchBoaTransactions schedule (9am ET weekdays)
- Add production test script and dry run simulation script
- Add OAuth client-credentials token exchange to both Lambda handlers
- Fix sandbox/prod base URL (api-sb.bofa.com / api.bofa.com)
- Fix issueAction casing to add_Issue / cancel_Issue per API docs
- Fix transaction inquiry response parsing (accountTransactions array)
- Move all BoA config (app IDs, bank ID) from env vars to SSM params
- Update template.yaml with correct SSM param names and policies
- Add project README with architecture, API details, and SSM param reference
- CSV processor detects new checks and submits add_issue to CashPro
- Checks updated to voided/cancelled trigger cancel_issue to CashPro
- Added SSM params for boa-api-token, boa-account-number, boa-company-id
to both processPaymentCsv and fetchBoaTransactions Lambdas
- Increased CSV processor timeout to 120s for API calls
- New fetchBoaTransactions Lambda: daily 9am ET schedule (disabled until API key set)
Calls CashPro Previous Day Transaction Inquiry, filters for codes 255/475,
matches bankReference to check_number, updates clear_status in DynamoDB
- CSV processor switched to UpdateCommand to preserve clearing data on re-upload
- Slack dashboard now shows Scheduled, Outstanding, Cleared, and Returned sections
- ACH payments auto-assumed cleared once past due date
- VPC with NAT Gateway for static outbound IP (52.86.95.107) for BoA API
- Payments stored as individual DynamoDB items keyed by check number
- Slack bot token fetched from SSM at runtime instead of CF parameter
- Slack Lambda scans payment items instead of reading single blob
Two Lambda functions:
- processPaymentCsv: S3 trigger, parses CSV, stores dashboard in DynamoDB
- slackAppHome: API Gateway endpoint for Slack events, publishes Home tab view