Skip to content

feat: support standard AWS env vars and default credential chain - #401

Merged
KMKoushik merged 5 commits into
mainfrom
fix/aws-env-vars-on-pr-395
May 17, 2026
Merged

KMKoushik merged 5 commits into
mainfrom
fix/aws-env-vars-on-pr-395

Conversation

@KMKoushik

@KMKoushik KMKoushik commented May 17, 2026

Copy link
Copy Markdown
Member

Summary

  • Support standard AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY while keeping runtime fallback for existing legacy envs
  • Allow the AWS SDK default credential chain when static credentials are omitted
  • Align Docker, docs, CI env, and turbo env declarations with standard AWS names

Based on #395 by @purva-8, with maintainer fixes on top.

Closes #316

Verification

  • git diff --check
  • pnpm --filter=web exec eslint src/env.js next.config.js (AWS/turbo warnings resolved; unrelated existing warnings remain)

Merge note

If squash-merging and you want co-author credit preserved on the squash commit, include:

Co-authored-by: Purva Kandalgaonkar 136103488+purva-8@users.noreply.github.com


Summary by cubic

Switches to the standard AWS env vars AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY and enables the AWS SDK default credential chain when both are unset. Updates code, Docker, CI, docs, and Turbo config; legacy envs still work as fallbacks.

  • New Features

    • Use AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY; AWS_ACCESS_KEY / AWS_SECRET_KEY remain as runtime fallbacks.
    • Omit both vars to use the AWS SDK default credential chain for SES/SNS/STS.
    • Added getAwsCredentialOptions with a guard that errors on partial config.
    • Use an aliased import for the credentials helper to avoid path issues.
  • Migration

    • Prefer AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, or rely on IAM/instance roles by leaving both unset.
    • Update your .env, CI, Docker, and Turbo env lists to the new names; examples and docs are aligned.

Written for commit b2147df. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • Added AWS credential validation with safe fallback behavior; deployments can run without credentials set.
  • Documentation

    • Updated setup guides, examples, and run instructions to use the standardized AWS environment variable names.
  • Chores

    • Standardized AWS credential configuration across examples, tests, CI workflows, Docker, and build tooling to align with AWS conventions.

Review Change Stack

purva-8 and others added 4 commits May 2, 2026 17:52
Replace non-standard AWS_ACCESS_KEY / AWS_SECRET_KEY with the AWS-standard
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. The old names are kept as
fallbacks in the runtimeEnv for backward compatibility.

Both vars are now optional. When omitted, the credentials object is not
passed to SESv2Client, STSClient, or SNSClient — the AWS SDK then falls
back to its default provider chain (IAM roles, ECS task roles, instance
profiles, etc.), which is the recommended approach for cloud-native deployments.

Closes #316

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…al-config guard

- Move the credential spread logic into a single credentials.ts helper
  so SESv2Client, STSClient, and SNSClient all share one implementation
- Throw a clear error if only one of AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
  is set, preventing silent fallback to the default provider chain with a
  half-configured environment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented May 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
unsend-marketing Ready Ready Preview, Comment May 17, 2026 11:21am

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e593e2ea-adba-4d19-9151-b80f2fe5a460

📥 Commits

Reviewing files that changed from the base of the PR and between 1c6317d and b2147df.

📒 Files selected for processing (2)
  • apps/web/src/server/aws/ses.ts
  • apps/web/src/server/aws/sns.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/src/server/aws/sns.ts
  • apps/web/src/server/aws/ses.ts

Walkthrough

This PR standardizes AWS credential environment variable names from AWS_ACCESS_KEY/AWS_SECRET_KEY to AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY across examples, docs, CI, and runtime. It adds getAwsCredentialOptions() which returns explicit credentials when both env vars are set, throws on partial configuration, or returns an empty object so the AWS SDK default credential provider chain can be used. SES and SNS clients now use this helper instead of inline credential objects.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main changes: adding support for standard AWS environment variables and enabling the AWS default credential chain.
Linked Issues check ✅ Passed The PR successfully addresses all key requirements from issue #316: supports standard AWS env vars (AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY), makes credentials optional via default chain, maintains backward compatibility with legacy vars, and implements validation for partial configuration.
Out of Scope Changes check ✅ Passed All changes are directly related to the objective of supporting standard AWS environment variables and the credential chain. Updates to env files, documentation, CI workflows, and code are all in scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 17, 2026

Copy link
Copy Markdown

Deploying usesend with  Cloudflare Pages  Cloudflare Pages

Latest commit: b2147df
Status: ✅  Deploy successful!
Preview URL: https://6f7e6eeb.usesend.pages.dev
Branch Preview URL: https://fix-aws-env-vars-on-pr-395.usesend.pages.dev

View logs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
apps/docs/get-started/set-up-docker.mdx (1)

55-57: ⚡ Quick win

Document AWS static credentials as optional in standalone Docker flow.

Line 55–57 and Line 63 currently imply static AWS keys are always needed. Since credentials are now optional, please note that users can omit these vars when their runtime provides IAM-role/default credential chain access.

Proposed doc patch
 docker run -d \
   -p 3000:3000 \
   -e NEXTAUTH_URL="<your-nextauth-url>" \
   -e NEXTAUTH_SECRET="<your-nextauth-secret>" \
   -e DATABASE_URL="<your-next-private-database-url>" \
   -e REDIS_URL="<your-next-private-redis-url>" \
-  -e AWS_ACCESS_KEY_ID="<your-next-private-aws-access-key-id>" \
-  -e AWS_SECRET_ACCESS_KEY="<your-next-private-aws-secret-access-key>" \
   -e AWS_DEFAULT_REGION="<your-next-private-aws-region>" \
   -e GITHUB_ID="<your-next-private-github-id>" \
   -e GITHUB_SECRET="<your-next-private-github-secret>" \
   usesend/usesend

-Replace the placeholders with your actual database and AWS details.
+Replace the placeholders with your actual database details.
+If your environment does not provide AWS credentials via IAM/default provider chain, also set:
+AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

</details>


Also applies to: 63-63

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @apps/docs/get-started/set-up-docker.mdx around lines 55 - 57, Update the
Docker setup instructions so the AWS static credential environment variables
(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) are documented as
optional: change the text that currently tells users to "Replace the
placeholders with your actual database and AWS details." to "Replace the
placeholders with your actual database details. If your environment does not
provide AWS credentials via IAM/default provider chain, also set:
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY." Ensure this change is applied to
the same explanatory lines that contain the three environment variable
placeholders and the similar line around the later occurrence (the one
referenced at line 63).


</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @apps/web/src/env.js:

  • Around line 102-103: The current fallback uses independent || for
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY which can mix standard and legacy
    values; update the logic so the code selects either the standard pair
    (AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY) or, only if both are absent, the
    legacy pair (AWS_ACCESS_KEY + AWS_SECRET) as a unit. In practice change the
    assignment for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to a small
    conditional that prefers the standard env vars together, otherwise uses the
    legacy pair only when both legacy vars exist, and yields undefined/null if
    neither full pair is present; reference the AWS_ACCESS_KEY_ID and
    AWS_SECRET_ACCESS_KEY symbols when locating where to implement this.

In @apps/web/src/server/aws/ses.ts:

  • Line 20: Replace the relative import of getAwsCredentialOptions from
    "./credentials" with the repo-standard src alias import (e.g. import {
    getAwsCredentialOptions } from "~/server/aws/credentials";) so the module uses
    the ~/ alias form consistent with apps/web src imports.

In @apps/web/src/server/aws/sns.ts:

  • Line 8: Replace the relative import for getAwsCredentialOptions with the
    project src alias; change the import source from "./credentials" to the aliased
    module (e.g. "/server/aws/credentials") so the import reads: import {
    getAwsCredentialOptions } from "
    /server/aws/credentials"; this aligns the
    getAwsCredentialOptions import with the apps/web src alias convention.

Nitpick comments:
In @apps/docs/get-started/set-up-docker.mdx:

  • Around line 55-57: Update the Docker setup instructions so the AWS static
    credential environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY,
    AWS_DEFAULT_REGION) are documented as optional: change the text that currently
    tells users to "Replace the placeholders with your actual database and AWS
    details." to "Replace the placeholders with your actual database details. If
    your environment does not provide AWS credentials via IAM/default provider
    chain, also set: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY." Ensure this
    change is applied to the same explanatory lines that contain the three
    environment variable placeholders and the similar line around the later
    occurrence (the one referenced at line 63).

</details>

<details>
<summary>🪄 Autofix (Beta)</summary>

Fix all unresolved CodeRabbit comments on this PR:

