Repository navigation
Carry release, SES, S3 and database name fixes into redesign main (#746) - #635
Merged
Merged
Conversation
* Guard Terraform web service updates before apply * Guard Terraform web service replacement and deletion (cherry picked from commit 7a1e26a)
(cherry picked from commit 498015a)
* Add SES identities, DNS, and delivery infrastructure * Add SES sender and signed SNS event handling * Classify SES webhook and clarify email contract * Fix SES cutover controls and webhook verification * Extract shared email composition for SES and Resend * Isolate staging SES events and sender credentials * Escape interpolated names in the SES isolation test patterns CodeQL js/incomplete-hostname-regexp flagged the tuple values flowing into new RegExp; every interpolated value is now escaped as a literal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit f770b47)
* Add staging keepalive and database reseed lifecycle * Document and strengthen staging seed command * Keep Terraform plan details out of workflow logs * Require successful health responses in staging workflows * Parse Render creation time portably * Isolate staging database state and gate reseed on deploy * Read the staging database id from the main state before moving it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Correlate staging reseed deploy with live commit --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit ee40ae9)
(cherry picked from commit 65d355f)
* Add configurable S3 upload signing * Provision private S3 upload buckets and scoped credentials * Expose storage provider cutover as Terraform variables * Add stable read redirects for private S3 uploads * Map public upload reads in agent catalog * Fix upload read validation and S3 bucket safeguards * Keep S3 upload reads available across provider rollback * Bound anonymous upload reads per client IP (cherry picked from commit 395239f)
* fix: derive Render database names from connection URLs * Generate the staging database name pattern with a match timeout SonarCloud S6444 and SYSLIB1045 on the seed target check: the pattern is now a GeneratedRegex with a one second timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 0fd416f)
There was a problem hiding this comment.
Important
The SES event path can permanently lose valid bounce and complaint notifications during transient certificate failures or an API outage. Please address both delivery paths before enabling SES.
Reviewed changes Carried release automation, staging database lifecycle, DNS and Terraform guards, SES delivery and event handling, S3 upload storage, the email composer integration, and their tests into redesign/main.
- Releases and infrastructure: Manual production and staging Render releases, a web service plan guard, apex DNS cutover, staging keepalive and reseed, and database connection name fixes.
- Email: SES identities, credentials and event routing, signed SNS processing and marketing suppression, with shared composition for the SES and Resend providers.
- Uploads: Private S3 uploads and stable API read redirects alongside the existing Supabase write path, plus provider configuration and focused tests.
- Redesign carry: Historical habit seed guards, bilingual error copy, OpenAPI output and gating matrix regeneration.
GPT Sol | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes Re-reviewed the SES event recovery changes in 80d8e7d7 against the full PR diff.
- Retryable verification: Distinguished temporary SNS certificate fetch failures from invalid messages and returned HTTP 503 for the former, with focused tests for HTTP, transport, and timeout failures.
- Recoverable delivery: Added separate encrypted SQS dead-letter queues and SNS redrive policies for production and staging, plus a documented replay procedure and Terraform checks.
GPT Sol | 𝕏
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Refs thomasluizon/orbit-tickets#746. This is the standing API sync ticket; keep it open.
Change
Carry the seven specified main fixes into
redesign/mainby cherry-pick with source references:7a1e26a9(Guard web service Terraform plans before apply #631), web service Terraform plan guard, was already on this branch asd45b4d98. It applied without conflict.498015ae(Add manual API release workflow for production and staging #632), manual production and staging release workflow, was already on this branch asb72cea41. It applied without conflict.f770b47f(Add Amazon SES delivery and signed event handling #628), SES delivery and signed events, is48baf3f6. Resolved the two email service conflicts described below.ee40ae9c(Keep staging awake and reseed its free database #626), staging keepalive and reseed, isfa40bf05. It applied without conflict.65d355fc(Point apex DNS at Render landing site #634), apex DNS, is6a9572d6. It applied without conflict.395239fe(Move uploads to private S3 with stable read links #625), private S3 uploads and stable read links, isd01042ad. It applied without conflict.0fd416fd(Fix Render database names in API connection strings #633), Render database names, isfd9390ce. It applied without conflict, including theStagingSeedCommandgenerated regex.The followup
0ab1112dadds the redesign error copy required by the carried staging habit guard and regeneratesgating-matrix.json.src/Orbit.Api/openapi.jsonwas regenerated by the API build after the picks. EF reports no pending model changes; these picks add no migration. There is no migration ordering question.Conflict resolution
src/Orbit.Infrastructure/Services/ResendEmailService.cs: kept main's sharedEmailServiceBaseextraction so SES and Resend use one composer, while retaining the redesign subject copy, HTML layout, marketing styling, support labels, Resend retry behavior, unsubscribe headers, and test account handling inEmailMessageComposerand the provider service.tests/Orbit.Infrastructure.Tests/Services/ResendEmailServiceTests.cs: retained the full redesign suite, including localized copy, plain text, HTML escaping, and layout checks. The main provider and composer cases remain covered by the newEmailMessageComposerTestsandSesEmailServiceTests; their subject expectations now match the redesign copy. No test behavior was dropped.Test evidence
env -u LANG LC_ALL=en_US.UTF-8 dotnet build Orbit.slnx --verbosity quiet: exit 0, zero errors.env -u LANG -u LC_ALL dotnet test --verbosity quiet: exit 0, 7,995 passed.env -u LANG LC_ALL=en_US.UTF-8 dotnet test --verbosity quiet: exit 0, 7,995 passed.terraform fmt -check -recursive infra: exit 0. After backendless provider initialization,terraform -chdir=infra validate -no-colorandterraform -chdir=infra/staging-database validate -no-color: exit 0.dotnet ef migrations has-pending-model-changes --project src/Orbit.Infrastructure --startup-project src/Orbit.Api: exit 0, no pending model changes.node --test infra/check-web-plan.test.mjs infra/ses-isolation.test.mjs: 9 passed. Focused email and event tests: 62 passed. Focused S3 and staging tests: 25 passed.node tools/arch-map.mjs: 198 endpoints, zero orphan endpoints, zero untested feature folders.node tools/gating-matrix.mjsregenerated the tracked matrix.ErrorCopyTests.EveryDomainErrorConstantHasCopyfailed withINVALID_CREATED_AT_UTCafter the staging carry. After adding its bilingual copy,dotnet test tests/Orbit.Application.Tests --filter 'FullyQualifiedName~ErrorCopyTests'passed all 716 cases. The existing test caught the defect, so no strengthened test was needed.git diff --checkchecks passed.CertificateFetchFailureIsRetryablefailed with the defect present for both HTTP and transport failures: no exception was thrown. After the fix, the focused SES and controller tests passed: 16 passed.dotnet build Orbit.slnx: zero errors in both requested locale settings. Fulldotnet test: 8,001 passed in each setting.External interface evidence
The source PRs record the observed external fields and reproduction commands. Their evidence was checked with
gh pr view <number> --json bodybefore this carry:Manual steps
These carried infrastructure changes retain the activation steps in their source PRs. Before enabling them on redesign deployments:
us-east-2to confirm production access and verifiedsend.useorbit.organdupdates.useorbit.orgidentities. Ininfra/local.tfvars, setproduction_email_providerorstaging_email_providertoSesonly after the reviewed Terraform apply. ConfirmEmail__Provider=Sesin the corresponding Render API Environment Group and a confirmed SNS HTTPS subscription. See #628.RENDER_API_KEYin GitHub Actions Secrets andSEED_OWNER_EMAIL,STAGING_ENVIRONMENT_ID,STAGING_API_SERVICE_ID, andSTAGING_POSTGRES_IP_ALLOW_LISTin GitHub Actions Variables. Complete the documented Terraform state transfer and apply before running Actions > Staging reseed. A successful migration, live deploy, and seed run prove readiness. See #626 and #633.dns_apex_target = "orbit-landing-aaa7.onrender.com"ininfra/local.tfvarsand apply only a reviewed apex plan. Confirm the flattened A answers on both Cloudflare nameservers and the verifieduseorbit.orgcustom domain in Render > orbit-landing > Settings > Custom Domains. See #634.infra/plan, then setproduction_storage_providerorstaging_storage_providertoS3only after the web client dependency is deployed. ConfirmStorage__Provider=S3and theStorage__S3__Bucket,Storage__S3__Region,Storage__S3__PublicBaseUrl,Storage__S3__AccessKeyId, andStorage__S3__SecretAccessKeykeys in Render > Environment Groups. A signed PUT and read throughpublicUrlprove the cutover. See #625.api_database = "render"ininfra/local.tfvarsonly after verifying the production database in Render > Postgres > Connections. Confirm bothConnectionStrings__DefaultConnectionandConnectionStrings__SessionConnectionin the linked Render API environment group name the correct database and that the API remains healthy.infraTerraform plan. In AWS SQS Queues, verifyorbit-ses-events-dead-letterandorbit-ses-events-staging-dead-letter; in SNS Subscriptions, verify each webhook’s redrive policy points to its matching queue.release.yml) for each intended environment. Verify the Renderorbit-apiororbit-api-stagingservice runs that release.production_email_providerorstaging_email_providertoSesininfra/local.tfvars, apply the reviewed plan, and verify the corresponding Render environment hasEmail__Provider=Sesand its signed SNS webhook succeeds.Assumptions