- Add hosted domain check to _verify_google_token (mirror Lambda)
- Gate auth on config (client_id presence), not request body — prevents
bypass by omitting google_id_token when auth is configured
- Add discount percentage clamping to match Lambda handler
- Add </script> escaping to google_client_id_json
- Remove dead elif branch in submit_order auth (always returned 403)
- Catch HTTPError before URLError so expired tokens return 403 not 503
- Wrap SSM get_parameter in try/except for fresh deployments
- Add wall-clock guard to close_form handler (Friday >= 11 PM ET)
- Add epsilon nudge to JS employeePrice for IEEE 754 boundary match
- Switch Flask dev server from round() to Decimal ROUND_HALF_UP
- Add tests for HTTPError handling and close_form guard (6 new tests)
Add escapeHtml() for all scraped content in innerHTML, fix script
injection via </script> in JSON, fix JWT base64url decoding, match
backend two-step rounding in JS employeePrice(), disable qty buttons
and submit when form is closed, add server-driven countdown from
reopen_at, add duplicate order warning via localStorage, add back
button after submission, embed favicon, use :g format for fractional
discounts, and exclude dead loadRoster code when Google auth enabled.
Form now shows discount pricing, responsive grid layout, Google Sign-In
overlay, and closed-orders page with countdown timer. CI workflow fetches
discount settings from DynamoDB and Google Client ID from SSM.
- Change custom domain from orders.seahavenind.com to
orders.seahaven.com to match other subdomain conventions
- Add GET /api/roster endpoint returning employee names/emails
- Replace name/email text inputs with dropdown populated from
roster API (falls back to embedded roster for local dev)
- Fix order deadline text from Wednesday to Thursday 11:59 PM
- Fix Slack API calls: use form-urlencoded for conversations and
users methods that reject JSON body encoding
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.
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.