- [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended)
- [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes

</details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: Organization UI

**Review profile**: CHILL

**Plan**: Pro

**Run ID**: `b582a91e-d79f-48e3-bf7b-c0e17c7b23fc`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 31a49fbdca243a4674ec07946f69e8479c86f1f9 and 1c6317daccebc1e2b2afe54cec38e735ac58d913.

</details>

<details>
<summary>📒 Files selected for processing (18)</summary>

* `.env.example`
* `.env.selfhost.example`
* `.github/workflows/test-web.yml`
* `CONTRIBUTION.md`
* `apps/docs/get-started/create-aws-credentials.mdx`
* `apps/docs/get-started/local.mdx`
* `apps/docs/get-started/set-up-docker.mdx`
* `apps/docs/self-hosting/overview.mdx`
* `apps/docs/self-hosting/railway.mdx`
* `apps/web/.env.test.example`
* `apps/web/src/env.js`
* `apps/web/src/server/aws/credentials.ts`
* `apps/web/src/server/aws/ses.ts`
* `apps/web/src/server/aws/sns.ts`
* `apps/web/src/test/setup/setup-env.ts`
* `docker/README.md`
* `docker/prod/compose.yml`
* `turbo.json`

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment thread apps/web/src/env.js
Comment on lines +102 to +103
AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID || process.env.AWS_ACCESS_KEY,
AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY || process.env.AWS_SECRET_KEY,

@coderabbitai coderabbitai Bot May 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid mixing standard and legacy credential sources across fields.

Line 102 and Line 103 independently fall back with ||, which can combine AWS_ACCESS_KEY_ID with legacy AWS_SECRET_KEY (or vice versa). That can create an invalid pair and undercut partial-config safeguards.

Suggested fix
-    AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID || process.env.AWS_ACCESS_KEY,
-    AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY || process.env.AWS_SECRET_KEY,
+    AWS_ACCESS_KEY_ID:
+      process.env.AWS_ACCESS_KEY_ID ?? process.env.AWS_ACCESS_KEY,
+    AWS_SECRET_ACCESS_KEY:
+      process.env.AWS_ACCESS_KEY_ID != null ||
+      process.env.AWS_SECRET_ACCESS_KEY != null
+        ? process.env.AWS_SECRET_ACCESS_KEY
+        : process.env.AWS_SECRET_KEY,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID || process.env.AWS_ACCESS_KEY,
AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY || process.env.AWS_SECRET_KEY,
AWS_ACCESS_KEY_ID:
process.env.AWS_ACCESS_KEY_ID ?? process.env.AWS_ACCESS_KEY,
AWS_SECRET_ACCESS_KEY:
process.env.AWS_ACCESS_KEY_ID != null ||
process.env.AWS_SECRET_ACCESS_KEY != null
? process.env.AWS_SECRET_ACCESS_KEY
: process.env.AWS_SECRET_KEY,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/env.js` around lines 102 - 103, The current fallback uses
independent || for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY which can mix
standard and legacy values; update the logic so the code selects either the
standard pair (AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY) or, only if both are
absent, the legacy pair (AWS_ACCESS_KEY + AWS_SECRET) as a unit. In practice
change the assignment for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to a small
conditional that prefers the standard env vars together, otherwise uses the
legacy pair only when both legacy vars exist, and yields undefined/null if
neither full pair is present; reference the AWS_ACCESS_KEY_ID and
AWS_SECRET_ACCESS_KEY symbols when locating where to implement this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nah thats fine, we should give responsibilty to users

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KMKoushik, understood — the independent fallback is intentional, and the partial-config guard in getAwsCredentialOptions in credentials.ts will still catch the case where only one standard key is set at runtime. Acknowledged!

(ᵔ ᵕ ᵔ) 🐇


✏️ Learnings added
Learnt from: KMKoushik
Repo: usesend/useSend PR: 401
File: apps/web/src/env.js:102-103
Timestamp: 2026-05-17T11:17:08.286Z
Learning: In `apps/web/src/env.js` (usesend/useSend), the independent `||` fallback for `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` (falling back to legacy `AWS_ACCESS_KEY`/`AWS_SECRET_KEY` respectively) is intentional. The project maintainer explicitly chose to give users responsibility for providing consistent credential pairs rather than enforcing paired fallback logic at the env layer. The partial-config guard is handled at runtime in `apps/web/src/server/aws/credentials.ts` via `getAwsCredentialOptions()`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread apps/web/src/server/aws/ses.ts Outdated
Comment thread apps/web/src/server/aws/sns.ts Outdated

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@KMKoushik
KMKoushik merged commit 04d0f4b into main May 17, 2026
7 checks passed
@KMKoushik
KMKoushik deleted the fix/aws-env-vars-on-pr-395 branch May 17, 2026 11:23
@coderabbitai coderabbitai Bot mentioned this pull request Jul 31, 2026
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.

Feat: Avoid hardcoding AWS credentials & support standard AWS env variables

2 participants