```html

Fixing Proposal Payment Terms Across S3 and Local Repos: A Multi-Environment Deployment Pattern

What Was Done

During this session, we identified and corrected payment term discrepancies across two client proposals stored in different environments: one in S3 and one in the local repository. The Jada charter proposals contained conflicting or incorrect deposit requirements that needed to be synchronized before client delivery. This work demonstrates a practical pattern for maintaining consistency across distributed storage systems and testing environments.

The Problem: Environment Drift

We discovered that two versions of the same proposal existed:

  • s3://queenofsandiego.com/proposals/jada-charter-proposal-ewing.html — production-ready file with incorrect "50% deposit" language
  • /Users/cb/Documents/repos/sites/queenofsandiego.com/proposals/jada-charter-proposal-sue.html — local development version with contradictory payment terms (line 525 stated "Deposit held in all cases" while another section referenced weather-based refund logic)

This is a classic problem in proposal management: when proposals are edited across multiple environments without a single source of truth, drift accumulates. The Sue proposal's contradiction between deposit handling and weather refund terms created legal ambiguity—the proposal didn't clearly state whether the deposit was refundable if weather caused cancellation.

Technical Approach

Discovery Phase: We used grep to identify the problematic lines across the local repository:

grep -n "deposit\|payment\|refund\|weather\|500\|balance" \
  /Users/cb/Documents/repos/sites/queenofsandiego.com/proposals/jada-charter-proposal-sue.html

This command surfaced both the contradictory language and the specific line numbers (line 525) where the conflict existed. The grep pattern targeted financial terms that commonly indicate payment obligations.

S3 Sync: We pulled the S3 version locally for comparison and correction:

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

This temporary workspace approach isolates testing from the production bucket, reducing risk of accidental overwrites during the editing phase.

Correction Strategy: Rather than choosing one version as authoritative, we applied the corrected payment terms to both files. The fix clarified that:

  • A specific deposit amount (not percentage-based language like "50% deposit") would be required
  • Refund conditions are explicit and tied to weather cancellation clauses
  • Both files now state identical terms to prevent future confusion

Deployment: The corrected files were redeployed to both locations:

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

The local repository file was updated directly via the text editor. Both versions now serve identical content.

Why This Pattern Matters

Single Source of Truth: Proposals are customer-facing documents. Having two versions with conflicting terms is a business risk. By synchronizing both copies, we eliminated the possibility of sending contradictory documents to the same client.

CloudFront Cache Implications: The S3 bucket sits behind CloudFront distribution for the queenofsandiego.com domain. Once we deployed the corrected HTML to S3, CloudFront's cache needed to recognize the updated object. By explicitly setting the --content-type text/html flag during the S3 copy, we ensured proper MIME typing. CloudFront's cache invalidation depends on ETag changes; since we modified the object content, the ETag automatically updated, triggering a refresh on the next request.

Local-to-S3 Workflow: This session highlights why maintaining a git-backed local repository as the primary editing environment is critical. The local files in /Users/cb/Documents/repos/sites/queenofsandiego.com/ represent the source of truth. S3 becomes the deployment target, not the editing environment. This prevents situations where someone edits directly in S3 (via AWS console, for example) without creating a git commit record.

Dashboard Integration

To ensure visibility across the team, we updated the project dashboard using the custom update tool:

python3 /Users/cb/Documents/repos/tools/update_dashboard.py add-note t-f20bc5a4 \
  --text "Payment terms fixed on both proposals. Sue and Ewing versions now synchronized."

This command writes a timestamped note to the task tracking system, creating an audit trail. The task ID t-f20bc5a4 links the fix to the original work item. Any engineer reviewing the project history can now see exactly when and why the change was made.

Key Decisions

  • Temporary workspace over direct editing: Using /tmp/ewing-proposal.html for S3 content gave us a chance to review and test before re-uploading. This adds one extra step but eliminates the risk of deploying broken HTML.
  • Grep-based discovery over manual inspection: For multi-line documents, targeted grep patterns find inconsistencies faster than reading the full file. The pattern deposit\|payment\|refund\|weather caught both the missing term and the contradiction in one pass.
  • Explicit MIME type on S3 copy: While AWS typically infers MIME types, explicitly setting --content-type text/html ensures downstream systems (CloudFront, browsers) handle the file correctly. This is defensive programming at the deployment level.
  • Both environments corrected, not just one: It would have been faster to only fix S3 or only the local file. But proposals are legal documents. Leaving a contradictory version anywhere creates future confusion. The extra minute to fix both is worth it.

What's Next

The proposals are now deployment-ready and synchronized. Follow-up work includes:

  • Client delivery: The corrected proposals can now be sent to Sue Ewing and Jada without risk of payment term contradictions.
  • Proposal versioning: Consider adding a version number or date to the filename (e.g., jada-charter-proposal-ewing-v2-2025.html) to prevent future confusion between drafts.
  • Source control for proposals: Ensure all proposal HTML files are committed to git with commit messages explaining the payment terms. This creates a historical record and makes diffs clear when terms change.
  • Template extraction: If these proposals share structure, consider extracting a template or base HTML file to DRY out common sections (header, footer, terms). This reduces the number of places payment terms need to be updated.

Repository locations for future reference:

  • Local source: /Users/cb/Documents/repos/sites/queenofsandiego.com/proposals/
  • Production S3: s3://queenofsandiego.com/proposals/
  • CloudFront distribution: Configured for queenofsandiego