AWS Service Baseline
Status
Locked first-pass direction for #57.
VRDex uses AWS narrowly for early supporting infrastructure. The current baseline is intentionally small: transactional auth email first, private profile asset storage next, and no broad AWS application platform before the product needs it.
Scope
The first AWS baseline covers:
- Amazon SES for Convex Auth password and email verification messages
- Route 53 DNS records for the SES sender domain
- IAM credentials scoped to SES sending for Convex
- a planned S3 private asset bucket for owner-authored profile assets, tracked by #115
- Terraform state in S3 for checked-in infrastructure stacks
Non-goals for this baseline:
- full production AWS landing zone
- multi-account AWS architecture
- CloudFront image CDN and transformation pipeline
- broad object lifecycle, malware scanning, moderation review, or asset-processing automation
- moving the application runtime from Convex/Vercel to AWS
Email Delivery
Locked decision: use Amazon SES for auth verification and transactional email.
Current hosted baseline:
- AWS account: BASIC BIT hosted production account; provider account IDs stay in provider configuration, Terraform state, or operator records rather than public docs
- SES region:
us-east-1 - sending domain identity:
vrdex.net - sender address:
no-reply@vrdex.net - Route 53 hosted zone:
vrdex.nethosted zone; provider-generated hosted zone IDs stay in provider configuration, Terraform state, or operator records rather than public docs - Terraform stack:
infra/terraform/ses - Terraform state key:
ses/terraform.tfstate
Verified state as of this baseline pass:
- SES identity verification:
Success - Easy DKIM: enabled
- DKIM verification:
Success - Terraform plan against the hosted stack: no changes
- SES send quota:
Max24HourSend=50000,MaxSendRate=14,SentLast24Hours=0
Convex deployments that send email must set:
AWS_SES_REGIONAWS_SES_FROM_EMAILAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYVRDEX_APP_NAMEoptional display name for email copy
The access key is generated by Terraform only when create_iam_access_key=true. Store the secret in Convex or the relevant provider secret store, never in git.
Asset Storage
Locked first-pass direction: use a private Amazon S3 bucket for owner-authored profile assets.
The first asset-storage implementation should use:
- S3 Block Public Access enabled at the bucket level
- server-side encryption; SSE-S3 is acceptable for the first slice because S3 encrypts new object uploads by default
- app-generated presigned upload URLs for controlled browser uploads
- app-generated reads, or a controlled delivery layer owned by #115, instead of public bucket objects
- deterministic object prefixes keyed by environment and asset owner/profile context
- metadata sufficient to connect uploaded objects to profile records, uploader, upload time, and moderation/review state
Do not make profile asset buckets public. Public profile pages should render through a controlled URL path that can enforce profile visibility, moderation suppression, replacement, and deletion behavior.
Deferred follow-on work:
- #115 S3 bucket Terraform/runtime baseline
- Convex asset metadata schema
- presigned upload endpoint/mutation
- image validation and size limits
- moderation or malware scanning
- CloudFront or image optimization
- lifecycle rules and deletion/retention policy
Candidate environment/config names for #115:
AWS_ASSET_REGIONAWS_ASSET_BUCKETAWS_ASSET_UPLOAD_ROLE_ARNor a narrow access key only if the runtime cannot use role-based authVRDEX_ASSET_PUBLIC_BASE_URLonly after a controlled public delivery layer exists
Terraform State
Terraform stacks use the S3 backend bucket vrdex-terraform-state in us-east-1 with stack-specific state keys and S3 native locking.
Current stacks:
infra/terraform/state-mgmt: local-state bootstrap stack for the shared S3 Terraform state bucketinfra/terraform/ses: SES domain identity, DKIM, MAIL FROM, Route 53 records, and optional IAM sender keyinfra/terraform/posthog: hosted PostHog project metadatainfra/terraform/vercel: hosted Vercel PostHog client environment variablesinfra/terraform/docs-site: hosted docs Vercel project/domain and Route 53 DNS
Keep stack state, plans, local provider caches, and terraform.tfvars uncommitted.
Self-Hosting Boundary
Self-hosted AWS usage is limited to the values this repo documents by name: SES sender identity, DNS zone, Terraform state location, and the S3 asset bucket tracked by #115.
This baseline does not claim complete self-hosting support. Alternative S3-compatible stores are out of scope until #115 creates the first asset abstraction and a follow-up issue or ADR covers provider portability.