afterhours-shift-manager/CHANGELOG.md

223 lines
11 KiB
Markdown
Raw Normal View History

# Changelog
What's changed in the **After-Hours Shift Manager** — the Slack bot that runs our
after-hours on-call phone duty. Newest first, in plain language.
Versions are `MAJOR.MINOR.PATCH`: a **minor** bump adds a new feature, a **patch**
is a fix or tidy-up, and a **major** would be a big change to how things work.
Add changelog-driven releases and App Home tab (#112) * Add changelog-driven releases and App Home tab Version the bot continuously from CHANGELOG.md (the single source of truth for both the version and the staff-readable notes) and surface changes to users in two ways: - A new afterhours-release-notifier Lambda posts a "What's New" message to the shift channel on minor/major releases (patches stay silent). - The bot gains an App Home "About" tab showing what it does, the command list, and the current version's notes. release.yaml runs on Deploy success (not release:published — GITHUB_TOKEN events don't start downstream workflows), checks out the deployed commit, and tags + publishes a GitHub Release + invokes the notifier. It assumes a dedicated, boundary-carrying OIDC role scoped to InvokeFunction on the notifier; the account's cfn role gates role creation on that boundary. The manual Version Bump workflow is retired. A CI guard enforces that a CHANGELOG edit is a clean SemVer bump and that the in-package copy matches. * Harden release workflow and regex against CodeQL findings Address three code-scanning alerts on the PR: - Critical (actions/untrusted-checkout): split release.yaml into a read-only `prepare` job that checks out and runs repo code, and a privileged `publish` job (contents:write + OIDC) that never checks out repo code — it tags, releases, and invokes purely through the GitHub and AWS APIs. Also assert head_branch == main. - High x2 (py/polynomial-redos): rewrite the italic and link regexes in markdown_to_mrkdwn with possessive quantifiers and exclusive character classes so they run in linear time on adversarial input. Adds a regression test. * Move release/announce into Deploy workflow to clear CodeQL The workflow_run-triggered release.yaml kept tripping CodeQL's privileged-context rules (untrusted-checkout, then cache-poisoning) — CodeQL distrusts any workflow_run that checks out a ref, regardless of the main-only guarantee, and there is no autofix. Fold the release job into deploy.yaml gated on `needs: deploy`. A push-to-main run is a trusted context, so checking out and running repo code with write/OIDC is safe there. This still gates on deploy success and serializes via the deploy concurrency group, and removes the separate workflow entirely.
2026-06-11 19:41:31 -04:00
A few older entries cover two versions at once (e.g. `v1.9.0 / v1.9.1`) — that's
fine and still supported.
---
## v1.16.0 — September 21, 2026
**After Hours is available in the employee portal, and Slack still works.** Employees
can pick up, drop, and swap shifts from `internal.seahaven.com`, and admins can
override coverage, open or clear a shift, manage holidays, and approve late
pickups there. Swap and late-pickup still send Slack DMs. Slack App Home admin
modals are unchanged.
Portal identity is the roster email on Paychex `PUT /roster` (optional so existing
syncs keep working). Admin access is still the Slack IDs in `admin_users` after
that lookup. A new `afterhours-portal-api` Lambda serves `GET/POST/DELETE /api/shifts`
on the existing HTTP API with Cognito ID-token auth.
## v1.15.0 — September 2, 2026
**Monday pay totals now queue to Flex payroll posting.** The weekly post still
emails payroll and DMs the pay summary as before. After those go out, it also
sends last week's after-hours dollar lines (by extension, previous Monday
through Sunday) to the paychex-integrations checkcomponents queue. Unassigned
fallback extension 100 and $0 totals are left out. A queue failure does not
block the Monday schedule post. A retry or forced re-run of the same week does
not send the lines twice.
## v1.14.0 — July 2, 2026
**Point-and-click admin actions, right inside Slack.** Admins no longer have to
remember the exact word order of `/oncall admin …` commands for the two most
fiddly tasks:
- **Set an override or add a holiday from a form.** The bot's *Home* tab now has
an **Admin** section with two buttons — *Set override* and *Add holiday* — that
open a small form with a date picker, an employee dropdown, and clearly
labelled fields (the holiday pay multiplier is its own box instead of a
squeezed-in `x2`). Pick the values, submit, and the change lands exactly as the
typed command would — same phone-routing update for same-day changes, same
schedule-post refresh — with mistakes flagged on the field instead of a wall of
usage text. The typed `/oncall admin …` commands still work as before.
- **See what's coming up.** The Admin section also lists the upcoming overrides
and holidays so you can scan the next couple of months at a glance.
## v1.13.1 — June 29, 2026
**Fixed: the weekly pay summary email to payroll is sending again.** A
permissions change had quietly been blocking the Monday pay-summary email to
payroll since mid-June. The Slack pay report and the schedule post were never
affected — only the email to payroll. That's now fixed, the two missed weeks
were re-sent to payroll, and we've added an alert so a future email failure
can't slip by unnoticed.
## v1.13.0 — June 27, 2026
**The two-week schedule post now sticks to the bottom of the channel.** It used
to drift up out of sight as people chatted through the day. Now, whenever there's
new activity in the channel, the bot quietly moves the schedule back down to the
bottom so it's always the last thing you see. To avoid spamming during a busy
back-and-forth, it only does this at most once every few minutes. The trade-off
for keeping it at the bottom is that the post's link changes each time it moves,
and moving it re-pings the channel. (This needs a one-time app reinstall to
switch on the new permission; until then the schedule still updates in place as
before.)
## v1.12.0 — June 26, 2026
**Clearer shift drops and an easier-to-read schedule.** Two small quality-of-life
improvements:
- **`/oncall drop` can now say which shift to let go.** If you hold more than one
shift on the same day — say a holiday day slot *and* that night's after-hours
shift, or a weekend day *and* night shift — dropping no longer guesses for you.
The bot lists what you hold and asks you to add `day`, `night`, or `holiday`
(for example `/oncall drop saturday night`), the same way picking one up
already works. Asking to drop a shift you don't actually hold is turned down
instead of quietly dropping the wrong one.
- **Night shifts stand out on the two-week post.** Day and night rows now carry
their own icons — a sun for the daytime shift and a moon for the after-hours
(night) shift — so the on-call row is easy to spot at a glance. Weekend rows,
which have both a day and a night shift, still spell out the full time range.
## v1.11.1 — June 17, 2026
**Fix holiday call routing to 3CX.** The holiday router was calling the wrong 3CX
API path for the auto-attendant (IVR 800), so activating a holiday wouldn't have
rerouted calls to the holiday queue. Corrected to the right endpoint and verified
end-to-end against the live phone system. No change to how you use the bot.
---
## v1.11.0 — June 15, 2026
**Holiday coverage and last-minute pickups.** Two related additions:
- **Holidays now have their own day shift.** An admin can schedule a holiday for
any date with `/oncall admin holiday add` — a single daytime shift (8am-5pm ET)
that can have more than one person on it. The bot shows the holiday in the
schedule with a button to grab an open slot, and holiday slots can be set to
pay a higher rate (1.5x by default). On the holiday itself the after-hours
phones automatically route to whoever claimed a slot, from 8am to 5pm, and
switch back to normal at 5pm — no one has to touch the phone system. If a
holiday goes by with nobody signed up, calls fall back to the default
extension. Admins can also list upcoming holidays and remove one they no longer
need. Holidays take priority over both regular overrides and the standing
weekly schedule for that date.
- **Picking up a shift after it has already started now needs an admin to say
yes.** Before, you could only pick up a shift that hadn't started. Now, if a
shift is already underway (8am for a day/holiday shift, 5pm for a night shift)
but hasn't ended yet, asking to pick it up sends every admin an Approve/Deny
message — the same way swaps are confirmed. The first admin to approve wins,
and once approved the shift is handed over and the phones are repointed right
away. Picking up a shift that hasn't started yet still happens instantly, and
a shift that has already ended can't be picked up at all. This applies to both
regular and holiday shifts.
## 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.
Add changelog-driven releases and App Home tab (#112) * Add changelog-driven releases and App Home tab Version the bot continuously from CHANGELOG.md (the single source of truth for both the version and the staff-readable notes) and surface changes to users in two ways: - A new afterhours-release-notifier Lambda posts a "What's New" message to the shift channel on minor/major releases (patches stay silent). - The bot gains an App Home "About" tab showing what it does, the command list, and the current version's notes. release.yaml runs on Deploy success (not release:published — GITHUB_TOKEN events don't start downstream workflows), checks out the deployed commit, and tags + publishes a GitHub Release + invokes the notifier. It assumes a dedicated, boundary-carrying OIDC role scoped to InvokeFunction on the notifier; the account's cfn role gates role creation on that boundary. The manual Version Bump workflow is retired. A CI guard enforces that a CHANGELOG edit is a clean SemVer bump and that the in-package copy matches. * Harden release workflow and regex against CodeQL findings Address three code-scanning alerts on the PR: - Critical (actions/untrusted-checkout): split release.yaml into a read-only `prepare` job that checks out and runs repo code, and a privileged `publish` job (contents:write + OIDC) that never checks out repo code — it tags, releases, and invokes purely through the GitHub and AWS APIs. Also assert head_branch == main. - High x2 (py/polynomial-redos): rewrite the italic and link regexes in markdown_to_mrkdwn with possessive quantifiers and exclusive character classes so they run in linear time on adversarial input. Adds a regression test. * Move release/announce into Deploy workflow to clear CodeQL The workflow_run-triggered release.yaml kept tripping CodeQL's privileged-context rules (untrusted-checkout, then cache-poisoning) — CodeQL distrusts any workflow_run that checks out a ref, regardless of the main-only guarantee, and there is no autofix. Fold the release job into deploy.yaml gated on `needs: deploy`. A push-to-main run is a trusted context, so checking out and running repo code with write/OIDC is safe there. This still gates on deploy success and serializes via the deploy concurrency group, and removes the separate workflow entirely.
2026-06-11 19:41:31 -04:00
## v1.10.0 — June 11, 2026
**The bot now tells you what's new.** Two things:
- When a noticeable update ships (a new feature or a bigger change), the bot
posts a short "What's New" note right in the on-call channel — so you hear
about changes without having to go looking. Small fixes stay quiet.
- The bot now has an **About** page. Click the bot's name in Slack and open its
**Home** tab to see what it does, the full list of `/oncall` commands, and the
latest "What's New". It always shows the current version.
## v1.9.2 — June 1, 2026
**Setup-guide fix.** Corrected the install instructions so secrets (the Slack and
phone-system passwords) are stored in the right, secure place. No change to the
bot itself — this only affects someone setting it up from scratch.
## v1.9.0 / v1.9.1 — June 1, 2026
**You can no longer drop a shift at the last minute.** If a shift starts within
the next 24 hours, you can't just drop it and walk away — you have to hand it to
someone specific (a swap they accept), or ask an admin. This stops the phones
from being left uncovered with no notice. *(v1.9.1 was a routine update of
behind-the-scenes software libraries.)*
## v1.8.0 — June 1, 2026
**Swaps now need the other person to say yes.** Before, `/oncall swap` instantly
dumped your shift on someone else. Now they get a Slack message with **Accept**
and **Decline** buttons, and the shift only moves if they accept. Until then it
stays yours. If they don't respond before the shift starts, the request quietly
expires.
## v1.7.19 — June 1, 2026
**Quality safety net (no visible change).** Added an automated test suite that
checks the bot's behavior on every change, so bugs get caught before they ship.
You won't notice anything different day-to-day — it just makes future updates
safer.
---
## May 2026 — Phone-system automation & a big fix
- **Live phone routing follows the schedule.** The system that decides which
phone rings after hours now reads directly from the on-call schedule, so
pickups, drops, and swaps take effect automatically.
- **Fixed a release that had broken the whole bot.** A packaging mistake stopped
all of the bot's functions from running; this was found and fixed.
- Ongoing routine updates to behind-the-scenes software libraries.
- **Behind the scenes:** moved to an automated build-and-release pipeline, added
automatic code checks and formatting, and turned on automated dependency and
code-review tooling. None of this changes how you use the bot.
## May 1, 2026 — Reliability & notifications
- **No more double-booking.** Fixed a timing bug where two people could grab the
same open shift at once.
- **Shift changes are announced.** When someone picks up, drops, or swaps a
shift, a note is posted to the team channel.
- **Fixed a confusing error** that showed up when picking a shift even though the
pickup had actually worked.
## April 8, 2026 — Schedule & pay polish
- The weekly schedule now always starts on **Monday** (it used to start from
today).
- Tidied up the weekly pay report (recipient and wording).
## April 7, 2026 — Scheduling & pay
- **Two-week schedule view** instead of just the current week.
- **Weekly pay totals** for on-call shifts, with a configurable flat rate.
- **Per-person pay rates** and an `/oncall rate` command to manage them from
Slack.
- **Weekend day shifts** — weekends are split into a daytime and an overnight
shift.
- **Automatic employee roster sync** — the bot pulls the staff list from the
phone system each day, so the roster stays current on its own.
- **Weekly "Bonus Pay Summary"** emailed to payroll (and sent as a Slack DM to
the admin) every Monday.
## April 3, 2026 — Launch 🎉
The first version of the After-Hours Shift Manager:
- See the on-call schedule in Slack with `/oncall`.
- **Pick up** an open shift and **drop** a shift you're covering.
- Link your Slack account to your phone extension with `/oncall register`.