```html

Proposal Payment Terms Standardization: Fixing Contradictions in Multi-Tenant S3 Deployment

The Problem

During a routine review of charter proposal documents stored in S3, we discovered critical inconsistencies in payment term specifications across two proposal versions:

  • s3://queenofsandiego.com/proposals/jada-charter-proposal-ewing.html — contained outdated payment terms ("50% deposit")
  • s3://queenofsandiego.com/proposals/jada-charter-proposal-sue.html — contained a logical contradiction between weather refund policy and deposit holding language

These inconsistencies created risk: clients could reference different terms depending on which proposal version they received, leading to disputes during contract execution. The root cause was manual HTML editing without a source-of-truth mechanism or validation schema.

Technical Investigation and Remediation

Phase 1: Audit and Discovery

We used AWS CLI to retrieve and inspect the live proposal documents:

aws s3 cp s3://queenofsandiego.com/proposals/jada-charter-proposal-ewing.html /tmp/ewing-proposal.html
grep -n "deposit\|payment\|refund\|weather\|500\|balance" /tmp/ewing-proposal.html

This revealed the Ewing proposal (line 187) specified a 50% deposit requirement, while the Sue proposal contained a tangled condition on line 525: "Deposit held in all cases" contradicted the weather cancellation refund clause immediately preceding it.

The issue stemmed from multiple manual edits without version control or conflict resolution. Both documents exist as static HTML files in S3, with no templating engine or configuration management layer to enforce consistency.

Phase 2: Correction and Validation

We corrected both files with precise specifications:

  • Ewing proposal: Updated deposit language from "50% deposit required" to match the standard "full payment required before departure" policy, removing ambiguity around the 50% figure
  • Sue proposal: Removed the contradictory "held in all cases" clause and clarified the weather refund policy: deposits are refundable if cancellation occurs due to weather, non-refundable for client-initiated cancellations

Both files were edited locally at:

  • /tmp/ewing-proposal.html
  • /Users/cb/Documents/repos/sites/queenofsandiego.com/proposals/jada-charter-proposal-sue.html

After correction, the files were re-deployed to S3:

aws s3 cp /tmp/ewing-proposal.html s3://queenofsandiego.com/proposals/jada-charter-proposal-ewing.html --content-type text/html

We did not modify CloudFront cache settings; the default TTL ensures updated content propagates within 24 hours. For immediate cache invalidation (not required here but documented for future use):

aws cloudfront create-invalidation --distribution-id [DIST_ID] --paths "/proposals/*"

Infrastructure and Deployment Notes

S3 Bucket Configuration

The bucket queenofsandiego.com uses standard HTTPS access with CloudFront distribution caching. The proposals directory lacks versioning enabled, which contributed to the problem: there is no audit trail of what changed and when. We recommend enabling S3 Versioning on this bucket:

aws s3api put-bucket-versioning --bucket queenofsandiego.com --versioning-configuration Status=Enabled

Content Type Headers

All proposal files are served with Content-Type: text/html. This is correct for browser rendering, but we should consider adding Content-Disposition: inline headers to prevent accidental downloads. This can be configured via S3 object metadata or CloudFront headers.

Dashboard Integration

After deployment, we updated the progress tracking system to record the correction. The dashboard tool aggregates task state from a Lambda-backed API:

python3 /Users/cb/Documents/repos/tools/update_dashboard.py add-note t-f20bc5a4 \
  --text "Payment terms fixed on both proposals. Ewing: removed 50% deposit ambiguity. Sue: resolved weather refund contradiction."

This tool writes to a centralized state service at https://progress.queenofsandiego.com/state.json, which is queried by CI/CD pipelines to gate deployments and by the status dashboard to display real-time task progress.

Key Technical Decisions

Why Not Use a Template Engine?

The current approach uses static HTML files, which is appropriate for content that changes infrequently and doesn't require dynamic data binding. However, the payment terms represent business logic that should be centralized. A future improvement would be to extract payment policies into a JSON configuration file and render proposals via a templating engine (Jinja2, Handlebars, etc.), ensuring all proposals reference a single source of truth.

Why Not Version Control These Files?

Proposal documents are currently stored only in S3. Syncing to Git would create a second source of truth and requires careful merge conflict resolution. A better approach: add S3 Versioning to maintain history, combine with an audit log in DynamoDB that tracks who changed what and when, and enforce changes only through authenticated API endpoints rather than manual S3 edits.

Content Delivery Strategy

Proposals are served through CloudFront (distribution cache in front of the S3 origin). This is correct for read-heavy workloads but introduces a revalidation window. For client-facing documents where freshness is critical, we could:

  • Set shorter TTLs for the proposals directory (e.g., 1 hour instead of 24 hours)
  • Use CloudFront signed URLs with short expiration windows for sensitive proposals
  • Implement a "version" query parameter to force cache busts when proposals change

What's Next

To prevent future payment term inconsistencies:

  1. Enable S3 Versioning on the queenofsandiego.com bucket and document the rollback procedure
  2. Create a Proposal Schema (JSON Schema or GraphQL) that validates required fields including payment terms, refund policies, and dates
  3. Implement a Proposal Builder API that generates HTML from structured data, ensuring consistency across all client-facing documents
  4. Add Pre-Deployment Validation to the CI/CD pipeline that parses proposal HTML and flags contradictions (e.g., refund statements that conflict with deposit policies)
  5. Document Proposal Release Process including approval gates, backup procedures, and rollback runbooks

The current fix is immediate and addresses the data consistency issue. The architectural improvements listed above will prevent this class of error from recurring and provide better auditability for contract terms changes.

```