Skip to content

Release staging to main: v1.0 artifacts, billing overage, Compose Redis/SMTP#662

Open
jaeyunha wants to merge 16 commits into
mainfrom
release/staging-main-20260618
Open

Release staging to main: v1.0 artifacts, billing overage, Compose Redis/SMTP#662
jaeyunha wants to merge 16 commits into
mainfrom
release/staging-main-20260618

Conversation

@jaeyunha

@jaeyunha jaeyunha commented Jun 18, 2026

Copy link
Copy Markdown
Member

Release package: staging → main (2026-06-18 refresh after #664)

Promote the current origin/staging release set into main after release authorization.

Do not merge until Jaeyun explicitly authorizes main promotion/deploy. This PR is the prepared release package only.

Live ref verification

Raw commit inventory (origin/main..origin/staging)

a249776c80949f40e6e7c7924d9093efac67384b	Merge pull request #664 from namuh-eng/issue-642-v1-release
e142672749b93ba70abf0baeb608821c0a129ed5	Update deploy test for pinned compose images
b28f0f00ab7f9baf973a2793d4caff5c1d180a53	Pin self-host compose to release images
64d334029d31eed4b4f5a2287e051b7055176796	Prepare v1.0.0 release artifacts
a2e6c107d7c2f8b316f83e960f2304c17c141b26	Complete Compose Redis and SMTP relay stack (#663)
34cc90d6c6f4db0bd7721082fc73f304ca393704	Implement metered overage billing (#661)

Release branch inventory (origin/main..release/staging-main-20260618)

42dc7623351f5aeb0871d20449fa06763e7c70fb	Merge origin/main into release staging-main 20260618
a249776c80949f40e6e7c7924d9093efac67384b	Merge pull request #664 from namuh-eng/issue-642-v1-release
e142672749b93ba70abf0baeb608821c0a129ed5	Update deploy test for pinned compose images
b28f0f00ab7f9baf973a2793d4caff5c1d180a53	Pin self-host compose to release images
64d334029d31eed4b4f5a2287e051b7055176796	Prepare v1.0.0 release artifacts
a2e6c107d7c2f8b316f83e960f2304c17c141b26	Complete Compose Redis and SMTP relay stack (#663)
34cc90d6c6f4db0bd7721082fc73f304ca393704	Implement metered overage billing (#661)

Upstream staging source PRs:

Conflict resolution applied

GitHub reported the stale release branch as DIRTY. I resolved the real origin/main conflicts on the release branch without merging to main:

  • Preserved current main Lite/51k pricing changes and combined them with staging's $0.85/1k overage language.
  • Preserved main's 0037_lite_tier_and_quota_20260617 data migration.
  • Renumbered staging's overage schema migration from 0037_real_hawkeye to 0038_real_hawkeye and updated the Drizzle journal/snapshot path accordingly.
  • Kept current main import-CSV/dashboard/learnings state through the merge parent, while retaining all staging release content.

Changed surfaces reviewed

  • v1.0.0 release artifacts (Prepare v1.0.0 release artifacts #664)
    • Root, @opensend/core, and @opensend/ingester versions set to 1.0.0.
    • Adds docs/release-notes/v1.0.0.md and release version sync tooling/tests.
    • Updates .github/workflows/release.yml for tag-gated version/notes checks, multi-arch GHCR image publication, manifest inspection, and GitHub Release creation after image publication succeeds.
    • Pins default self-host Compose services to versioned GHCR images and adds docker-compose.local.yml for source-build local development.
  • Compose / self-hosting / SMTP relay (Complete Compose Redis and SMTP relay stack #663)
    • Redis-backed Compose stack, SMTP relay stack, env examples, and startup guardrails.
    • Self-hosting, security, SMTP, ingester deploy, and README docs refreshed.
  • Billing / Stripe / quota (Implement metered overage billing #661)
    • Metered overage billing, usage quota behavior, Stripe webhook handling, billing summary, and ingester overage reporting job.
    • Free remains hard-capped; paid plans soft-cap included emails with $0.85 per 1,000 overage.
  • Schema / migrations
    • Main's 0037_lite_tier_and_quota_20260617 retained.
    • Staging overage schema migration is now 0038_real_hawkeye on this release branch.

Validation evidence

  • ✅ Exact staging-head CI passed before branch refresh:
  • ✅ Release PR-head CI passed after conflict resolution:
    • Run: https://github.com/namuh-eng/opensend/actions/runs/27762392360
    • Workflow/event: CI / pull_request
    • Head SHA: 42dc7623351f5aeb0871d20449fa06763e7c70fb
    • Conclusion: success
    • Jobs successful: Typecheck (full project), Lint (change-scoped), Unit tests (Vitest), Migration parity (prod migrator path), Onboarding acceptance, PHP SDK tests, JVM SDK tests.
  • ✅ PR policy checks passed:
  • ✅ Local validation in this worktree:
    • git diff --check passed.
    • git diff --cached --check passed before conflict-resolution commit.
    • make check passed: full-project typecheck + Biome check of 811 files.
    • node tools/verify-release-version-sync.mjs --tag v1.0.0 --require-release-notes passed.
    • bunx vitest run tests/release-version-sync.test.ts tests/deploy.test.ts tests/security-startup-checks.test.ts tests/billing-schema.test.ts tests/billing-plans-page.test.tsx tests/pricing-grid.test.tsx passed: 6 files, 48 tests.
    • bun run docs:check passed: 216 docs pages.
    • ruby -e 'require "yaml"; ARGV.each { |f| YAML.load_file(f); puts "YAML OK #{f}" }' .github/workflows/release.yml docker-compose.yml docker-compose.local.yml passed.
    • docker compose --env-file .env.example config --quiet passed.
    • docker compose --env-file .env.example -f docker-compose.yml -f docker-compose.local.yml config --quiet passed.
    • Push guardrails passed twice: changed-file guardrails, full-project typecheck, and change-scoped Biome lint.

Caveats / not validated in this refresh session

  • No browser or Playwright E2E proof was run in this release refresh session.
  • No live Stripe Checkout, Stripe API, or Stripe Meter Event call was run.
  • No live SMTP relay send or external SMTP delivery proof was run.
  • No Docker image build/push was run during this refresh.
  • This PR does not push v1.0.0, create a GitHub Release, publish GHCR images, merge to main, deploy production, or authorize Stripe/SMTP cutover.

Jaeyun authorization gate

Merge/main promotion/deploy gate: Jaeyun must explicitly authorize merging this staging→main release PR and any subsequent deploy/cutover.

* Implement metered overage billing

* Fix metered overage billing follow-up
@jaeyunha

Copy link
Copy Markdown
Member Author

Release-readiness refresh — 2026-06-18

Release package prepared for current staging head, but not merge-ready yet because GitHub reports conflicts against main.

Verified live refs / PR shape

  • origin/main: 5f16631975efa211400dfda56b700746bb0d5083
  • origin/staging: 34cc90d6c6f4db0bd7721082fc73f304ca393704
  • This PR head: release/staging-main-20260618 at 34cc90d6c6f4db0bd7721082fc73f304ca393704
  • Base: main
  • Open base:main PRs were rechecked before creating this PR: Finish the audience surface: wire dead controls + session auth #660 existed but is feat/audience-dead-controls, not the release PR.

Raw commit inventory

34cc90d6c6f4db0bd7721082fc73f304ca393704	Implement metered overage billing (#661)

Validation evidence

  • Exact staging CI succeeded for 34cc90d6c6f4db0bd7721082fc73f304ca393704: https://github.com/namuh-eng/opensend/actions/runs/27744535867
    • Typecheck, change-scoped lint, Vitest unit tests, migration parity, onboarding acceptance, PHP SDK tests, and JVM SDK tests all passed.
  • PR checks visible on this PR are green:
    • PR Base Guidance, PR Size Label, Draft Check passed.
    • Existing exact-head CI checks are green on the same SHA.
  • Local validation in release worktree:
    • git diff --check origin/main..origin/staging passed.
    • Release-scope sanity over billing/schema/ingester/docs passed: overage schema symbols are present in both schema copies, migration 0037_real_hawkeye is in the journal with SQL/snapshot files present, and /jobs/billing-overage scheduler/ingester references are wired.
    • make check && make test passed after bun install repaired declared worktree dependencies: typecheck passed, Biome passed, Vitest passed with 212 files passed / 3 skipped and 1,732 tests passed / 10 skipped.

Mergeability blocker

GitHub reports mergeStateStatus=DIRTY for this PR. Read-only git merge-tree origin/main origin/staging reports conflicts in:

drizzle/meta/_journal.json
public/docs/knowledge-base/quotas-rate-limits-production-access.md
src/components/landing/pricing-page.tsx

No conflict-resolution branch update was pushed because main promotion / merge work requires explicit Jaeyun authorization.

Caveats

  • No live Stripe Checkout/API call or Stripe Meter Event call was run in this release prep session.
  • No browser/Playwright E2E proof was run in this release prep session.
  • This PR must not be merged/promoted/deployed until Jaeyun explicitly authorizes that next step, including how to handle the current conflicts.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 34cc90d6c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +88 to +90
5. Update `plans.stripe_price_id` and `plans.stripe_overage_price_id` for the
matching paid public `plans.slug` rows.
6. Run `bun run billing:preflight -- --check-db --strict` against the hosted DB.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Backfill existing Stripe subscriptions before soft caps

For existing paid subscribers created before this release, the old checkout path created Stripe subscriptions with only the base stripe_price_id; this cutover step only updates local plans rows, while the new checkout code attaches the metered Price only for future checkouts. In a staging→main cutover, those existing subscribers become soft-capped in OpenSend but still lack a metered Stripe subscription item to invoice the reported meter usage, so the runbook needs an explicit backfill/update of active Stripe subscriptions before enabling overage sends.

Useful? React with 👍 / 👎.

Comment thread src/lib/billing/quota.ts
Comment on lines +223 to +225
const quotaPredicate = hardCapEmails
? sql`${usagePeriods.emailsSent} + ${delta} <= ${limit}`
: sql`true`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep caps until overage billing is configured

When BILLING_BACKEND=stripe is deployed before every existing paid plan has a non-empty stripe_overage_price_id populated (the migration leaves the new column nullable), this sqltrue`` branch removes the monthly cap for paid subscribers anyway, while /jobs/billing-overage only scans plans with an overage price and therefore skips null configurations. That lets existing paid accounts send unlimited over quota without any billable overage; keep the hard cap unless the plan is actually overage-configured, and mirror the same guard in the core `usageQuota` path.

Useful? React with 👍 / 👎.

@jaeyunha

Copy link
Copy Markdown
Member Author

Release package refresh needed

staging advanced after this release PR was opened.

Live refs now:

Validation evidence for newest staging head:

Current classification: release PR #662 is stale/DIRTY and its body does not include #663 or a2e6c107.... It needs the existing release-prep lane/branch refreshed to current origin/staging; main merge/deploy remains Jaeyun-gated after refresh.

@jaeyunha jaeyunha changed the title Release staging to main: metered overage billing Release staging to main: billing overage + Compose Redis/SMTP Jun 18, 2026
@jaeyunha

Copy link
Copy Markdown
Member Author

Release refresh complete for existing PR #662 (no duplicate PR created).

  • Old release head: 34cc90d6c6f4db0bd7721082fc73f304ca393704
  • New release head: a2e6c107d7c2f8b316f83e960f2304c17c141b26 (matches current origin/staging exactly)
  • Inventory now covered: Complete Compose Redis and SMTP relay stack #663 Complete Compose Redis and SMTP relay stack + Implement metered overage billing #661 Implement metered overage billing
  • Exact staging-head CI is green: https://github.com/namuh-eng/opensend/actions/runs/27750980996
  • Local validation passed: git diff --check origin/main..HEAD, make check, targeted Vitest for billing/Stripe/ingester scheduler/startup/deploy surfaces (6 files, 60 tests), and docker compose config with dummy required interpolation env.
  • Caveats: no browser/E2E, live Stripe, or live SMTP proof was run in this refresh session.

Remaining gate: main merge/deploy/cutover still requires explicit Jaeyun authorization. Do not merge until that approval is given.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a2e6c107d7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +411 to +415
status: "failed",
lastError: truncateError(input.error),
updatedAt: input.now,
})
.where(eq(billingOverageReports.id, input.report.id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard stale failures from overwriting reported rows

When a Stripe call outlives REPORT_LEASE_MS, another scheduler run can reclaim the same sending row and successfully mark it reported. If the original attempt then errors, this update matches only by id and changes that already reported row back to failed, so a later scan retries the already reported range before moving on to new overage. Add a status/lease/attempt guard (or claim token) before setting failed.

Useful? React with 👍 / 👎.

jaeyunha added 5 commits June 18, 2026 20:09
# Conflicts:
#	drizzle/meta/_journal.json
#	public/docs/knowledge-base/quotas-rate-limits-production-access.md
#	src/components/landing/pricing-page.tsx
@jaeyunha jaeyunha changed the title Release staging to main: billing overage + Compose Redis/SMTP Release staging to main: v1.0 artifacts, billing overage, Compose Redis/SMTP Jun 18, 2026
@jaeyunha

Copy link
Copy Markdown
Member Author

Refreshed PR #662 after #664 merged.

  • Release branch now: 42dc7623351f5aeb0871d20449fa06763e7c70fb
  • Included staging head: a249776c80949f40e6e7c7924d9093efac67384b
  • Base main: 5f16631975efa211400dfda56b700746bb0d5083
  • Resolved prior DIRTY conflicts by merging origin/main into the release branch, preserving main's Lite/51k pricing and renumbering staging's overage migration to 0038_real_hawkeye after main's 0037_lite_tier_and_quota_20260617.

Validation:

No v1.0.0 tag pushed, no GitHub Release created, no GHCR images published, and no merge/deploy performed. Main promotion/deploy remains gated on explicit Jaeyun authorization.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42dc762335

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docker-compose.yml
build:
context: .
target: runner
image: ghcr.io/namuh-eng/opensend:v1.0.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep Compose source-built until GHCR tags are live

If this release PR is merged before the v1.0.0 tag workflow has successfully pushed the GHCR images, the documented default docker compose up -d path will fail while pulling ghcr.io/namuh-eng/opensend:v1.0.0 instead of building from the checked-out source; the new workflow only publishes these tags on a later v* tag event, so keep the default source-built (or otherwise gate this switch on already-published artifacts) until those images are guaranteed to exist.

Useful? React with 👍 / 👎.

@jaeyunha

Copy link
Copy Markdown
Member Author

Refreshed existing staging→main release PR after #665 landed on staging.

Live refs at refresh:

  • origin/main: 5f16631975efa211400dfda56b700746bb0d5083
  • origin/staging: 00d13d1a975b64bb58e46fb9d7ee3ec44ffbabf6
  • Release branch head: b1cfdda5a9e1995f9c2f2797c00b4eb7e2b32a90

New staging content included since prior refresh:

Validation run on refreshed release worktree:

  • git diff --check origin/main..HEAD
  • targeted Vitest: tests/env-bootstrap.test.ts, tests/security-startup-checks.test.ts, tests/ingester-startup-checks.test.ts, tests/ingester-job-scheduler-coverage.test.ts, tests/deploy.test.ts, tests/release-version-sync.test.ts → 47 tests passed
  • bun run setup -- --yes --output <temp> --force completed without printing generated secret assignments
  • docker compose --env-file .env.example config --quiet
  • push guardrails ran during push: full-project typecheck passed; changed-file Biome lint passed

No browser/E2E, live Stripe, live SMTP, GHCR publish, tag, release, main merge, or deploy was performed in this refresh.

Remaining gate: main merge/deploy/cutover still requires explicit Jaeyun authorization. Do not merge until that approval is given.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b1cfdda5a9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

try {
await input.stripe.billing.meterEvents.create(
{
event_name: input.meterEventName,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reuse the stored meter name when retrying reports

When a billing_overage_reports row is retried after STRIPE_OVERAGE_METER_EVENT_NAME changes, this sends the old reportKey/idempotency key to the new meter because the persisted meterEventName is ignored. In that configuration-change scenario Stripe can reject the idempotency replay as different parameters, or the usage can land on the wrong meter, leaving the outbox stuck or usage unbilled; include the row's meterEventName in the claimed report and use it for the retry.

Useful? React with 👍 / 👎.

Comment thread src/lib/env/setup.ts
}

await mkdir(path.dirname(outputPath), { recursive: true });
await writeFile(outputPath, renderOpenSendEnvFile(env), { mode: 0o600 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Tighten permissions when overwriting generated env files

When users run bun run setup -- --force against an existing .env, writeFile(..., { mode: 0o600 }) does not change the permissions of an already-created file, so a previously copied or editor-created 0644 .env remains readable after the command writes fresh database/auth/DKIM secrets. Explicitly chmod the output after writing, or write a new temp file with restrictive permissions and rename it.

Useful? React with 👍 / 👎.

jaeyunha added 5 commits June 19, 2026 09:11
Adds production CloudWatch alarm manifesting, alerting runbook/docs, and alarm-friendly EMF metrics for queue publish, scheduler, worker, SES ingest, ECS, ALB, and DLQ coverage. Validated with PR CI plus targeted maintainer QA.
* Add deploy fallback runbook preflight

* Fix deploy fallback preflight review comments

* Fix deploy fallback preflight secret coverage

* Check Docker ECR auth in deploy fallback preflight

* Check ECS task definitions in deploy fallback preflight

* Fix deploy fallback preflight contract

* Validate scheduler base secrets in fallback preflight

* fix: require app database metadata in deploy preflight

* Fix fallback preflight Bun prerequisite

* Tighten ingester fallback preflight metadata

* fix deploy fallback app metadata preflight

* Require active ECS services in deploy preflight

* fix deploy fallback preflight blockers
* Add DB polling fallback for queued sends

* Fix scheduled SQS claim race

* Align DB polling fallback e2e status
@jaeyunha

jaeyunha commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

Release PR #662 refresh evidence — 2026-06-19

Refs

Raw origin/main..origin/staging inventory (13 commits)

34cc90d Implement metered overage billing (#661)
a2e6c10 Complete Compose Redis and SMTP relay stack (#663)
64d3340 Prepare v1.0.0 release artifacts
b28f0f0 Pin self-host compose to release images
e142672 Update deploy test for pinned compose images
a249776 Merge pull request #664 from namuh-eng/issue-642-v1-release
523e9ce Add secrets bootstrap and env preflight
058db29 Fix generated env scheduler ingester URL
00d13d1 Merge pull request #665 from namuh-eng/issue-641-secrets-bootstrap
61dc157 Add production CloudWatch alerting (#668)
4990082 Add Resend migration verifier CLI (#669)
6cfbb81 Add deploy fallback runbook preflight (#667)
5f4d855 Fix self-host queued send fallback without SQS (#666)

Raw origin/main..release/staging-main-20260618 inventory (16 commits)

34cc90d Implement metered overage billing (#661)
a2e6c10 Complete Compose Redis and SMTP relay stack (#663)
64d3340 Prepare v1.0.0 release artifacts
b28f0f0 Pin self-host compose to release images
e142672 Update deploy test for pinned compose images
a249776 Merge pull request #664 from namuh-eng/issue-642-v1-release
42dc762 Merge origin/main into release staging-main 20260618
523e9ce Add secrets bootstrap and env preflight
058db29 Fix generated env scheduler ingester URL
00d13d1 Merge pull request #665 from namuh-eng/issue-641-secrets-bootstrap
b1cfdda Merge remote-tracking branch 'origin/staging' into release/staging-main-20260618
61dc157 Add production CloudWatch alerting (#668)
4990082 Add Resend migration verifier CLI (#669)
6cfbb81 Add deploy fallback runbook preflight (#667)
5f4d855 Fix self-host queued send fallback without SQS (#666)
ab83fee Merge remote-tracking branch 'origin/staging' into release/staging-main-20260618

Refresh action

  • Fetched: origin main staging release/staging-main-20260618.
  • Merged origin/staging into release/staging-main-20260618 only. Did not merge main during this refresh.
  • Merge completed cleanly; no conflict edits were required.

Local validation

  • bun install --ignore-scripts — checked 724 installs across 906 packages; no changes.
  • git diff --check origin/main..origin/staging — passed.
  • git diff --check origin/main..HEAD — passed.
  • make check — TypeScript passed; Biome checked 835 files.
  • make test — 216 test files passed, 3 skipped; 1,785 tests passed, 10 skipped.
  • bun run build — production build completed. Caveat: emitted existing Next 16 warnings for invalid experimental.nodeMiddleware/middleware convention and Better Auth default-secret warnings during static page collection.
  • ⚠️ Targeted Playwright attempted: bunx playwright test tests/e2e/compose-db-polling-fallback.spec.ts. First run skipped because this worktree has no .env; rerun against the canonical checkout's local localhost:5432/opensend env failed before exercising the scenario because Postgres rejected local credentials for user opensend. This is not counted as E2E proof. Full E2E/browser sweep not claimed.
  • Push hook also ran: change-scoped push guardrails, full-project typecheck, and changed-file Biome lint; all passed.

Current GitHub PR state after push

  • PR head verified via GitHub: ab83fee6720a3b58166f7071ec7c8accd9273be7.
  • Merge state at final verification: BLOCKED / review required.
  • Remote CI at final verification: ✅ all observed checks completed successfully — Typecheck, Lint, Unit tests, Migration parity, PHP SDK tests, JVM SDK tests, Onboarding acceptance, PR Base Guidance, PR Size Label, Draft Check.

Caveats / gate

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab83fee672

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

await emailRepo.update(email.id, { status: "processing" });
const [claimedEmail] = await emailRepo.claimForSending(email.id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reclaim stale processing sends before skipping

When a worker crashes or is restarted after this claim has set the email row to processing but before the retry handler changes it back to queued/failed, the SQS redelivery or DB poller reaches this claim again and finds no queued/due scheduled row. processEmailSend then returns not_claimed, and the SQS path treats that as success and deletes the message, leaving the email permanently processing and never sent; add a processing lease/stale reclaim path or avoid deleting these retries until ownership is resolved.

Useful? React with 👍 / 👎.

Comment thread packages/core/src/env.ts
S3_BUCKET_NAME: external.S3_BUCKET_NAME?.trim() ?? "",
CLOUDFLARE_API_TOKEN: external.CLOUDFLARE_API_TOKEN?.trim() ?? "",
CLOUDFLARE_ZONE_ID: external.CLOUDFLARE_ZONE_ID?.trim() ?? "",
RATE_LIMIT_BACKEND: "disabled",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep generated Compose env on Redis

When users follow the documented quick start (bun run setup then docker compose up), this writes RATE_LIMIT_BACKEND=disabled into .env, and the app service's ${RATE_LIMIT_BACKEND:-redis} default is overridden by that non-empty value. The result is production Compose booting with rate limiting disabled even though the Redis service is started; omit this key from generated setup output or generate the Compose-safe Redis value so the documented path actually uses shared Redis.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant