Commit graph

11 commits

Author SHA1 Message Date
Cursor Agent
6bc5ccaedd
fix: Email order filenames, SSM param TTL, DST-safe reopen_at
- Flask dev server: persist orders under lowercase email slug (match Lambda/Dynamo)
- shared.secrets: split secret vs SSM caches; expire get_parameter entries every 5 minutes
- form-status reopen_at: calendar Monday + datetime.combine for 8am ET (not 24h timedelta)
- Add _eastern_now() for testability; tests for SSM TTL and DST weekend edge case

Co-authored-by: Adam Moussa <amoussa1229@users.noreply.github.com>
2026-05-13 18:32:08 +00:00
Adam Moussa
5db992b0be Fix close-form weekday guard and SSM auth fail-open
- Close form guard: check weekday == 3 (Thursday), not 4 (Friday) — the
  crons fire at Thursday 11:59 PM ET, when weekday() is 3
- SSM fail-closed: separate _google_auth_configured() (checks env var) from
  _get_google_client_id() (fetches value). If auth is configured but the SSM
  fetch fails, return 503 instead of silently falling back to manual auth
- Update close_form tests to use Thursday dates
- Add test_ssm_failure_fails_closed
2026-05-13 13:50:48 -04:00
Adam Moussa
5c040bf55c Fix PR review findings: auth, rounding, and close-form guard
- 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)
2026-05-13 13:39:18 -04:00
Adam Moussa
fa8f19660d Apply ruff formatting 2026-05-13 13:25:40 -04:00
Adam Moussa
406aa9b95d Use full email as order slug for defense-in-depth
Replace email-prefix slug with full lowercase email to eliminate any
possibility of cross-domain collisions, per senior review sign-off.
2026-05-13 13:21:52 -04:00
Adam Moussa
bcce15b9e6 Harden auth, pricing, and reliability in order handlers
Enforce Google auth when configured (reject missing tokens with 403),
return 503 on token verification outages, switch to Decimal with
ROUND_HALF_UP for financial precision, clamp discount bounds 0-100,
use email-based slugs, add 5-min cache TTL with time.monotonic(),
wrap Slack invocation in try/except, add reopen_at timestamp to
closed form status, add reminder dedup guards for dual EST/EDT crons,
escape Slack mrkdwn special characters, and handle empty employee names.
2026-05-13 12:58:56 -04:00
Adam Moussa
81543c3b7f Add Google OAuth, server-side discounts, and Slack order confirmations
Submit order Lambda now verifies Google ID tokens via tokeninfo endpoint,
calculates two-tier discount pricing server-side, and async-invokes the
Slack notifier for per-employee order confirmation DMs. Deadlines updated
to Thursday 11:59pm across all Slack messages.
2026-05-13 11:35:56 -04:00
Adam Moussa
a8adbdc116
Switch to orders.seahaven.com, add roster dropdown, fix deadline (#9)
Some checks are pending
Deploy / deploy (push) Waiting to run
- 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
2026-05-12 20:16:46 -04:00
Adam Moussa
440117c9a1
Fix ruff lint and format violations, update README (#5)
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.
2026-05-12 19:31:27 -04:00
Adam Moussa
8935fc8f2d
Add roster sync Lambda, move API key to Secrets Manager, add Slack manifest (#3)
- 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)
2026-05-12 19:21:47 -04:00
Adam Moussa
d332affd56
Initial commit: meal ordering automation system (#1)
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.
2026-05-12 18:25:15 -04:00