conversations.members, conversations.open, and users.info reject
JSON body with 'missing required field'. Use form-urlencoded for
these methods while keeping JSON for chat.postMessage and
files.upload which require it for structured blocks/payloads.
Use cfn-role-arn as input (not secret), pass deploy-role-arn and
parameter-overrides as secrets, add permissions and concurrency
blocks matching the standard org pattern.
Apply ruff check --fix and ruff format across all Python files to
pass CI pipeline. Remove unused imports (os, sys), fix f-strings
without placeholders. Update README to reflect sync-roster Lambda,
corrected shared layer path, and current project structure.
- Add sync-roster Lambda that auto-syncs employee roster from Slack
channel membership (runs Monday 6:55am ET before menu publish)
- Move FormApiKey from CloudFormation parameter/env var to Secrets
Manager (meal-order-manager/form-api-key) per security conventions
- Add Slack app manifest with required bot scopes
- Add get_channel_members() and get_user_info() to shared Slack module
- Add Lambda function ARN outputs to CloudFormation
- Add log group for sync-roster Lambda (60-day retention)
Move shared layer source from src/shared/python/shared/ to
src/shared/shared/ to prevent SAM from creating a double
python/python/ directory in the layer artifact. Add _to_decimal()
helper to convert floats to Decimal for DynamoDB compatibility
in put_order.
Playwright-based menu scraper for Redefine Meals, self-contained HTML
order form with S3/CloudFront hosting, DynamoDB-backed order submission
via API Gateway, and automated payroll deduction reports via SES.