mirror of
https://github.com/Sea-Haven-Industries/afterhours-shift-manager.git
synced 2026-10-05 15:22:03 +00:00
Fix payroll summary email (SES config-set permission) + isolate failures (#114)
* Fix payroll email: grant SES config-set permission + isolate failures The weekly pay-summary email to payroll has been failing with SES AccessDenied since 2026-06-08. The sending identity (seahaven.com) gained a default configuration set (seahaven-email-events), and SES authorizes SendEmail against the config-set ARN as well as the identity — but the WeeklyPostFunction role only granted ses:SendEmail on identity/*. - template.yaml: add the configuration-set ARN (scoped to the known set name) to the SES policy so sends are authorized again. - weekly-post/app.py: wrap _send_pay_email in try/except so a delivery failure can never abort the handler before the Slack schedule post. Previously the SES error also blocked the two-week schedule post. - Add a regression test covering the isolation. Cross-family GPT-4.1 IAM review: APPROVE. * Bump to v1.10.1 in CHANGELOG and sync App Home copy
This commit is contained in:
parent
8e90d41b6c
commit
1e1e5176a3
5 changed files with 54 additions and 2 deletions
|
|
@ -10,6 +10,15 @@ fine and still supported.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## v1.10.1 — June 15, 2026
|
||||||
|
|
||||||
|
**Payroll summary emails are sending again.** The automated weekly pay summary
|
||||||
|
to payroll had stopped going out (an email-permissions change on our side blocked
|
||||||
|
it from June 8 onward). Fixed the permission so the emails send, and made the
|
||||||
|
Monday job sturdier: if the payroll email ever fails again, it no longer stops
|
||||||
|
the on-call schedule from being posted in Slack. The two missed summaries were
|
||||||
|
re-sent by hand.
|
||||||
|
|
||||||
## v1.10.0 — June 11, 2026
|
## v1.10.0 — June 11, 2026
|
||||||
|
|
||||||
**The bot now tells you what's new.** Two things:
|
**The bot now tells you what's new.** Two things:
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,15 @@ fine and still supported.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## v1.10.1 — June 15, 2026
|
||||||
|
|
||||||
|
**Payroll summary emails are sending again.** The automated weekly pay summary
|
||||||
|
to payroll had stopped going out (an email-permissions change on our side blocked
|
||||||
|
it from June 8 onward). Fixed the permission so the emails send, and made the
|
||||||
|
Monday job sturdier: if the payroll email ever fails again, it no longer stops
|
||||||
|
the on-call schedule from being posted in Slack. The two missed summaries were
|
||||||
|
re-sent by hand.
|
||||||
|
|
||||||
## v1.10.0 — June 11, 2026
|
## v1.10.0 — June 11, 2026
|
||||||
|
|
||||||
**The bot now tells you what's new.** Two things:
|
**The bot now tells you what's new.** Two things:
|
||||||
|
|
|
||||||
|
|
@ -183,8 +183,16 @@ def handler(event, context):
|
||||||
else:
|
else:
|
||||||
logger.warning("PAY_REPORT_USER not set — skipping Slack pay summary")
|
logger.warning("PAY_REPORT_USER not set — skipping Slack pay summary")
|
||||||
|
|
||||||
# Email pay summary to payroll
|
# Email pay summary to payroll. Isolated so a delivery failure (e.g.
|
||||||
_send_pay_email(week_label, pay_record)
|
# an SES permission/identity issue) can never abort the rest of the
|
||||||
|
# handler — the Slack schedule post below must still go out.
|
||||||
|
try:
|
||||||
|
_send_pay_email(week_label, pay_record)
|
||||||
|
except Exception:
|
||||||
|
logger.exception(
|
||||||
|
"Failed to send pay summary email to payroll for week of %s",
|
||||||
|
week_key,
|
||||||
|
)
|
||||||
|
|
||||||
# --- Delete previous week's schedule post ---
|
# --- Delete previous week's schedule post ---
|
||||||
old_post = schedule.get_schedule_post(channel_id)
|
old_post = schedule.get_schedule_post(channel_id)
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,11 @@ Resources:
|
||||||
- ses:SendEmail
|
- ses:SendEmail
|
||||||
Resource:
|
Resource:
|
||||||
- !Sub "arn:aws:ses:${AWS::Region}:${AWS::AccountId}:identity/*"
|
- !Sub "arn:aws:ses:${AWS::Region}:${AWS::AccountId}:identity/*"
|
||||||
|
# The sending identity has a default configuration set
|
||||||
|
# (seahaven-email-events); SES authorizes SendEmail against the
|
||||||
|
# config-set resource too, so it must be granted alongside the
|
||||||
|
# identity or the send is denied. Scoped to the known set name.
|
||||||
|
- !Sub "arn:aws:ses:${AWS::Region}:${AWS::AccountId}:configuration-set/seahaven-email-events"
|
||||||
Events:
|
Events:
|
||||||
# EST: 7am ET = 12:00 UTC (Nov-Mar)
|
# EST: 7am ET = 12:00 UTC (Nov-Mar)
|
||||||
WeeklyPostEST:
|
WeeklyPostEST:
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,27 @@ def test_calculates_and_dms_pay(weeklypost_app, schedule, seed, slack, env):
|
||||||
assert dm_calls
|
assert dm_calls
|
||||||
|
|
||||||
|
|
||||||
|
@freeze_time(MON_0800)
|
||||||
|
def test_pay_email_failure_does_not_block_schedule_post(
|
||||||
|
weeklypost_app, schedule, seed, slack, env, monkeypatch
|
||||||
|
):
|
||||||
|
# Previous week has an assigned shift, so the pay/email path runs.
|
||||||
|
seed.config(shift_rate="50")
|
||||||
|
seed.weekly("Monday", "114", "Alice")
|
||||||
|
# SES delivery blows up (e.g. a permission/identity issue).
|
||||||
|
monkeypatch.setattr(
|
||||||
|
weeklypost_app,
|
||||||
|
"_send_pay_email",
|
||||||
|
MagicMock(side_effect=Exception("SES AccessDenied")),
|
||||||
|
)
|
||||||
|
|
||||||
|
result = weeklypost_app.handler({"force": True}, None)
|
||||||
|
|
||||||
|
# The email failure is swallowed; the schedule post still goes out.
|
||||||
|
assert result["posted"] is True
|
||||||
|
assert schedule.get_schedule_post("C_TEST")["message_ts"] == "999.000"
|
||||||
|
|
||||||
|
|
||||||
@freeze_time(MON_0800)
|
@freeze_time(MON_0800)
|
||||||
def test_deletes_previous_schedule_post(weeklypost_app, schedule, seed, slack, env):
|
def test_deletes_previous_schedule_post(weeklypost_app, schedule, seed, slack, env):
|
||||||
seed.schedule_post("C_TEST", "111.111")
|
seed.schedule_post("C_TEST", "111.111")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue