Skip to content

feat: Follow-ups after the 1.3.0 delivery: Phase B credential scoping, a stranded uncertain row, and the prod client-env sessi - #82

Merged
andrei-hasna merged 2 commits into
mainfrom
factory/b16075b8-ae32-4671-a3b0-f930480e-f8991de0
Jul 27, 2026
Merged

feat: Follow-ups after the 1.3.0 delivery: Phase B credential scoping, a stranded uncertain row, and the prod client-env sessi#82
andrei-hasna merged 2 commits into
mainfrom
factory/b16075b8-ae32-4671-a3b0-f930480e-f8991de0

Conversation

@andrei-hasna

@andrei-hasna andrei-hasna commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Objective

Follow-ups after the 1.3.0 delivery: Phase B credential scoping, a stranded uncertain row, and the prod client-env session token

Resolve GitHub issue #61 and open a PR against hasna/emails.

Issue URL: #61
Target repo checkout: /home/hasna/workspace/hasna/opensource/open-emails

--- Issue body ---
Three loose ends from the 2026-07-25 delivery of @hasna/emails 1.3.0 (merged #55, #54, #56, #57, #58, #59; deployed as emails-prod:28). None of them blocks the release; all three were found while verifying it.

1. Phase B — drop the unscoped AWS_* credential pair from emails-prod

emails-prod:28 injects both name pairs from Secrets Manager:

  • AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY — repoints the container's whole SDK default credential chain at 638389534677
  • EMAILS_SES_ACCESS_KEY_ID / EMAILS_SES_SECRET_ACCESS_KEY — the scoped names 1.3.0's sender reads

The unscoped pair existed to make the 1.2.7 image send without a code change. 1.3.0 is now live and its boot log confirms credentials=environment, so the unscoped pair is redundant and should go — leaving the default chain back on the API task role.

It is safe today only because emails-prod runs ["src/server/index.ts"] and makes no S3/SQS calls. That is a property of the current entrypoint, not a guarantee, so it should not be relied on indefinitely.

Change is in hasna/hasna-xyz-infra, apps/emails/prod/taskdefs/emails-prod.json. Keep it off emails-prod-ingest-worker either way — the alumia principal has no SQS or inbound-bucket access.

2. One send intent is legitimately still uncertain and needs SES-log-level evidence

16bb4fa4-0458-4ceb-ab23-f7373ac14b98 — 2026-07-24T18:40:54Z, andrei@hasna.com, subject "CAPS PROBE 1x 64KiB (sub limita)".

Thirteen of the fourteen uncertain rows were reconciled on evidence. This one cannot be, and it is worth understanding rather than closing:

  • AWS/SES CloudWatch on 789877399345, 1-minute buckets, shows Send=1 in the 18:40Z minute — the exact minute this intent was created — and that datapoint is **not claimed by any
    [...body truncated; see issue URL for full text...]

Verification

  • install: pass
  • typecheck: pass
  • build: pass
  • test: pass

Run run_a50ad6238563 · backend codewith · task b16075b8-ae32-4671-a3b0-f930480ed9a5
🏭 Generated by @hasnaxyz/factory


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…, a stranded uncertain row, and the prod client-env sessi
@andrei-hasna

Copy link
Copy Markdown
Contributor Author

Triaged this against current main (5bb126e). Summary: the change is correct and worth landing, but this PR cannot merge as-is — rebased and corrected in #85, which supersedes this one.

State of this PR

  • mergeable: CONFLICTING / mergeStateStatus: DIRTY. It branched at 45584a7; 41 commits have landed since.
  • No CI check has ever run on it (no checks reported on the 'factory/b16075b8-…' branch), so its "Verification: test: pass" line is unverified against today's main.
  • The only real conflict was CHANGELOG.md (purely additive). deploy/aws/compute.tf and docs/SELF_HOSTED_RUNTIME.md auto-merged — main's only compute.tf change since the base is the EMAILS_TRUSTED_PROXY_HOPS hunk from the auth rate-limit security fix, which is a different region of the same locals block. So the change does still apply.

The change itself is good. Dropping the unscoped AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY pair is a privilege reduction — it adds no credential storage, no schema columns, and no provider secrets, so it raises none of the encryption-at-rest concerns that new server-side secret storage would. Rebased, terraform test is 24/24 and the full suite is 2410 pass / 0 fail / 137 skip, identical to main.

One correction was needed. This PR rewrote two boundary guards in deploy/aws/tests/dormant.tftest.hcl from

!strcontains(upper(entry.name), "ACCESS_KEY")

to !contains([<the four names the module injects today>], entry.name).

That converts a pattern into a name allowlist, on exactly the worker/migration task definitions whose SES-blind task roles are the reason inbound mail keeps working. It also wasn't necessary: after the scoping change those tasks carry only EMAILS_DATABASE_URL, so the original patterns still pass. Concretely — injecting a secret named EMAILS_S3_ACCESS_KEY_ID into the worker task fails the original pattern and passes the allowlist form. #85 restores both patterns and keeps your new exact-set assertion on the API secrets block, which is a genuine strengthening.

Two things #85 flags for the coordinator rather than deciding:

  1. Applying this module breaks SES sending for any deployed image older than 1.3.0, so it wants a [BREAKING] post to #announcements before merge.
  2. The title covers three follow-ups from Follow-ups after the 1.3.0 delivery: Phase B credential scoping, a stranded uncertain row, and the prod client-env session token #61, but only credential scoping is in the diff — Follow-ups after the 1.3.0 delivery: Phase B credential scoping, a stranded uncertain row, and the prod client-env session token #61 shouldn't be closed on this alone.

Recommend closing this in favour of #85.

…-key guards

main already carries this branch's SES credential scoping (landed as #85,
0c54ce3) and then corrected the test guards in c96b196. This merge resolves
both conflicts in favour of main:

- deploy/aws/tests/dormant.tftest.hcl: restores
  !strcontains(upper(entry.name), "ACCESS_KEY") in the worker/migration guard
  of ses_credentials_injected_by_arn_reference_only and in the API guard of
  no_ses_credentials_leaves_the_task_role_alone. The 4-name allowlist this
  branch carried let any future credential secret under a different
  access-key name pass, on exactly the task definitions whose SES-blind task
  roles keep inbound mail working.
- CHANGELOG.md: main's entry is a strict superset; no branch content is lost.

The resulting tree is byte-identical to origin/main, so this branch can no
longer regress the default branch.
@andrei-hasna
andrei-hasna merged commit fe3ebc6 into main Jul 27, 2026
3 checks passed
@andrei-hasna
andrei-hasna deleted the factory/b16075b8-ae32-4671-a3b0-f930480e-f8991de0 branch July 27, 2026 01:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant