Commit graph

5 commits

Author SHA1 Message Date
Adam Moussa
26adb8e6c0
feat(api): collapse Slack, portal, and jobs onto Fargate (PLAT-216) (#259)
* feat(api): collapse Slack, portal, and jobs onto Fargate (PLAT-216)

Move HTTP and scheduled work onto one always-on Flask task so after-hours
loses Lambda cold start without changing the Cognito or roster contracts.

* fix(portal-api): keep CORS headers on unexpected 500s

Portal SPA error handling needs Access-Control-Allow-Origin even when
DynamoDB or other internals fail, otherwise the browser hides the 500.

* fix(api): retarget holidays per account and ship App Home changelog (PLAT-216)

* fix(iam): list ECS tasks and fail closed on non-prod Paychex (PLAT-216)

* fix(portal-api): serve portal JSON with an explicit JSON content type
2026-09-21 19:13:30 +00:00
Adam Moussa
13350b72d0
feat(infra): migrate afterhours to HCP Terraform (PLAT-74) (#252)
Some checks are pending
Deploy / Deploy to prod (push) Waiting to run
* fix(cutover): write Slack secrets into empty Terraform shells

DescribeSecret succeeds on HCP-created shells with no version, so skip-if-exists left roster and Slack tokens unset.

* feat(infra): migrate afterhours to HCP Terraform (PLAT-74)

Replace the mgmt SAM stack with a prod-only HCP workspace, in-repo hcptf IAM, stub Lambdas, and zip CD on push to main.

* fix(cutover): retry DDB unprocessed items and skip past at() holidays

Unprocessed BatchWriteItem rows and leftover past at() schedules would drop roster data or abort holiday recreation during prod cutover.
2026-09-15 23:31:59 +00:00
Adam Moussa
23bad9bee6
feat(roster): add HTTP PUT/DELETE roster API (PLAT-180) (#247)
Some checks are pending
Deploy / deploy (push) Waiting to run
Deploy / release (push) Blocked by required conditions
* feat(roster): add Bearer PUT/DELETE roster API

Identity hire needs to write Slack IDs onto roster rows without a stale
daily 3CX sync clearing them, using the existing HTTP client contract.

* fix(roster): strip Secrets Manager token whitespace

A file:// secret commonly includes a trailing newline, so compare_digest
must strip the cached value the same way it strips the Bearer header.
2026-09-09 21:13:27 +00:00
Adam Moussa
11512f9aad
Fix SETUP.md to use Secrets Manager, not SSM (compliance #68) (#89)
SETUP.md step 2 told operators to store the Slack token/signing secret in
SSM Parameter Store, which (a) violates the secrets-and-config handbook
(API tokens/signing values must live in Secrets Manager) and (b) contradicts
the IaC — the stack reads Secrets Manager and the IAM roles only grant
secretsmanager:GetSecretValue on afterhours-shift-manager/*, so following the
old instructions would break the deploy.

- Section 2 now uses `aws secretsmanager create-secret` for all five secrets
  (slack-bot-token, slack-signing-secret, 3cx-domain/client-id/client-secret) —
  the 3CX secrets were also previously undocumented.
- The Slack channel ID is not a secret; documented as the `ShiftChannel` deploy
  parameter (--parameter-overrides) instead of an SSM SecureString.

Addresses violation 2 of #68.
2026-06-01 19:46:47 -04:00
Adam Moussa
4d0cdb5cfb Initial commit: after-hours shift manager Slack bot
Slack Bolt app on Lambda for managing on-call shifts. Employees can
pick up, drop, and swap shifts via /oncall commands. Changes update
3CX ring group 800 routing in real time for same-day shifts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 18:32:32 -04:00