proposal-system/infra
Adam Moussa 1fca0fa978
feat: proposal delivery — email customers the PDF on Mark as Sent (#126)
* feat: proposal delivery — email customers the PDF on "Mark as Sent"

Makes the system's namesake feature real: marking a proposal Sent now emails the
customer an expiring link to the branded PDF, and customers are managed (with
contact emails) instead of hardcoded. v1 PR4.

API:
- Customer.ContactEmail + migration; Customer list/update endpoints. Search stays
  additive at GET /api/customers?query= (frozen-mobile + web compat); new paginated
  list at GET /api/customers/list (admin).
- IEmailService (SesEmailService v2 / DevEmailService, dev-gated). MarkSentAsync
  resolves the customer's email, presigns the latest PDF (7d), and sends via SES.
  Email/presign failures are caught + audited and NEVER roll back the Sent transition.
- Startup EF migration guarded by a Postgres advisory lock (concurrency-safe).

Infra:
- SES email identity (proposals@seahavenind.com); least-privilege ses:SendEmail/
  SendRawEmail scoped to the identity ARN + ses:FromAddress condition; SES_FROM_ADDRESS
  env. SES starts in sandbox — production access needed for unverified recipients.

Web:
- Customer management page (/admin/customers): list / create / edit incl. contact email.
- New-proposal form searches real customers (free-solo) instead of a hardcoded value.
- Mark-as-Sent dialog notes the PDF will be emailed to the customer.

GPT-4.1 cross-review (SES IAM): no BLOCK (ses:FromAddress condition applied).
Verified: api build + 121 tests; web tsc + 26 tests; infra tsc; ruff clean.

* Potential fix for pull request finding 'CodeQL / Exposure of private information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Exposure of private information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Exposure of private information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-06-18 12:40:55 -04:00
..
bin feat(infra): migrate Bedrock KB vector store to Aurora pgvector (#125) 2026-06-12 18:44:42 -04:00
lib feat: proposal delivery — email customers the PDF on Mark as Sent (#126) 2026-06-18 12:40:55 -04:00
cdk.context.json Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model 2026-05-16 18:40:46 -04:00
cdk.json feat(infra): parameterize stacks for multi-env (prod/staging) (#123) 2026-06-12 18:04:53 -04:00
package-lock.json fix(deps): pin aws-cdk-lib to ==2.257.0 (#90) 2026-06-05 13:20:09 -04:00
package.json build(deps-dev): bump aws-cdk from 2.1124.1 to 2.1125.0 in /infra (#71) 2026-05-30 04:33:26 +00:00
tsconfig.json Initial scaffold: monorepo structure, CDK stacks, CI/CD, domain model 2026-05-16 18:40:46 -04:00